From e65c0d44bb881e730df0d3e5a0661b66647fa3b3 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Mon, 15 Dec 2014 16:29:13 +0300 Subject: [PATCH] Reuse JavaPsiFacadeImpl impl for package caching and search in dumb mode + Add filter for packages --- .../resolve/java/JavaClassFinderImpl.java | 6 +- .../lang/resolve/java/JavaPsiFacadeImpl.java | 6 +- .../java/JavaPsiFacadeKotlinHacks.java | 103 ---------- .../lang/resolve/java/KotlinFinderMarker.java | 20 ++ .../resolve/java/KotlinJavaPsiFacade.java | 192 ++++++++++++++++++ .../jet/asJava/JavaElementFinder.java | 4 +- 6 files changed, 221 insertions(+), 110 deletions(-) delete mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPsiFacadeKotlinHacks.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/KotlinFinderMarker.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/KotlinJavaPsiFacade.java diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassFinderImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassFinderImpl.java index b897ccd3d15..c40072e262c 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassFinderImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassFinderImpl.java @@ -41,7 +41,7 @@ public class JavaClassFinderImpl implements JavaClassFinder { private GlobalSearchScope baseScope; private GlobalSearchScope javaSearchScope; - private JavaPsiFacadeKotlinHacks javaFacade; + private KotlinJavaPsiFacade javaFacade; @Inject public void setProject(@NotNull Project project) { @@ -63,7 +63,7 @@ public class JavaClassFinderImpl implements JavaClassFinder { javaSearchScope = new DelegatingGlobalSearchScope(baseScope) { @Override public boolean contains(@NotNull VirtualFile file) { - return myBaseScope.contains(file) && file.getFileType() != JetFileType.INSTANCE; + return myBaseScope.contains(file) && (file.isDirectory() || file.getFileType() != JetFileType.INSTANCE); } //NOTE: expected by class finder to be not null @@ -73,7 +73,7 @@ public class JavaClassFinderImpl implements JavaClassFinder { return project; } }; - javaFacade = new JavaPsiFacadeKotlinHacks(project); + javaFacade = new KotlinJavaPsiFacade(project, javaSearchScope); } @Nullable diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPsiFacadeImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPsiFacadeImpl.java index 9e169a4cbab..160367d649a 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPsiFacadeImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPsiFacadeImpl.java @@ -59,6 +59,8 @@ import java.util.concurrent.ConcurrentMap; /** * Copy idea version of JavaPsiFacadeImpl + * TODO Temporary class until {@link com.intellij.psi.impl.JavaPsiFacadeImpl} hacked. + * @see com.intellij.psi.impl.JavaPsiFacadeImpl */ @SuppressWarnings({"UnnecessaryFinalOnLocalVariableOrParameter", "UnusedDeclaration", "NullableProblems"}) public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { @@ -69,7 +71,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { private final JavaFileManager myFileManager; public JavaPsiFacadeImpl(Project project, - PsiManagerImpl psiManager, + PsiManager psiManager, JavaFileManager javaFileManager, MessageBus bus) { myProject = project; @@ -165,7 +167,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { } @NotNull - private PsiElementFinder[] calcFinders() { + protected PsiElementFinder[] calcFinders() { List elementFinders = new ArrayList(); elementFinders.add(new PsiElementFinderImpl()); ContainerUtil.addAll(elementFinders, myProject.getExtensions(PsiElementFinder.EP_NAME)); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPsiFacadeKotlinHacks.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPsiFacadeKotlinHacks.java deleted file mode 100644 index 62d81062ad9..00000000000 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPsiFacadeKotlinHacks.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.resolve.java; - -import com.google.common.collect.Lists; -import com.intellij.core.CoreJavaFileManager; -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.progress.ProgressIndicatorProvider; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElementFinder; -import com.intellij.psi.PsiPackage; -import com.intellij.psi.impl.JavaPsiFacadeImpl; -import com.intellij.psi.impl.file.impl.JavaFileManager; -import com.intellij.psi.search.GlobalSearchScope; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -/** - * TODO Temporary class until {@link JavaPsiFacadeImpl} hacked. - * - * @see JavaPsiFacadeImpl - */ -public class JavaPsiFacadeKotlinHacks { - public interface KotlinFinderMarker {} - - private final JavaFileManager javaFileManager; - private final List extensionPsiElementFinders; - private final boolean isCoreJavaFileManager; - - public JavaPsiFacadeKotlinHacks(@NotNull Project project) { - this.javaFileManager = findJavaFileManager(project); - this.isCoreJavaFileManager = javaFileManager instanceof CoreJavaFileManager; - this.extensionPsiElementFinders = Lists.newArrayList(); - for (PsiElementFinder finder : project.getExtensions(PsiElementFinder.EP_NAME)) { - if (!(finder instanceof KotlinFinderMarker)) { - this.extensionPsiElementFinders.add(finder); - } - } - } - - @NotNull - private static JavaFileManager findJavaFileManager(@NotNull Project project) { - JavaFileManager javaFileManager = ServiceManager.getService(project, JavaFileManager.class); - if (javaFileManager != null) { - return javaFileManager; - } - throw new IllegalStateException("JavaFileManager component is not found in project"); - } - - @Nullable - public PsiPackage findPackage(@NotNull String qualifiedName) { - PsiPackage psiPackage = javaFileManager.findPackage(qualifiedName); - if (psiPackage != null) { - return psiPackage; - } - - for (PsiElementFinder finder : extensionPsiElementFinders) { - psiPackage = finder.findPackage(qualifiedName); - if (psiPackage != null) { - return psiPackage; - } - } - return null; - } - - public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { - ProgressIndicatorProvider.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly - - PsiClass aClass = javaFileManager.findClass(qualifiedName, scope); - if (aClass != null) { - //TODO: (module refactoring) CoreJavaFileManager should check scope - if (!isCoreJavaFileManager || scope.contains(aClass.getContainingFile().getOriginalFile().getVirtualFile())) { - return aClass; - } - } - - for (PsiElementFinder finder : extensionPsiElementFinders) { - aClass = finder.findClass(qualifiedName, scope); - if (aClass != null) { - return aClass; - } - } - - return null; - } -} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/KotlinFinderMarker.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/KotlinFinderMarker.java new file mode 100644 index 00000000000..ccf169e5aaf --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/KotlinFinderMarker.java @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.java; + +public interface KotlinFinderMarker { +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/KotlinJavaPsiFacade.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/KotlinJavaPsiFacade.java new file mode 100644 index 00000000000..077104719c4 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/KotlinJavaPsiFacade.java @@ -0,0 +1,192 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.java; + +import com.intellij.core.CoreJavaFileManager; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.PackageIndex; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.psi.impl.file.PsiPackageImpl; +import com.intellij.psi.impl.file.impl.JavaFileManager; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.CommonProcessors; +import com.intellij.util.Processor; +import com.intellij.util.Query; +import kotlin.Function1; +import kotlin.KotlinPackage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class KotlinJavaPsiFacade { + private final KotlinJavaPsiFacadeWrapper javaPsiFacadeWrapper; + + public KotlinJavaPsiFacade(Project project, GlobalSearchScope searchScope) { + javaPsiFacadeWrapper = new KotlinJavaPsiFacadeWrapper(project, searchScope); + } + + public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { + return javaPsiFacadeWrapper.findClass(qualifiedName, scope); + } + + public PsiPackage findPackage(@NotNull String qualifiedName) { + return javaPsiFacadeWrapper.findPackage(qualifiedName); + } + + static class KotlinJavaPsiFacadeWrapper extends JavaPsiFacadeImpl { + private final GlobalSearchScope searchScope; + + public KotlinJavaPsiFacadeWrapper(Project project, GlobalSearchScope searchScope) { + super(project, PsiManager.getInstance(project), findJavaFileManager(project), project.getMessageBus()); + this.searchScope = searchScope; + } + + @NotNull + @Override + protected PsiElementFinder[] calcFinders() { + List filteredBaseFinders = KotlinPackage.filter( + super.calcFinders(), new Function1() { + @Override + public Boolean invoke(PsiElementFinder finder) { + if (finder instanceof KotlinFinderMarker) return false; + + if (finder.getClass().getName().equals("org.jetbrains.jet.lang.resolve.java.JavaPsiFacadeImpl$PsiElementFinderImpl")) { + // TODO: Replace with instanceof check in idea 14 + return false; + } + + return true; + } + }); + + List elementFinders = new ArrayList(); + elementFinders.add(new KotlinPsiElementFinderImpl(getProject(), searchScope)); + elementFinders.addAll(filteredBaseFinders); + + return elementFinders.toArray(new PsiElementFinder[elementFinders.size()]); + } + + @NotNull + private static JavaFileManager findJavaFileManager(@NotNull Project project) { + JavaFileManager javaFileManager = ServiceManager.getService(project, JavaFileManager.class); + if (javaFileManager == null) { + throw new IllegalStateException("JavaFileManager component is not found in project"); + } + + return javaFileManager; + } + + static class KotlinPsiElementFinderImpl extends PsiElementFinder implements DumbAware { + private final GlobalSearchScope searchScope; + + private final JavaFileManager javaFileManager; + private final boolean isCoreJavaFileManager; + + private final PsiManager psiManager; + private final PackageIndex packageIndex; + + public KotlinPsiElementFinderImpl(Project project, GlobalSearchScope searchScope) { + this.searchScope = searchScope; + + this.javaFileManager = findJavaFileManager(project); + this.isCoreJavaFileManager = javaFileManager instanceof CoreJavaFileManager; + + this.packageIndex = PackageIndex.getInstance(project); + this.psiManager = PsiManager.getInstance(project); + } + + @Override + public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { + PsiClass aClass = javaFileManager.findClass(qualifiedName, scope); + if (aClass != null) { + //TODO: (module refactoring) CoreJavaFileManager should check scope + if (!isCoreJavaFileManager || scope.contains(aClass.getContainingFile().getOriginalFile().getVirtualFile())) { + return aClass; + } + } + + return null; + } + + @Override + public PsiPackage findPackage(@NotNull String qualifiedName) { + if (isCoreJavaFileManager) { + return javaFileManager.findPackage(qualifiedName); + } + + Query dirs = packageIndex.getDirsByPackageName(qualifiedName, true); + return hasDirectoriesInScope(dirs) ? new PsiPackageImpl(psiManager, qualifiedName) : null; + } + + private boolean hasDirectoriesInScope(Query dirs) { + CommonProcessors.FindProcessor findProcessor = new CommonProcessors.FindProcessor() { + @Override + protected boolean accept(VirtualFile file) { + return searchScope.accept(file); + } + }; + + dirs.forEach(findProcessor); + return findProcessor.isFound(); + } + + @Override + @NotNull + public PsiClass[] findClasses(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { + throw new UnsupportedOperationException(); + } + + @Override + @NotNull + public PsiPackage[] getSubPackages(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + throw new UnsupportedOperationException(); + } + + @Override + @NotNull + public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + throw new UnsupportedOperationException(); + } + + @Override + @NotNull + public PsiClass[] getClasses(@Nullable String shortName, @NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public Set getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, + @NotNull GlobalSearchScope scope, + @NotNull Processor consumer, + boolean includeLibrarySources) { + throw new UnsupportedOperationException(); + } + } + } +} \ No newline at end of file diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JavaElementFinder.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JavaElementFinder.java index 098156897e6..2dc5aadb4ae 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JavaElementFinder.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JavaElementFinder.java @@ -35,7 +35,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetEnumEntry; import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.resolve.java.JavaPsiFacadeKotlinHacks; +import org.jetbrains.jet.lang.resolve.java.KotlinFinderMarker; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.NamePackage; @@ -44,7 +44,7 @@ import java.util.Collection; import java.util.List; import java.util.Set; -public class JavaElementFinder extends PsiElementFinder implements JavaPsiFacadeKotlinHacks.KotlinFinderMarker { +public class JavaElementFinder extends PsiElementFinder implements KotlinFinderMarker { @NotNull public static JavaElementFinder getInstance(@NotNull Project project) {