[java] allow providing exclusions for PsiShortNamesCache by specific languages

It will be additionally used in the following commit

KTIJ-30842

GitOrigin-RevId: 8370a2ef5157b8c4afff45cfbf6c1e563cb9cd82
This commit is contained in:
Ilya Kirillov
2024-08-15 17:45:50 +02:00
committed by intellij-monorepo-bot
parent 378186e17f
commit 8f34a2a79f
8 changed files with 92 additions and 50 deletions

View File

@@ -371,6 +371,9 @@
<extensionPoint qualifiedName="com.intellij.openapi.projectRoots.externalJavaConfigurationProvider"
interface="com.intellij.openapi.projectRoots.impl.ExternalJavaConfigurationProvider" dynamic="true"/>
<extensionPoint qualifiedName="com.intellij.gotoByName.defaultProvider.ignoreLanguage" dynamic="true"
beanClass="com.intellij.ide.util.gotoByName.IgnoreLanguageInDefaultProvider"/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">

View File

@@ -23,6 +23,7 @@ import com.intellij.util.indexing.IdFilter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.regex.Matcher;
public class DefaultClassNavigationContributor implements ChooseByNameContributorEx, GotoClassContributor, PossiblyDumbAware {
@@ -51,7 +52,7 @@ public class DefaultClassNavigationContributor implements ChooseByNameContributo
public void processNames(@NotNull Processor<? super String> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter) {
Project project = scope.getProject();
DumbModeAccessType.RAW_INDEX_DATA_ACCEPTABLE.ignoreDumbMode(() -> {
PsiShortNamesCache.getInstance(project).forDefaultGotoContributor().processAllClassNames(processor, scope, filter);
getPsiShortNamesCache(project).processAllClassNames(processor, scope, filter);
});
}
@@ -61,12 +62,16 @@ public class DefaultClassNavigationContributor implements ChooseByNameContributo
final @NotNull FindSymbolParameters parameters) {
DumbModeAccessType.RELIABLE_DATA_ONLY.ignoreDumbMode(() -> {
DefaultClassProcessor defaultClassProcessor = new DefaultClassProcessor(processor, parameters, false);
PsiShortNamesCache.getInstance(parameters.getProject())
.forDefaultGotoContributor()
getPsiShortNamesCache(parameters.getProject())
.processClassesWithName(name, defaultClassProcessor, parameters.getSearchScope(), parameters.getIdFilter());
});
}
private static PsiShortNamesCache getPsiShortNamesCache(@NotNull Project project) {
Set<Language> withoutLanguages = IgnoreLanguageInDefaultProvider.getIgnoredLanguages();
return PsiShortNamesCache.getInstance(project).withoutLanguages(withoutLanguages);
}
public static class DefaultClassProcessor implements Processor<PsiClass> {
private final @NotNull Processor<? super NavigationItem> processor;
private final @Nullable MinusculeMatcher innerClassMatcher;

View File

@@ -3,6 +3,7 @@ package com.intellij.ide.util.gotoByName;
import com.intellij.ide.actions.JavaQualifiedNameProvider;
import com.intellij.ide.util.gotoByName.DefaultClassNavigationContributor.DefaultClassProcessor;
import com.intellij.lang.Language;
import com.intellij.navigation.ChooseByNameContributorEx;
import com.intellij.navigation.GotoClassContributor;
import com.intellij.navigation.NavigationItem;
@@ -101,12 +102,17 @@ public class DefaultSymbolNavigationContributor implements ChooseByNameContribut
return false;
}
private static PsiShortNamesCache getPsiShortNamesCache(@NotNull Project project) {
Set<Language> withoutLanguages = IgnoreLanguageInDefaultProvider.getIgnoredLanguages();
return PsiShortNamesCache.getInstance(project).withoutLanguages(withoutLanguages);
}
@Override
public void processNames(@NotNull Processor<? super String> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter) {
Project project = scope.getProject();
if (project == null) return;
DumbModeAccessType.RAW_INDEX_DATA_ACCEPTABLE.ignoreDumbMode(() -> {
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project).forDefaultGotoContributor();
PsiShortNamesCache cache = getPsiShortNamesCache(project);
cache.processAllClassNames(processor, scope, filter);
cache.processAllFieldNames(processor, scope, filter);
cache.processAllMethodNames(processor, scope, filter);
@@ -126,7 +132,7 @@ public class DefaultSymbolNavigationContributor implements ChooseByNameContribut
final Predicate<PsiMember> qualifiedMatcher = getQualifiedNameMatcher(completePattern);
final Set<PsiMethod> collectedMethods = new HashSet<>();
DumbModeAccessType.RELIABLE_DATA_ONLY.ignoreDumbMode(() -> {
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project).forDefaultGotoContributor();
PsiShortNamesCache cache = getPsiShortNamesCache(project);
boolean success = cache.processFieldsWithName(name, field -> {
if (isOpenable(field) && qualifiedMatcher.test(field)) return processor.process(field);
return true;

View File

@@ -0,0 +1,32 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.util.gotoByName
import com.intellij.lang.Language
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.extensions.RequiredElement
import com.intellij.util.xmlb.annotations.Attribute
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
class IgnoreLanguageInDefaultProvider {
@RequiredElement
@JvmField
@Attribute("language")
var language: String = ""
fun languageInstance(): Language =
Language.findLanguageByID(language) ?: error("No language with id $language found")
companion object {
@ApiStatus.Internal
val EP_NAME: ExtensionPointName<IgnoreLanguageInDefaultProvider> =
ExtensionPointName.create<IgnoreLanguageInDefaultProvider>("com.intellij.gotoByName.defaultProvider.ignoreLanguage")
@JvmStatic
@ApiStatus.Internal
fun getIgnoredLanguages(): Set<Language> =
EP_NAME.extensionList.mapTo(mutableSetOf()) { it.languageInstance() }
}
}

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.search;
import com.intellij.lang.Language;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
@@ -16,6 +17,8 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
/**
* Allows to retrieve files and Java classes, methods and fields in a project by non-qualified names.
*/
@@ -147,47 +150,33 @@ public abstract class PsiShortNamesCache {
return ContainerUtil.process(getClassesByName(name, scope), processor);
}
/**
* <p>
* Determines whether the specific {@link PsiShortNamesCache} should be used in the default implementation of the goto contributor,
* specifically the {@link com.intellij.ide.util.gotoByName.DefaultSymbolNavigationContributor} and {@link com.intellij.ide.util.gotoByName.DefaultClassNavigationContributor}.
* </p>
*
* <p>
* Alternatively, a language for which <code>serveDefaultGotoContributor()</code> returns <code>false</code>,
* provides its own contributors,
* and supplies its own instances of {@link com.intellij.navigation.ChooseByNameContributor} and {@link com.intellij.navigation.GotoClassContributor}.
* </p>
*
* @return <code>true</code> (default) if a language should rely on Java-based PSI (e.g., {@link PsiClass}, {@link PsiMethod}, etc.) for goto contributors,
* and <code>false</code> if a language has its own contributors.
*/
@ApiStatus.Internal
public boolean serveDefaultGotoContributor() {
return true;
}
/**
* Determines for which language the current {@link PsiShortNamesCache} provides the declarations.
* <p>
* Returns a new instance
* of {@link PsiShortNamesCache} to be used in the {@link com.intellij.ide.util.gotoByName.DefaultSymbolNavigationContributor}
* and {@link com.intellij.ide.util.gotoByName.DefaultClassNavigationContributor}
* for providing default Java-based PSI declarations such as {@link PsiClass}, {@link PsiMethod}, etc.
* </p>
*
* <p>
* Languages that have implemented {@link #serveDefaultGotoContributor} have their own goto contributors, and these languages are not processed by the returned {@link PsiShortNamesCache}.
* </p>
*
* The default is {@link Language#ANY}
*/
@ApiStatus.Internal
public @NotNull Language getLanguage() {
return Language.ANY;
}
/**
* Returns a new instance of {@link PsiShortNamesCache} which will provide declarations for all the languages except for the ones specified via {@code languages}
* <p>
* This method is implemented only in the {@link PsiShortNamesCache}, which is registered as a project service.
* For other implementations, it throws a {@link UnsupportedOperationException}.
* </p>
*
* @see #serveDefaultGotoContributor
* @see #getLanguage
*/
@ApiStatus.Internal
public @NotNull PsiShortNamesCache forDefaultGotoContributor() {
throw new UnsupportedOperationException("Works only in `PsiShortNamesCache` which is registered as a project service");
public @NotNull PsiShortNamesCache withoutLanguages(Set<Language> languages) {
throw new UnsupportedOperationException();
}
@ApiStatus.Internal
public @NotNull PsiShortNamesCache withoutLanguages(Language... languages) {
return withoutLanguages(Set.of(languages));
}
}

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.impl;
import com.intellij.lang.Language;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
@@ -13,7 +14,7 @@ import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.IdFilter;
import org.jetbrains.annotations.ApiStatus;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -25,21 +26,23 @@ import java.util.Set;
public final class CompositeShortNamesCache extends PsiShortNamesCache {
private final Project myProject;
private final boolean myForDefaultGotoContributor;
private final Set<Language> myExcludeLanguages;
public CompositeShortNamesCache(Project project) {
this(project, /*forGotoContributor*/false);
this(project, /*withoutLanguages*/Collections.emptySet());
}
private CompositeShortNamesCache(Project project, boolean forDefaultGotoContributor) {
private CompositeShortNamesCache(Project project, Set<Language> excludeLanguages) {
myProject = project;
myForDefaultGotoContributor = forDefaultGotoContributor;
myExcludeLanguages = excludeLanguages;
}
@ApiStatus.Internal
@Override
public @NotNull PsiShortNamesCache forDefaultGotoContributor() {
return new CompositeShortNamesCache(myProject, /*forGotoContributor*/true);
public @NotNull PsiShortNamesCache withoutLanguages(Set<Language> excludeLanguages) {
if (excludeLanguages.isEmpty()) return this;
Set<Language> newExcludeLanguages = CollectionsKt.union(myExcludeLanguages, excludeLanguages);
return new CompositeShortNamesCache(myProject, newExcludeLanguages);
}
@NotNull
@@ -47,10 +50,10 @@ public final class CompositeShortNamesCache extends PsiShortNamesCache {
if (myProject.isDefault()) return Collections.emptyList();
List<@NotNull PsiShortNamesCache> extensionList = EP_NAME.getExtensionList(myProject);
if (myForDefaultGotoContributor) {
if (!myExcludeLanguages.isEmpty()) {
return extensionList
.stream()
.filter(cache -> cache.serveDefaultGotoContributor())
.filter(cache -> !myExcludeLanguages.contains(cache.getLanguage()))
.toList();
} else {
return extensionList;

View File

@@ -2,6 +2,7 @@
package org.jetbrains.kotlin.idea.caches
import com.intellij.lang.Language
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.fileTypes.FileTypeRegistry
import com.intellij.openapi.module.Module
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.asJava.defaultImplsChild
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.asJava.getAccessorLightMethods
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.base.projectStructure.scope.KotlinSourceFilterScope
import org.jetbrains.kotlin.idea.base.psi.KotlinPsiHeuristics
import org.jetbrains.kotlin.idea.stubindex.KotlinClassShortNameIndex
@@ -337,7 +339,7 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
fun toArray(a: Array<T>): Array<T> = set.toArray(a)
}
override fun serveDefaultGotoContributor(): Boolean {
return false
override fun getLanguage(): Language {
return KotlinLanguage.INSTANCE
}
}

View File

@@ -33,5 +33,7 @@
<gotoSymbolContributor implementation="org.jetbrains.kotlin.idea.goto.KotlinGotoJvmNameSymbolContributor"/>
<gotoPrimeSymbolContributor implementation="org.jetbrains.kotlin.idea.goto.KotlinGotoPrimeSymbolContributor"/>
<gotoByName.defaultProvider.ignoreLanguage language="kotlin"/>
</extensions>
</idea-plugin>