From 000b0a0e7836807bf40ec08dc26aa9192fd7b24e Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 28 Sep 2016 15:22:37 +0300 Subject: [PATCH] do not forget about comments while searching using javac ast --- .../CompilerReferenceServiceImpl.java | 38 ++++++++++--------- .../dataFlow/DataFlowInspection.java | 2 +- .../compiler/CompilerReferenceService.java | 4 +- ...mpilerReferencesInCodeScopeOptimizer.java} | 8 ++-- .../psi/search/InCodeScopeOptimizer.java | 28 ++++++++++++++ .../psi/search/SearchRequestCollector.java | 38 ++++++++++++++++--- .../src/META-INF/LangExtensionPoints.xml | 1 + resources/src/META-INF/IdeaPlugin.xml | 2 +- 8 files changed, 91 insertions(+), 30 deletions(-) rename java/java-indexing-impl/src/com/intellij/compiler/{CompilerReferenceScopeOptimizer.java => JavaCompilerReferencesInCodeScopeOptimizer.java} (76%) create mode 100644 platform/indexing-api/src/com/intellij/psi/search/InCodeScopeOptimizer.java diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerReferenceServiceImpl.java b/java/compiler/impl/src/com/intellij/compiler/CompilerReferenceServiceImpl.java index 4b733acaa7d5..6b5d54d773e7 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompilerReferenceServiceImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompilerReferenceServiceImpl.java @@ -24,11 +24,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.roots.impl.LibraryScopeCache; import com.intellij.openapi.vfs.*; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.ProjectScope; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; @@ -55,6 +55,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService { private final Set myFileTypes; private volatile CompilerReferenceReader myReader; + private volatile GlobalSearchScope myMayContainInvalidDataScope = GlobalSearchScope.EMPTY_SCOPE; private final Object myLock = new Object(); @@ -79,6 +80,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService { @Override public boolean execute(CompileContext context) { myChangedModules.clear(); + myMayContainInvalidDataScope = GlobalSearchScope.EMPTY_SCOPE; openReaderIfNeed(); return true; } @@ -127,7 +129,9 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService { if (myReader != null && myProjectFileIndex.isInSourceContent(file) && myFileTypes.contains(file.getFileType())) { final Module module = myProjectFileIndex.getModuleForFile(file); if (module != null) { - myChangedModules.add(module); + if (myChangedModules.add(module)) { + myMayContainInvalidDataScope = myMayContainInvalidDataScope.union(module.getModuleWithDependentsScope()); + } } } } @@ -139,25 +143,27 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService { closeReaderIfNeed(); } + @Nullable @Override - public GlobalSearchScope getScopeWithoutReferences(@NotNull PsiElement element) { + public GlobalSearchScope getMayContainReferencesInCodeScope(@NotNull PsiElement element) { if (!isServiceEnabled()) return null; - return CachedValuesManager.getCachedValue(element, () -> CachedValueProvider.Result.create(calculateScopeWithoutReferences(element), - PsiModificationTracker.MODIFICATION_COUNT)); + return CachedValuesManager.getCachedValue(element, () -> CachedValueProvider.Result.create(calculateMayContainReferencesScope(element), PsiModificationTracker.MODIFICATION_COUNT)); } + private boolean isServiceEnabled() { return myReader != null && isEnabled(); } @Nullable - private GlobalSearchScope calculateScopeWithoutReferences(@NotNull PsiElement element) { + private GlobalSearchScope calculateMayContainReferencesScope(@NotNull PsiElement element) { TIntHashSet referentFileIds = getReferentFileIds(element); if (referentFileIds == null) return null; - final GlobalSearchScope everythingIsClearScope = GlobalSearchScope - .getScopeRestrictedByFileTypes(ProjectScope.getContentScope(myProject), myFileTypes.toArray(new FileType[myFileTypes.size()])); - return new ScopeWithoutBytecodeReferences(referentFileIds).intersectWith(everythingIsClearScope); + return new ScopeWithBytecodeReferences(referentFileIds) + .union(myMayContainInvalidDataScope) + .union(LibraryScopeCache.getInstance(element.getProject()).getLibrariesOnlyScope()) + .union(GlobalSearchScope.notScope(GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(myProject), myFileTypes.toArray(new FileType[myFileTypes.size()])))); } @Nullable @@ -171,11 +177,9 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService { if (place == null) { return null; } - if (!myChangedModules.isEmpty()) { - final Module module = myProjectFileIndex.getModuleForFile(vFile); - if (module == null || areDependenciesOrSelfChanged(module, new THashSet<>())) { - return null; - } + + if (myMayContainInvalidDataScope.contains(vFile)) { + return null; } final FileType type = vFile.getFileType(); CompilerElement[] compilerElements = null; @@ -250,16 +254,16 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService { } } - private static class ScopeWithoutBytecodeReferences extends GlobalSearchScope { + private static class ScopeWithBytecodeReferences extends GlobalSearchScope { private final TIntHashSet myReferentIds; - private ScopeWithoutBytecodeReferences(TIntHashSet ids) { + private ScopeWithBytecodeReferences(TIntHashSet ids) { myReferentIds = ids; } @Override public boolean contains(@NotNull VirtualFile file) { - return !(file instanceof VirtualFileWithId) || !myReferentIds.contains(((VirtualFileWithId)file).getId()); + return file instanceof VirtualFileWithId && myReferentIds.contains(((VirtualFileWithId)file).getId()); } @Override diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java index 6b0e5a204fd9..437d09fd2dfe 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java @@ -194,4 +194,4 @@ public class DataFlowInspection extends DataFlowInspectionBase { } } -} +} \ No newline at end of file diff --git a/java/java-indexing-impl/src/com/intellij/compiler/CompilerReferenceService.java b/java/java-indexing-impl/src/com/intellij/compiler/CompilerReferenceService.java index 39c1480af5b2..0b5d252ad658 100644 --- a/java/java-indexing-impl/src/com/intellij/compiler/CompilerReferenceService.java +++ b/java/java-indexing-impl/src/com/intellij/compiler/CompilerReferenceService.java @@ -22,6 +22,7 @@ import com.intellij.openapi.util.registry.RegistryValue; import com.intellij.psi.PsiElement; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public abstract class CompilerReferenceService extends AbstractProjectComponent { public static final RegistryValue IS_ENABLED_KEY = Registry.get("bytecode.ref.index"); @@ -34,7 +35,8 @@ public abstract class CompilerReferenceService extends AbstractProjectComponent return project.getComponent(CompilerReferenceService.class); } - public abstract GlobalSearchScope getScopeWithoutReferences(@NotNull PsiElement element); + @Nullable + public abstract GlobalSearchScope getMayContainReferencesInCodeScope(@NotNull PsiElement element); public static boolean isEnabled() { return IS_ENABLED_KEY.asBoolean(); diff --git a/java/java-indexing-impl/src/com/intellij/compiler/CompilerReferenceScopeOptimizer.java b/java/java-indexing-impl/src/com/intellij/compiler/JavaCompilerReferencesInCodeScopeOptimizer.java similarity index 76% rename from java/java-indexing-impl/src/com/intellij/compiler/CompilerReferenceScopeOptimizer.java rename to java/java-indexing-impl/src/com/intellij/compiler/JavaCompilerReferencesInCodeScopeOptimizer.java index 2050ef343c79..537c2e481fc1 100644 --- a/java/java-indexing-impl/src/com/intellij/compiler/CompilerReferenceScopeOptimizer.java +++ b/java/java-indexing-impl/src/com/intellij/compiler/JavaCompilerReferencesInCodeScopeOptimizer.java @@ -17,14 +17,14 @@ package com.intellij.compiler; import com.intellij.psi.PsiElement; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.UseScopeOptimizer; +import com.intellij.psi.search.InCodeScopeOptimizer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class CompilerReferenceScopeOptimizer extends UseScopeOptimizer { +public class JavaCompilerReferencesInCodeScopeOptimizer implements InCodeScopeOptimizer { @Nullable @Override - public GlobalSearchScope getScopeToExclude(@NotNull PsiElement element) { - return CompilerReferenceService.getInstance(element.getProject()).getScopeWithoutReferences(element); + public GlobalSearchScope getOptimizedScopeInCode(@NotNull PsiElement element) { + return CompilerReferenceService.getInstance(element.getProject()).getMayContainReferencesInCodeScope(element); } } diff --git a/platform/indexing-api/src/com/intellij/psi/search/InCodeScopeOptimizer.java b/platform/indexing-api/src/com/intellij/psi/search/InCodeScopeOptimizer.java new file mode 100644 index 000000000000..178df2e74499 --- /dev/null +++ b/platform/indexing-api/src/com/intellij/psi/search/InCodeScopeOptimizer.java @@ -0,0 +1,28 @@ +/* + * 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.psi.search; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface InCodeScopeOptimizer { + ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.inCodeScopeOptimizer"); + + @Nullable + GlobalSearchScope getOptimizedScopeInCode(@NotNull PsiElement element); +} diff --git a/platform/indexing-api/src/com/intellij/psi/search/SearchRequestCollector.java b/platform/indexing-api/src/com/intellij/psi/search/SearchRequestCollector.java index 84fe188c1382..0d542827cb5a 100644 --- a/platform/indexing-api/src/com/intellij/psi/search/SearchRequestCollector.java +++ b/platform/indexing-api/src/com/intellij/psi/search/SearchRequestCollector.java @@ -28,6 +28,8 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -60,7 +62,7 @@ public class SearchRequestCollector { short searchContext, boolean caseSensitive, @NotNull PsiElement searchTarget) { - searchWord(word, searchScope, searchContext, caseSensitive, getContainerName(searchTarget), new SingleTargetRequestResultProcessor(searchTarget)); + searchWord(word, searchScope, searchContext, caseSensitive, getContainerName(searchTarget), new SingleTargetRequestResultProcessor(searchTarget), searchTarget); } private void searchWord(@NotNull String word, @@ -68,11 +70,35 @@ public class SearchRequestCollector { short searchContext, boolean caseSensitive, String containerName, - @NotNull RequestResultProcessor processor) { + @NotNull RequestResultProcessor processor, + PsiElement searchTarget) { if (!makesSenseToSearch(word, searchScope)) return; + + Collection requests = null; + if (searchTarget != null && (searchScope instanceof GlobalSearchScope) && ((searchContext & UsageSearchContext.IN_CODE) != 0 || searchContext == UsageSearchContext.ANY)) { + for (InCodeScopeOptimizer optimizer : InCodeScopeOptimizer.EP_NAME.getExtensions()) { + final GlobalSearchScope optimizedSourcesSearchScope = optimizer.getOptimizedScopeInCode(searchTarget); + if (optimizedSourcesSearchScope != null) { + short exceptCodeSearchContext = searchContext == UsageSearchContext.ANY + ? (short)(searchContext ^ UsageSearchContext.IN_CODE) + : (UsageSearchContext.IN_COMMENTS | + UsageSearchContext.IN_STRINGS | + UsageSearchContext.IN_FOREIGN_LANGUAGES | + UsageSearchContext.IN_PLAIN_TEXT); + final GlobalSearchScope effectiveScopeWithSources = ((GlobalSearchScope)searchScope).intersectWith(optimizedSourcesSearchScope); + final GlobalSearchScope effectiveScopeWithoutSources = + ((GlobalSearchScope)searchScope).intersectWith(GlobalSearchScope.notScope(optimizedSourcesSearchScope)); + requests = ContainerUtil.list(new PsiSearchRequest(effectiveScopeWithSources, word, searchContext, caseSensitive, containerName, processor), + new PsiSearchRequest(effectiveScopeWithoutSources, word, exceptCodeSearchContext, caseSensitive, containerName, processor)); + } + } + } + if (requests == null) { + requests = Collections.singleton(new PsiSearchRequest(searchScope, word, searchContext, caseSensitive, containerName, processor)); + } + synchronized (lock) { - PsiSearchRequest request = new PsiSearchRequest(searchScope, word, searchContext, caseSensitive, containerName, processor); - myWordRequests.add(request); + myWordRequests.addAll(requests); } } public void searchWord(@NotNull String word, @@ -81,7 +107,7 @@ public class SearchRequestCollector { boolean caseSensitive, @NotNull PsiElement searchTarget, @NotNull RequestResultProcessor processor) { - searchWord(word, searchScope, searchContext, caseSensitive, getContainerName(searchTarget), processor); + searchWord(word, searchScope, searchContext, caseSensitive, getContainerName(searchTarget), processor, searchTarget); } private static String getContainerName(@NotNull final PsiElement target) { @@ -111,7 +137,7 @@ public class SearchRequestCollector { short searchContext, boolean caseSensitive, @NotNull RequestResultProcessor processor) { - searchWord(word, searchScope, searchContext, caseSensitive, (String)null, processor); + searchWord(word, searchScope, searchContext, caseSensitive, null, processor, null); } private static boolean makesSenseToSearch(@NotNull String word, @NotNull SearchScope searchScope) { diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 016b8f89683d..13b617483352 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -260,6 +260,7 @@ + diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 069fd6e32048..5bf0a71ad886 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -1803,7 +1803,7 @@ - +