javac ast indices: do not process examine from compilation files

This commit is contained in:
Dmitry Batkovich
2016-12-20 12:39:44 +03:00
parent a15916ae24
commit acacaa89e2
12 changed files with 183 additions and 22 deletions
@@ -68,7 +68,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
private final static Logger LOG = Logger.getInstance(CompilerReferenceServiceImpl.class);
private final Set<FileType> myFileTypes;
private final DirtyModulesHolder myDirtyModulesHolder;
private final DirtyScopeHolder myDirtyScopeHolder;
private final ProjectFileIndex myProjectFileIndex;
private final LongAdder myCompilationCount = new LongAdder();
private final ReentrantReadWriteLock myLock = new ReentrantReadWriteLock();
@@ -82,7 +82,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
myProjectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
myFileTypes = Stream.of(LanguageLightRefAdapter.INSTANCES).flatMap(a -> a.getFileTypes().stream()).collect(Collectors.toSet());
myDirtyModulesHolder = new DirtyModulesHolder(this, fileDocumentManager, psiDocumentManager);
myDirtyScopeHolder = new DirtyScopeHolder(this, fileDocumentManager, psiDocumentManager);
}
@Override
@@ -91,7 +91,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
myProject.getMessageBus().connect(myProject).subscribe(BuildManagerListener.TOPIC, new BuildManagerListener() {
@Override
public void buildStarted(Project project, UUID sessionId, boolean isAutomake) {
myDirtyModulesHolder.compilerActivityStarted();
myDirtyScopeHolder.compilerActivityStarted();
closeReaderIfNeed();
}
});
@@ -127,9 +127,9 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
modulesWithErrors = Collections.emptySet();
}
if (modulesWithErrors.contains(null) /*unknown error location*/) {
myDirtyModulesHolder.compilerActivityFinished(Module.EMPTY_ARRAY, compilationModules);
myDirtyScopeHolder.compilerActivityFinished(Module.EMPTY_ARRAY, compilationModules);
} else {
myDirtyModulesHolder.compilerActivityFinished(compilationModules, modulesWithErrors.toArray(Module.EMPTY_ARRAY));
myDirtyScopeHolder.compilerActivityFinished(compilationModules, modulesWithErrors.toArray(Module.EMPTY_ARRAY));
}
myCompilationCount.increment();
@@ -139,7 +139,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
}
});
myDirtyModulesHolder.installVFSListener();
myDirtyScopeHolder.installVFSListener();
if (!ApplicationManager.getApplication().isUnitTestMode()) {
ApplicationManager.getApplication().executeOnPooledThread(() -> {
@@ -152,12 +152,12 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
});
if (modules == null) return;
if (isUpToDate) {
myDirtyModulesHolder.compilerActivityFinished(modules, Module.EMPTY_ARRAY);
myDirtyScopeHolder.compilerActivityFinished(modules, Module.EMPTY_ARRAY);
myCompilationCount.increment();
openReaderIfNeed();
}
else {
myDirtyModulesHolder.compilerActivityFinished(Module.EMPTY_ARRAY, modules);
myDirtyScopeHolder.compilerActivityFinished(Module.EMPTY_ARRAY, modules);
}
});
});
@@ -233,7 +233,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
});
if (candidatesPerFile == null) return null;
GlobalSearchScope dirtyScope = myDirtyModulesHolder.getDirtyScope();
GlobalSearchScope dirtyScope = myDirtyScopeHolder.getDirtyScope();
if (ElementPlace.LIB == ReadAction.compute(() -> ElementPlace.get(aClass.getContainingFile().getVirtualFile(), myProjectFileIndex))) {
dirtyScope = dirtyScope.union(LibraryScopeCache.getInstance(myProject).getLibrariesOnlyScope());
}
@@ -270,7 +270,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
try {
if (myReader == null) return null;
try {
return myReader.getDirectInheritors(searchElement, useScope, myDirtyModulesHolder.getDirtyScope(), searchFileType, searchType);
return myReader.getDirectInheritors(searchElement, useScope, myDirtyScopeHolder.getDirtyScope(), searchFileType, searchType);
}
catch (StorageException e) {
throw new RuntimeException(e);
@@ -285,7 +285,8 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
TIntHashSet referentFileIds = getReferentFileIds(element);
if (referentFileIds == null) return null;
return getScopeRestrictedByFileTypes(new ScopeWithoutReferencesOnCompilation(referentFileIds, myProjectFileIndex).intersectWith(notScope(myDirtyModulesHolder.getDirtyScope())),
return getScopeRestrictedByFileTypes(new ScopeWithoutReferencesOnCompilation(referentFileIds, myProjectFileIndex).intersectWith(notScope(
myDirtyScopeHolder.getDirtyScope())),
myFileTypes.toArray(new FileType[myFileTypes.size()]));
}
@@ -323,7 +324,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
VirtualFile file = PsiUtilCore.getVirtualFile(psiElement);
if (file == null) return null;
ElementPlace place = ElementPlace.get(file, myProjectFileIndex);
if (place == null || (place == ElementPlace.SRC && myDirtyModulesHolder.contains(file))) {
if (place == null || (place == ElementPlace.SRC && myDirtyScopeHolder.contains(file))) {
return null;
}
final LanguageLightRefAdapter adapter = findAdapterForFileType(file.getFileType());
@@ -500,7 +501,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
@TestOnly
@NotNull
public DirtyModulesHolder getDirtyModulesHolder() {
return myDirtyModulesHolder;
public DirtyScopeHolder getDirtyScopeHolder() {
return myDirtyScopeHolder;
}
}
@@ -37,7 +37,7 @@ import org.jetbrains.annotations.TestOnly;
import java.util.Collections;
import java.util.Set;
public class DirtyModulesHolder extends UserDataHolderBase {
public class DirtyScopeHolder extends UserDataHolderBase {
private final CompilerReferenceServiceImpl myService;
private final FileDocumentManager myFileDocManager;
private final PsiDocumentManager myPsiDocManager;
@@ -46,10 +46,11 @@ public class DirtyModulesHolder extends UserDataHolderBase {
private final Object myLock = new Object();
private boolean myCompilationPhase;
private volatile GlobalSearchScope myExcludedFilesScope;
public DirtyModulesHolder(@NotNull CompilerReferenceServiceImpl service,
FileDocumentManager fileDocumentManager,
PsiDocumentManager psiDocumentManager){
public DirtyScopeHolder(@NotNull CompilerReferenceServiceImpl service,
FileDocumentManager fileDocumentManager,
PsiDocumentManager psiDocumentManager){
myService = service;
myFileDocManager = fileDocumentManager;
myPsiDocManager = psiDocumentManager;
@@ -69,6 +70,7 @@ public class DirtyModulesHolder extends UserDataHolderBase {
Collections.addAll(myVFSChangedModules, markAsDirty);
myVFSChangedModules.addAll(myChangedModulesDuringCompilation);
myChangedModulesDuringCompilation.clear();
myExcludedFilesScope = ExcludedFromCompileFilesUtil.getExcludedFilesScope(myService.getProject(), myService.getFileTypes());
}
}
@@ -81,13 +83,18 @@ public class DirtyModulesHolder extends UserDataHolderBase {
return ReadAction.compute(() -> {
if (project.isDisposed()) throw new ProcessCanceledException();
return CachedValuesManager.getManager(project).getCachedValue(this, () ->
CachedValueProvider.Result.create(calculateDirtyModules(), PsiModificationTracker.MODIFICATION_COUNT, VirtualFileManager.getInstance(), myService));
CachedValueProvider.Result.create(calculateDirtyScope(), PsiModificationTracker.MODIFICATION_COUNT, VirtualFileManager.getInstance(), myService));
});
}
}
private GlobalSearchScope calculateDirtyModules() {
return getAllDirtyModules().stream().map(Module::getModuleWithDependentsScope).reduce(GlobalSearchScope.EMPTY_SCOPE, (s1, s2) -> s1.union(s2));
private GlobalSearchScope calculateDirtyScope() {
final GlobalSearchScope dirtyModuleScope = getAllDirtyModules()
.stream()
.map(Module::getModuleWithDependentsScope)
.reduce(GlobalSearchScope.EMPTY_SCOPE, (s1, s2) -> s1.union(s2));
return dirtyModuleScope.union(myExcludedFilesScope);
}
@NotNull
@@ -0,0 +1,63 @@
/*
* Copyright 2000-2016 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 com.intellij.compiler.backwardRefs;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class ExcludedFromCompileFilesUtil {
static GlobalSearchScope getExcludedFilesScope(@NotNull Project project, @NotNull Set<FileType> fileTypes) {
final Collection<VirtualFile> excludedFiles = Stream
.of(CompilerConfiguration.getInstance(project).getExcludedEntriesConfiguration().getExcludeEntryDescriptions())
.flatMap(description -> {
final VirtualFile file = description.getVirtualFile();
if (file == null) return Stream.empty();
if (description.isFile()) {
return Stream.of(file);
}
else if (description.isIncludeSubdirectories()) {
return iterateChildrenRecursively(file);
}
else {
return Stream.of(file.getChildren());
}
})
.filter(f -> !f.isDirectory() && f instanceof VirtualFileWithId && fileTypes.contains(f.getFileType()))
.collect(Collectors.toList());
return GlobalSearchScope.filesWithoutLibrariesScope(project, excludedFiles);
}
private static Stream<VirtualFile> iterateChildrenRecursively(VirtualFile file) {
final Stream.Builder<VirtualFile> builder = Stream.builder();
VfsUtilCore.iterateChildrenRecursively(file, null, f -> {
builder.accept(f);
return true;
});
return builder.build();
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m() {
Runnable r = () -> {};
}
}
@@ -0,0 +1,5 @@
public class A {
void m() {
Runnable r = () -> {};
}
}
@@ -0,0 +1,5 @@
public class ShouldFindHere {
void m() {
Runnable r = () -> {};
}
}
@@ -0,0 +1,5 @@
public class Bar {
void m() {
Runnable r = () -> {};
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m() {
Runnable r = () -> {};
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m() {
Runnable r = () -> {};
}
}
@@ -0,0 +1,5 @@
public class ShouldFindHere {
void m() {
Runnable r = () -> {};
}
}
@@ -18,12 +18,24 @@ package com.intellij.compiler;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.compiler.options.ExcludeEntryDescription;
import com.intellij.openapi.compiler.options.ExcludesConfiguration;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.injected.MyTestInjector;
import com.intellij.psi.search.searches.FunctionalExpressionSearch;
import com.intellij.psi.search.searches.MethodReferencesSearch;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.testFramework.CompilerTester;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.SkipSlowTestLocally;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
@SkipSlowTestLocally
public class CompilerReferencesFindUsagesTest extends DaemonAnalyzerTestCase {
@@ -37,6 +49,7 @@ public class CompilerReferencesFindUsagesTest extends DaemonAnalyzerTestCase {
CompilerReferenceService.IS_ENABLED_KEY.setValue(true);
super.setUp();
myCompilerTester = new CompilerTester(myModule);
LanguageLevelProjectExtension.getInstance(myProject).setLanguageLevel(LanguageLevel.JDK_1_8);
}
@Override
@@ -51,10 +64,16 @@ public class CompilerReferencesFindUsagesTest extends DaemonAnalyzerTestCase {
}
}
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath() + "/compiler/compilerReferenceFindUsages/";
}
@Override
protected Sdk getTestProjectJdk() {
return IdeaTestUtil.getMockJdk18();
}
public void testMethodUsageOnGetter() throws Exception {
configureByFiles(getName(), getName() + "/Foo.java", getName() + "/FooFactory.java", getName() + "/Bar.java");
PsiMethod methodToSearch = findClass("Foo").findMethodsByName("someMethod", false)[0];
@@ -117,4 +136,40 @@ public class CompilerReferencesFindUsagesTest extends DaemonAnalyzerTestCase {
PsiReference reference = assertOneElement(ReferencesSearch.search(classForSearch).findAll());
assertTrue(InjectedLanguageManager.getInstance(getProject()).isInjectedFragment(reference.getElement().getContainingFile()));
}
public void testFindUsagesWithExcludedFromCompilationDirectory() {
doTestRunnableFindUsagesWithExcludesConfiguration(configuration -> {
final VirtualFile dirToExclude = findClass("A").getContainingFile().getVirtualFile().getParent();
configuration.addExcludeEntryDescription(new ExcludeEntryDescription(dirToExclude, false, false, myProject));
}, 3, "Foo.java", "excluded/A.java", "excluded/child/ShouldFindHere.java");
}
public void testFindUsagesWithRecursivelyExcludedFromCompilationDirectory() {
doTestRunnableFindUsagesWithExcludesConfiguration(configuration -> {
final VirtualFile dirToExclude = findClass("ShouldFindHere").getContainingFile().getVirtualFile().getParent().getParent();
configuration.addExcludeEntryDescription(new ExcludeEntryDescription(dirToExclude, true, false, myProject));
}, 2, "Foo.java", "excluded/child/ShouldFindHere.java");
}
public void testFindUsagesWithExcludedFromCompilationFile() {
doTestRunnableFindUsagesWithExcludesConfiguration(configuration -> {
final VirtualFile dirToExclude = findClass("Foo").getContainingFile().getVirtualFile();
configuration.addExcludeEntryDescription(new ExcludeEntryDescription(dirToExclude, false, true, myProject));
}, 2, "Foo.java", "Bar.java");
}
private void doTestRunnableFindUsagesWithExcludesConfiguration(@NotNull Consumer<ExcludesConfiguration> excludesConfigurationPatcher,
int expectedUsagesCount,
String... testFiles) {
final ExcludesConfiguration excludesConfiguration = CompilerConfiguration.getInstance(myProject).getExcludedEntriesConfiguration();
try {
configureByFiles(getName(), Arrays.stream(testFiles).map(f -> getName() + "/" + f).toArray(String[]::new));
excludesConfigurationPatcher.consume(excludesConfiguration);
//assertSize(expectedUsagesCount, FunctionalExpressionSearch.search(myJavaFacade.findClass(CommonClassNames.JAVA_LANG_RUNNABLE)).findAll());
myCompilerTester.rebuild();
assertSize(expectedUsagesCount, FunctionalExpressionSearch.search(myJavaFacade.findClass(CommonClassNames.JAVA_LANG_RUNNABLE)).findAll());
} finally {
excludesConfiguration.removeAllExcludeEntryDescriptions();
}
}
}
@@ -61,6 +61,6 @@ class CompilerReferencesMultiModuleTest : CompilerReferencesTestBase() {
private fun dirtyModules() =
(CompilerReferenceService.getInstance(project) as CompilerReferenceServiceImpl)
.dirtyModulesHolder
.dirtyScopeHolder
.allDirtyModulesForTest
}