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;
private final Set<FileType> myFileTypes;
private volatile CompilerReferenceReader myReader;
+ private volatile GlobalSearchScope myMayContainInvalidDataScope = GlobalSearchScope.EMPTY_SCOPE;
private final Object myLock = new Object();
@Override
public boolean execute(CompileContext context) {
myChangedModules.clear();
+ myMayContainInvalidDataScope = GlobalSearchScope.EMPTY_SCOPE;
openReaderIfNeed();
return true;
}
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());
+ }
}
}
}
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
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;
}
}
- 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
}
}
-}
+}
\ No newline at end of file
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");
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();
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);
}
}
--- /dev/null
+/*
+ * 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<InCodeScopeOptimizer> EP_NAME = ExtensionPointName.create("com.intellij.inCodeScopeOptimizer");
+
+ @Nullable
+ GlobalSearchScope getOptimizedScopeInCode(@NotNull PsiElement element);
+}
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
/**
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,
short searchContext,
boolean caseSensitive,
String containerName,
- @NotNull RequestResultProcessor processor) {
+ @NotNull RequestResultProcessor processor,
+ PsiElement searchTarget) {
if (!makesSenseToSearch(word, searchScope)) return;
+
+ Collection<PsiSearchRequest> 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,
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) {
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) {
<extensionPoint name="resolveScopeEnlarger" interface="com.intellij.psi.ResolveScopeEnlarger"/>
<extensionPoint name="resolveScopeProvider" interface="com.intellij.psi.ResolveScopeProvider"/>
<extensionPoint name="useScopeOptimizer" interface="com.intellij.psi.search.UseScopeOptimizer"/>
+ <extensionPoint name="inCodeScopeOptimizer" interface="com.intellij.psi.search.InCodeScopeOptimizer"/>
<extensionPoint name="generatedSourcesFilter" interface="com.intellij.openapi.roots.GeneratedSourcesFilter"/>
<extensionPoint name="outOfSourcesChecker" interface="com.intellij.openapi.projectRoots.OutOfSourcesChecker"/>
<fileBasedIndex implementation="com.intellij.psi.impl.search.JavaNullMethodArgumentIndex"/>
- <useScopeOptimizer implementation="com.intellij.find.compiler.CompilerReferenceScopeOptimizer"/>
+ <inCodeScopeOptimizer implementation="com.intellij.compiler.JavaCompilerReferencesInCodeScopeOptimizer"/>
</extensions>
<actions>