mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
cleanup [platform]: dead code; deprecated API; typos; formatting
GitOrigin-RevId: 41d8ae44e3b577b502dec1a75ad8f0a3b0d6b45e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6b7ecb38dc
commit
ad91c3a8ec
@@ -17,7 +17,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
* {@link PsiReferenceProvider#getReferencesByElement(PsiElement, com.intellij.util.ProcessingContext)}.
|
||||
*/
|
||||
public abstract class PsiReferenceRegistrar implements UserDataHolder {
|
||||
|
||||
public static final double DEFAULT_PRIORITY = 0.0;
|
||||
public static final double HIGHER_PRIORITY = 100.0;
|
||||
public static final double LOWER_PRIORITY = -100.0;
|
||||
@@ -27,7 +26,8 @@ public abstract class PsiReferenceRegistrar implements UserDataHolder {
|
||||
/**
|
||||
* Register reference provider with default priority ({@link #DEFAULT_PRIORITY}).
|
||||
*
|
||||
* @param pattern reference place description. See {@link com.intellij.patterns.StandardPatterns}, {@link com.intellij.patterns.PlatformPatterns} and their extenders.
|
||||
* @param pattern reference place description. See {@link com.intellij.patterns.StandardPatterns},
|
||||
* {@link com.intellij.patterns.PlatformPatterns} and their extenders.
|
||||
* @param provider provider to be registered
|
||||
*/
|
||||
public void registerReferenceProvider(@NotNull ElementPattern<? extends PsiElement> pattern, @NotNull PsiReferenceProvider provider) {
|
||||
@@ -37,13 +37,16 @@ public abstract class PsiReferenceRegistrar implements UserDataHolder {
|
||||
/**
|
||||
* Register reference provider with custom priority.
|
||||
*
|
||||
* @param pattern reference place description. See {@link com.intellij.patterns.StandardPatterns}, {@link com.intellij.patterns.PlatformPatterns} and their extenders.
|
||||
* @param pattern reference place description. See {@link com.intellij.patterns.StandardPatterns},
|
||||
* {@link com.intellij.patterns.PlatformPatterns} and their extenders.
|
||||
* @param provider provider to be registered
|
||||
* @param priority see {@link #DEFAULT_PRIORITY), {@link #HIGHER_PRIORITY}, {@link #LOWER_PRIORITY}
|
||||
*/
|
||||
public abstract <T extends PsiElement> void registerReferenceProvider(@NotNull ElementPattern<T> pattern,
|
||||
@NotNull PsiReferenceProvider provider,
|
||||
double priority);
|
||||
public abstract <T extends PsiElement> void registerReferenceProvider(
|
||||
@NotNull ElementPattern<T> pattern,
|
||||
@NotNull PsiReferenceProvider provider,
|
||||
double priority
|
||||
);
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T getUserData(@NotNull Key<T> key) {
|
||||
|
||||
+8
-5
@@ -1,5 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
package com.intellij.psi.impl.source.resolve.reference;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -16,7 +15,8 @@ import java.util.List;
|
||||
public interface ProviderBinding {
|
||||
class ProviderInfo<T> {
|
||||
static final ProviderInfo<?>[] EMPTY_ARRAY = new ProviderInfo[0];
|
||||
static final ArrayFactory<ProviderInfo<?>> ARRAY_FACTORY = n -> n == 0 ? ProviderInfo.EMPTY_ARRAY : new ProviderInfo[n];
|
||||
static final ArrayFactory<ProviderInfo<?>> ARRAY_FACTORY = n -> n == 0 ? EMPTY_ARRAY : new ProviderInfo[n];
|
||||
|
||||
final @NotNull PsiReferenceProvider provider;
|
||||
final @NotNull T processingContext;
|
||||
final double priority;
|
||||
@@ -32,9 +32,12 @@ public interface ProviderBinding {
|
||||
return "ProviderInfo{provider=" + provider + ", priority=" + priority + '}';
|
||||
}
|
||||
}
|
||||
void addAcceptableReferenceProviders(@NotNull PsiElement position,
|
||||
@NotNull List<? super ProviderInfo<ProcessingContext>> list,
|
||||
@NotNull PsiReferenceService.Hints hints);
|
||||
|
||||
void addAcceptableReferenceProviders(
|
||||
@NotNull PsiElement position,
|
||||
@NotNull List<? super ProviderInfo<ProcessingContext>> list,
|
||||
@NotNull PsiReferenceService.Hints hints
|
||||
);
|
||||
|
||||
void unregisterProvider(@NotNull PsiReferenceProvider provider);
|
||||
}
|
||||
|
||||
+46
-38
@@ -46,20 +46,19 @@ public class PsiReferenceRegistrarImpl extends PsiReferenceRegistrar {
|
||||
|
||||
PsiReferenceRegistrarImpl() {
|
||||
myBindingCache = ConcurrentFactoryMap.createMap(key -> {
|
||||
List<ProviderBinding> result = new SmartList<>();
|
||||
for (Class<?> bindingClass : myBindingsMap.keySet()) {
|
||||
if (bindingClass.isAssignableFrom(key)) {
|
||||
result.add(myBindingsMap.get(bindingClass));
|
||||
}
|
||||
}
|
||||
for (Class<?> bindingClass : myNamedBindingsMap.keySet()) {
|
||||
if (bindingClass.isAssignableFrom(key)) {
|
||||
result.add(myNamedBindingsMap.get(bindingClass));
|
||||
}
|
||||
}
|
||||
return result.toArray(new ProviderBinding[0]);
|
||||
}
|
||||
);
|
||||
List<ProviderBinding> result = new SmartList<>();
|
||||
for (Class<?> bindingClass : myBindingsMap.keySet()) {
|
||||
if (bindingClass.isAssignableFrom(key)) {
|
||||
result.add(myBindingsMap.get(bindingClass));
|
||||
}
|
||||
}
|
||||
for (Class<?> bindingClass : myNamedBindingsMap.keySet()) {
|
||||
if (bindingClass.isAssignableFrom(key)) {
|
||||
result.add(myNamedBindingsMap.get(bindingClass));
|
||||
}
|
||||
}
|
||||
return result.toArray(new ProviderBinding[0]);
|
||||
});
|
||||
}
|
||||
|
||||
void markInitialized() {
|
||||
@@ -74,16 +73,20 @@ public class PsiReferenceRegistrarImpl extends PsiReferenceRegistrar {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends PsiElement> void registerReferenceProvider(@NotNull ElementPattern<T> pattern,
|
||||
@NotNull PsiReferenceProvider provider,
|
||||
double priority) {
|
||||
public <T extends PsiElement> void registerReferenceProvider(
|
||||
@NotNull ElementPattern<T> pattern,
|
||||
@NotNull PsiReferenceProvider provider,
|
||||
double priority
|
||||
) {
|
||||
registerReferenceProvider(pattern, provider, priority, null);
|
||||
}
|
||||
|
||||
public <T extends PsiElement> void registerReferenceProvider(@NotNull ElementPattern<T> pattern,
|
||||
@NotNull PsiReferenceProvider provider,
|
||||
double priority,
|
||||
@Nullable Disposable parentDisposable) {
|
||||
public <T extends PsiElement> void registerReferenceProvider(
|
||||
@NotNull ElementPattern<T> pattern,
|
||||
@NotNull PsiReferenceProvider provider,
|
||||
double priority,
|
||||
@Nullable Disposable parentDisposable
|
||||
) {
|
||||
if (myInitialized && !ApplicationManager.getApplication().isUnitTestMode() && parentDisposable == null) {
|
||||
LOG.error("Reference provider registration is only allowed from PsiReferenceContributor");
|
||||
}
|
||||
@@ -98,9 +101,8 @@ public class PsiReferenceRegistrarImpl extends PsiReferenceRegistrar {
|
||||
List<PatternCondition<? super String>> conditions1 = nameCondition.getNamePattern().getCondition().getConditions();
|
||||
for (PatternCondition<? super String> condition1 : conditions1) {
|
||||
if (condition1 instanceof ValuePatternCondition) {
|
||||
Collection<String> strings = ((ValuePatternCondition)condition1).getValues();
|
||||
registerNamedReferenceProvider(ArrayUtilRt.toStringArray(strings), nameCondition, scope, true, provider, priority, pattern,
|
||||
parentDisposable);
|
||||
@SuppressWarnings({"unchecked", "rawtypes"}) Collection<String> strings = ((ValuePatternCondition)condition1).getValues();
|
||||
registerNamedReferenceProvider(ArrayUtilRt.toStringArray(strings), nameCondition, scope, true, provider, priority, pattern, parentDisposable);
|
||||
return;
|
||||
}
|
||||
if (condition1 instanceof CaseInsensitiveValuePatternCondition) {
|
||||
@@ -127,7 +129,7 @@ public class PsiReferenceRegistrarImpl extends PsiReferenceRegistrar {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PsiReferenceRegistrarImpl cleanuper for " + provider +" ("+provider.getClass()+")";
|
||||
return "PsiReferenceRegistrarImpl cleaner for " + provider + " (" + provider.getClass() + ")";
|
||||
}
|
||||
};
|
||||
Disposer.register(parentDisposable, disposable);
|
||||
@@ -152,14 +154,16 @@ public class PsiReferenceRegistrarImpl extends PsiReferenceRegistrar {
|
||||
clearBindingsCache();
|
||||
}
|
||||
|
||||
private void registerNamedReferenceProvider(String @NotNull [] names,
|
||||
PsiNamePatternCondition<?> nameCondition,
|
||||
@NotNull Class<?> scopeClass,
|
||||
boolean caseSensitive,
|
||||
@NotNull PsiReferenceProvider provider,
|
||||
double priority,
|
||||
@NotNull ElementPattern<?> pattern,
|
||||
@Nullable Disposable parentDisposable) {
|
||||
private void registerNamedReferenceProvider(
|
||||
String @NotNull [] names,
|
||||
PsiNamePatternCondition<?> nameCondition,
|
||||
@NotNull Class<?> scopeClass,
|
||||
boolean caseSensitive,
|
||||
@NotNull PsiReferenceProvider provider,
|
||||
double priority,
|
||||
@NotNull ElementPattern<?> pattern,
|
||||
@Nullable Disposable parentDisposable
|
||||
) {
|
||||
NamedObjectProviderBinding providerBinding = myNamedBindingsMap.get(scopeClass);
|
||||
|
||||
if (providerBinding == null) {
|
||||
@@ -189,9 +193,10 @@ public class PsiReferenceRegistrarImpl extends PsiReferenceRegistrar {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Unmodifiable
|
||||
@NotNull List<ProviderBinding.ProviderInfo<ProcessingContext>> getPairsByElement(@NotNull PsiElement element,
|
||||
@NotNull PsiReferenceService.Hints hints) {
|
||||
@Unmodifiable @NotNull List<ProviderBinding.ProviderInfo<ProcessingContext>> getPairsByElement(
|
||||
@NotNull PsiElement element,
|
||||
@NotNull PsiReferenceService.Hints hints
|
||||
) {
|
||||
ProviderBinding[] bindings = myBindingCache.get(element.getClass());
|
||||
if (bindings.length == 0) return Collections.emptyList();
|
||||
|
||||
@@ -201,9 +206,12 @@ public class PsiReferenceRegistrarImpl extends PsiReferenceRegistrar {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public @Unmodifiable @NotNull List<PsiReferenceProvider> getPsiReferenceProvidersByElement(@NotNull PsiElement element,
|
||||
@NotNull PsiReferenceService.Hints hints) {
|
||||
public @Unmodifiable @NotNull List<PsiReferenceProvider> getPsiReferenceProvidersByElement(
|
||||
@NotNull PsiElement element,
|
||||
@NotNull PsiReferenceService.Hints hints
|
||||
) {
|
||||
return ContainerUtil.map(getPairsByElement(element, hints), info -> info.provider);
|
||||
}
|
||||
}
|
||||
|
||||
+29
-25
@@ -45,18 +45,17 @@ public final class ReferenceProvidersRegistryImpl extends ReferenceProvidersRegi
|
||||
|
||||
private final Map<Language, PsiReferenceRegistrarImpl> myRegistrars = new ConcurrentHashMap<>();
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public ReferenceProvidersRegistryImpl() {
|
||||
if (ApplicationManager.getApplication().getExtensionArea().hasExtensionPoint(PsiReferenceContributor.EP_NAME)) {
|
||||
PsiReferenceContributor.EP_NAME.addExtensionPointListener(new ExtensionPointListener<KeyedLazyInstance<PsiReferenceContributor>>() {
|
||||
@Override
|
||||
public void extensionAdded(@NotNull KeyedLazyInstance<PsiReferenceContributor> extension,
|
||||
@NotNull PluginDescriptor pluginDescriptor) {
|
||||
public void extensionAdded(@NotNull KeyedLazyInstance<PsiReferenceContributor> extension, @NotNull PluginDescriptor pluginDescriptor) {
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void extensionRemoved(@NotNull KeyedLazyInstance<PsiReferenceContributor> extension,
|
||||
@NotNull PluginDescriptor pluginDescriptor) {
|
||||
public void extensionRemoved(@NotNull KeyedLazyInstance<PsiReferenceContributor> extension, @NotNull PluginDescriptor pluginDescriptor) {
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -75,7 +74,7 @@ public final class ReferenceProvidersRegistryImpl extends ReferenceProvidersRegi
|
||||
private static @NotNull PsiReferenceRegistrarImpl createRegistrar(@NotNull Language language) {
|
||||
PsiReferenceRegistrarImpl registrar = new PsiReferenceRegistrarImpl();
|
||||
for (PsiReferenceContributor contributor : CONTRIBUTOR_EXTENSION.allForLanguageOrAny(language)) {
|
||||
registerContributedReferenceProviders(registrar, contributor);
|
||||
contributor.registerReferenceProviders(registrar);
|
||||
}
|
||||
|
||||
List<PsiReferenceProviderBean> referenceProviderBeans = REFERENCE_PROVIDER_EXTENSION.allForLanguageOrAny(language);
|
||||
@@ -83,7 +82,7 @@ public final class ReferenceProvidersRegistryImpl extends ReferenceProvidersRegi
|
||||
ElementPattern<PsiElement> pattern = providerBean.createElementPattern();
|
||||
if (pattern != null) {
|
||||
registrar.registerReferenceProvider(pattern, new PsiReferenceProvider() {
|
||||
PsiReferenceProvider myProvider;
|
||||
private PsiReferenceProvider myProvider;
|
||||
|
||||
@Override
|
||||
public PsiReference @NotNull [] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
|
||||
@@ -104,11 +103,6 @@ public final class ReferenceProvidersRegistryImpl extends ReferenceProvidersRegi
|
||||
return registrar;
|
||||
}
|
||||
|
||||
private static void registerContributedReferenceProviders(@NotNull PsiReferenceRegistrarImpl registrar,
|
||||
@NotNull PsiReferenceContributor contributor) {
|
||||
contributor.registerReferenceProviders(registrar);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Override
|
||||
public @NotNull PsiReferenceRegistrarImpl getRegistrar(@NotNull Language language) {
|
||||
@@ -130,9 +124,12 @@ public final class ReferenceProvidersRegistryImpl extends ReferenceProvidersRegi
|
||||
// 1. we create priorities map: "priority" -> non-empty references from providers
|
||||
// if provider returns EMPTY_ARRAY or array with "null" references then this provider isn't added in priorities map.
|
||||
// 2. references with the highest priority are added "as is"
|
||||
// 3. all other references are added only they could be correctly merged with any reference with higher priority (ReferenceRange.containsRangeInElement(higherPriorityRef, lowerPriorityRef)
|
||||
protected PsiReference @NotNull [] doGetReferencesFromProviders(@NotNull PsiElement context,
|
||||
@NotNull PsiReferenceService.Hints hints) {
|
||||
// 3. all other references are added only they could be correctly merged with any reference with higher priority
|
||||
// (ReferenceRange.containsRangeInElement(higherPriorityRef, lowerPriorityRef)
|
||||
protected PsiReference @NotNull [] doGetReferencesFromProviders(
|
||||
@NotNull PsiElement context,
|
||||
@NotNull PsiReferenceService.Hints hints
|
||||
) {
|
||||
List<ProviderBinding.ProviderInfo<ProcessingContext>> providers = getRegistrar(context.getLanguage()).getPairsByElement(context, hints);
|
||||
|
||||
Double2ObjectMap<List<PsiReference[]>> allReferencesMap = mapNotEmptyReferencesFromProviders(context, providers);
|
||||
@@ -152,8 +149,10 @@ public final class ReferenceProvidersRegistryImpl extends ReferenceProvidersRegi
|
||||
|
||||
// we create priorities map: "priority" -> non-empty references from providers
|
||||
// if provider returns EMPTY_ARRAY or array with "null" references then this provider isn't added in priorities map.
|
||||
private static @NotNull Double2ObjectMap<List<PsiReference[]>> mapNotEmptyReferencesFromProviders(@NotNull PsiElement context,
|
||||
@NotNull List<? extends ProviderBinding.ProviderInfo<ProcessingContext>> providers) {
|
||||
private static @NotNull Double2ObjectMap<List<PsiReference[]>> mapNotEmptyReferencesFromProviders(
|
||||
@NotNull PsiElement context,
|
||||
@NotNull List<? extends ProviderBinding.ProviderInfo<ProcessingContext>> providers
|
||||
) {
|
||||
Double2ObjectOpenHashMap<List<PsiReference[]>> map = new Double2ObjectOpenHashMap<>();
|
||||
for (ProviderBinding.ProviderInfo<ProcessingContext> info : providers) {
|
||||
PsiReference[] refs = getReferences(context, info);
|
||||
@@ -172,19 +171,22 @@ public final class ReferenceProvidersRegistryImpl extends ReferenceProvidersRegi
|
||||
return map;
|
||||
}
|
||||
|
||||
private static PsiReference @NotNull [] getReferences(@NotNull PsiElement context,
|
||||
@NotNull ProviderBinding.ProviderInfo<ProcessingContext> providerInfo) {
|
||||
private static PsiReference @NotNull [] getReferences(
|
||||
@NotNull PsiElement context,
|
||||
@NotNull ProviderBinding.ProviderInfo<ProcessingContext> providerInfo
|
||||
) {
|
||||
try {
|
||||
return providerInfo.provider.getReferencesByElement(context, providerInfo.processingContext);
|
||||
}
|
||||
catch (IndexNotReadyException ignored) {
|
||||
}
|
||||
catch (IndexNotReadyException ignored) { }
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
private static @NotNull List<PsiReference> getLowerPriorityReferences(@NotNull Double2ObjectMap<List<PsiReference[]>> allReferencesMap,
|
||||
double maxPriority,
|
||||
@NotNull List<? extends PsiReference> maxPriorityRefs) {
|
||||
private static @NotNull List<PsiReference> getLowerPriorityReferences(
|
||||
@NotNull Double2ObjectMap<List<PsiReference[]>> allReferencesMap,
|
||||
double maxPriority,
|
||||
@NotNull List<? extends PsiReference> maxPriorityRefs
|
||||
) {
|
||||
List<PsiReference> result = new SmartList<>();
|
||||
for (Double2ObjectMap.Entry<List<PsiReference[]>> entry : Double2ObjectMaps.fastIterable(allReferencesMap)) {
|
||||
if (maxPriority != entry.getDoubleKey()) {
|
||||
@@ -198,8 +200,10 @@ public final class ReferenceProvidersRegistryImpl extends ReferenceProvidersRegi
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean haveNotIntersectedTextRanges(@NotNull List<? extends PsiReference> higherPriorityRefs,
|
||||
PsiReference @NotNull [] lowerPriorityRefs) {
|
||||
private static boolean haveNotIntersectedTextRanges(
|
||||
@NotNull List<? extends PsiReference> higherPriorityRefs,
|
||||
PsiReference @NotNull [] lowerPriorityRefs
|
||||
) {
|
||||
for (PsiReference ref : lowerPriorityRefs) {
|
||||
if (ref != null) {
|
||||
for (PsiReference reference : higherPriorityRefs) {
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@
|
||||
package com.intellij.internal.statistic.devkit
|
||||
|
||||
import com.intellij.internal.statistic.StatisticsBundle
|
||||
import com.intellij.internal.statistic.eventLog.FUS_RECORDER
|
||||
import com.intellij.internal.statistic.eventLog.StatisticsEventLogProviderUtil
|
||||
import com.intellij.internal.statistic.eventLog.StatisticsEventLoggerProvider
|
||||
import com.intellij.internal.statistic.utils.StatisticsRecorderUtil
|
||||
@@ -10,7 +11,7 @@ import com.intellij.notification.NotificationType
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
internal object StatisticsDevKitUtil {
|
||||
const val DEFAULT_RECORDER = "FUS"
|
||||
const val DEFAULT_RECORDER = FUS_RECORDER
|
||||
const val STATISTICS_NOTIFICATION_GROUP_ID = "FeatureUsageStatistics"
|
||||
|
||||
fun getLogProvidersInTestMode(): List<StatisticsEventLoggerProvider> {
|
||||
|
||||
@@ -2,8 +2,8 @@ java.code.block=Java Code Block
|
||||
java.expression=Java Expression
|
||||
java.method=Java Method
|
||||
|
||||
inspections.group.path=Plugin DevKit
|
||||
inspections.group.code=Code
|
||||
inspections.group.path=Plugin Dev
|
||||
inspections.highlight.visitor.internal.display.name=Good code is red
|
||||
|
||||
#PSI Viewer Debugger
|
||||
@@ -19,4 +19,4 @@ psi.viewer.show.whitespace.action = Show Whitespace
|
||||
psi.viewer.show.whitespace.description = Show whitespace nodes in the PSI tree
|
||||
psi.viewer.show.tree.nodes.action = Show Tree Nodes
|
||||
psi.viewer.show.tree.nodes.description = Show tree nodes in the PSI tree
|
||||
psi.viewer.debug.evaluation.failed=Failed to find PSI structure
|
||||
psi.viewer.debug.evaluation.failed=Failed to find PSI structure
|
||||
|
||||
+30
-41
@@ -4,72 +4,61 @@ package org.jetbrains.idea.devkit.inspections;
|
||||
import com.intellij.codeInspection.LocalInspectionEP;
|
||||
import com.intellij.testFramework.fixtures.BasePlatformTestCase;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class DevkitInspectionsRegistrationCheckTest extends BasePlatformTestCase {
|
||||
private static final int EXPECTED_INSPECTIONS_NUMBER = 94;
|
||||
|
||||
/**
|
||||
* Inspections that are finished and intentionally disabled.
|
||||
*/
|
||||
private static final List<String> DISABLED_INSPECTIONS =
|
||||
Stream.of(
|
||||
"SerializableCtor",
|
||||
"StatisticsCollectorNotRegistered"
|
||||
).sorted().toList();
|
||||
private static final List<String> DISABLED_INSPECTIONS = List.of(
|
||||
"SerializableCtor",
|
||||
"StatisticsCollectorNotRegistered"
|
||||
);
|
||||
|
||||
/**
|
||||
* Inspections which implementation is in progress
|
||||
* or are finished but not battle-tested yet and may require improvements/polishing.
|
||||
* Inspections which implementation is in progress or are finished but not battle-tested yet and may require improvements/polishing.
|
||||
*/
|
||||
private static final List<String> WIP_INSPECTIONS =
|
||||
Stream.of("ExtensionClassShouldBeFinalAndNonPublic",
|
||||
"CanBeDumbAware",
|
||||
"CancellationCheckInLoops",
|
||||
"ThreadingConcurrency",
|
||||
"CallingMethodShouldBeRequiresBlockingContext",
|
||||
"PotentialDeadlockInServiceInitialization",
|
||||
"ObsoleteDispatchersEdt",
|
||||
"PathAnnotationInspection"
|
||||
).sorted().toList();
|
||||
private static final List<String> WIP_INSPECTIONS = List.of(
|
||||
"ExtensionClassShouldBeFinalAndNonPublic",
|
||||
"CanBeDumbAware",
|
||||
"CancellationCheckInLoops",
|
||||
"ThreadingConcurrency",
|
||||
"CallingMethodShouldBeRequiresBlockingContext",
|
||||
"PotentialDeadlockInServiceInitialization",
|
||||
"ObsoleteDispatchersEdt",
|
||||
"PathAnnotationInspection"
|
||||
);
|
||||
|
||||
public void testNumberOfKnownDevKitInspections() {
|
||||
List<LocalInspectionEP> devkitInspections = getDevKitInspections();
|
||||
assertEquals(
|
||||
"""
|
||||
Mismatch in total number of DevKit inspections.
|
||||
* If you've just added a DevKit inspection, then just increment DevkitInspectionsRegistrationCheckTest#EXPECTED_INSPECTIONS_NUMBER.
|
||||
* Otherwise, check classpath in test run configuration (intellij.devkit.plugin.main)""",
|
||||
EXPECTED_INSPECTIONS_NUMBER, devkitInspections.size()
|
||||
EXPECTED_INSPECTIONS_NUMBER, getDevKitInspections().count()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates all DevKit inspections that are disabled by default match the expected known set.
|
||||
*/
|
||||
/**
|
||||
* Validates all DevKit inspections that are disabled by default match the expected known set.
|
||||
*/
|
||||
public void testKnownDisabledByDefaultInspections() {
|
||||
List<LocalInspectionEP> devkitInspections = getDevKitInspections();
|
||||
List<LocalInspectionEP> disabledInspections = ContainerUtil.filter(devkitInspections, ep -> !ep.enabledByDefault);
|
||||
List<String> disabledInspectionShortNames = new ArrayList<>(ContainerUtil.map(disabledInspections, ep -> ep.getShortName()));
|
||||
Collections.sort(disabledInspectionShortNames);
|
||||
|
||||
assertContainsElements("Mismatch in known disabled inspections", disabledInspectionShortNames, DISABLED_INSPECTIONS);
|
||||
|
||||
List<String> allKnownDisabledInspections = new ArrayList<>(ContainerUtil.concat(DISABLED_INSPECTIONS, WIP_INSPECTIONS));
|
||||
Collections.sort(allKnownDisabledInspections);
|
||||
|
||||
assertSameElements("Mismatch in known WIP inspections", disabledInspectionShortNames, allKnownDisabledInspections);
|
||||
var disabledInspectionShortNames = getDevKitInspections()
|
||||
.filter(ep -> !ep.enabledByDefault)
|
||||
.map(ep -> ep.getShortName())
|
||||
.toList();
|
||||
var allKnownDisabledInspections = ContainerUtil.concat(DISABLED_INSPECTIONS, WIP_INSPECTIONS);
|
||||
assertThat(disabledInspectionShortNames).containsExactlyInAnyOrderElementsOf(allKnownDisabledInspections);
|
||||
}
|
||||
|
||||
private static @NotNull List<LocalInspectionEP> getDevKitInspections() {
|
||||
List<LocalInspectionEP> devkitInspections = ContainerUtil.filter(LocalInspectionEP.LOCAL_INSPECTION.getExtensionList(), ep -> {
|
||||
return "DevKit".equals(ep.getPluginDescriptor().getPluginId().getIdString());
|
||||
});
|
||||
return devkitInspections;
|
||||
private static Stream<LocalInspectionEP> getDevKitInspections() {
|
||||
return LocalInspectionEP.LOCAL_INSPECTION.getExtensionList().stream()
|
||||
.filter(ep -> "DevKit".equals(ep.getPluginDescriptor().getPluginId().getIdString()));
|
||||
}
|
||||
}
|
||||
|
||||
+7
-10
@@ -15,22 +15,19 @@ import java.util.List;
|
||||
public class PropertyReference extends PropertyReferenceBase implements LocalQuickFixProvider {
|
||||
private final @Nullable String myBundleName;
|
||||
|
||||
public PropertyReference(final @NotNull String key, final @NotNull PsiElement element, final @Nullable String bundleName, final boolean soft, final TextRange range) {
|
||||
super(key, soft, element, range);
|
||||
public PropertyReference(@NotNull String key, @NotNull PsiElement element, @Nullable String bundleName, boolean soft) {
|
||||
super(key, soft, element);
|
||||
myBundleName = bundleName;
|
||||
}
|
||||
|
||||
public PropertyReference(@NotNull String key, @NotNull PsiElement element, final @Nullable String bundleName, final boolean soft) {
|
||||
super(key, soft, element);
|
||||
public PropertyReference(@NotNull String key, @NotNull PsiElement element, @Nullable String bundleName, boolean soft, TextRange range) {
|
||||
super(key, soft, element, range);
|
||||
myBundleName = bundleName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable List<PropertiesFile> getPropertiesFiles() {
|
||||
if (myBundleName == null) {
|
||||
return null;
|
||||
}
|
||||
return retrievePropertyFilesByBundleName(myBundleName, myElement);
|
||||
return myBundleName == null ? null : retrievePropertyFilesByBundleName(myBundleName, myElement);
|
||||
}
|
||||
|
||||
protected List<PropertiesFile> retrievePropertyFilesByBundleName(String bundleName, PsiElement element) {
|
||||
@@ -39,8 +36,8 @@ public class PropertyReference extends PropertyReferenceBase implements LocalQui
|
||||
|
||||
@Override
|
||||
public @NotNull LocalQuickFix @Nullable [] getQuickFixes() {
|
||||
List<PropertiesFile> propertiesFiles = retrievePropertyFilesByBundleName(myBundleName, getElement());
|
||||
LocalQuickFix fix = PropertiesQuickFixFactory.getInstance().createCreatePropertyFix(myElement, myKey, propertiesFiles);
|
||||
var propertiesFiles = retrievePropertyFilesByBundleName(myBundleName, getElement());
|
||||
var fix = PropertiesQuickFixFactory.getInstance().createCreatePropertyFix(myElement, myKey, propertiesFiles);
|
||||
return new LocalQuickFix[] {fix};
|
||||
}
|
||||
}
|
||||
|
||||
+23
-33
@@ -30,17 +30,16 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class PropertyReferenceBase implements PsiPolyVariantReference, EmptyResolveMessageProvider {
|
||||
|
||||
protected final String myKey;
|
||||
protected final PsiElement myElement;
|
||||
protected boolean mySoft;
|
||||
private final boolean mySoft;
|
||||
private final TextRange myTextRange;
|
||||
|
||||
public PropertyReferenceBase(@NotNull String key, final boolean soft, @NotNull PsiElement element) {
|
||||
public PropertyReferenceBase(@NotNull String key, boolean soft, @NotNull PsiElement element) {
|
||||
this(key, soft, element, ElementManipulators.getValueTextRange(element));
|
||||
}
|
||||
|
||||
public PropertyReferenceBase(@NotNull String key, final boolean soft, @NotNull PsiElement element, TextRange range) {
|
||||
public PropertyReferenceBase(@NotNull String key, boolean soft, @NotNull PsiElement element, TextRange range) {
|
||||
myKey = key;
|
||||
mySoft = soft;
|
||||
myElement = element;
|
||||
@@ -49,7 +48,7 @@ public abstract class PropertyReferenceBase implements PsiPolyVariantReference,
|
||||
|
||||
@Override
|
||||
public PsiElement resolve() {
|
||||
ResolveResult[] resolveResults = multiResolve(false);
|
||||
var resolveResults = multiResolve(false);
|
||||
return resolveResults.length == 1 ? resolveResults[0].getElement() : null;
|
||||
}
|
||||
|
||||
@@ -58,11 +57,10 @@ public abstract class PropertyReferenceBase implements PsiPolyVariantReference,
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PropertyReferenceBase other = (PropertyReferenceBase)o;
|
||||
|
||||
var other = (PropertyReferenceBase)o;
|
||||
return getElement() == other.getElement() && getKeyText().equals(other.getKeyText());
|
||||
}
|
||||
|
||||
@@ -99,8 +97,8 @@ public abstract class PropertyReferenceBase implements PsiPolyVariantReference,
|
||||
@Override
|
||||
public boolean isReferenceTo(@NotNull PsiElement element) {
|
||||
if (!isProperty(element)) return false;
|
||||
for (ResolveResult result : multiResolve(false)) {
|
||||
final PsiElement el = result.getElement();
|
||||
for (var result : multiResolve(false)) {
|
||||
var el = result.getElement();
|
||||
if (el != null && el.isEquivalentTo(element)) return true;
|
||||
}
|
||||
return false;
|
||||
@@ -110,10 +108,6 @@ public abstract class PropertyReferenceBase implements PsiPolyVariantReference,
|
||||
variants.add(property);
|
||||
}
|
||||
|
||||
protected void setSoft(final boolean soft) {
|
||||
mySoft = soft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSoft() {
|
||||
return mySoft;
|
||||
@@ -125,37 +119,33 @@ public abstract class PropertyReferenceBase implements PsiPolyVariantReference,
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolveResult @NotNull [] multiResolve(final boolean incompleteCode) {
|
||||
final String key = getKeyText();
|
||||
public ResolveResult @NotNull [] multiResolve(boolean incompleteCode) {
|
||||
var key = getKeyText();
|
||||
|
||||
List<IProperty> properties;
|
||||
final List<PropertiesFile> propertiesFiles = getPropertiesFiles();
|
||||
var propertiesFiles = getPropertiesFiles();
|
||||
if (propertiesFiles == null) {
|
||||
properties = PropertiesImplUtil.findPropertiesByKey(getElement().getProject(), key);
|
||||
}
|
||||
else {
|
||||
properties = new ArrayList<>();
|
||||
for (PropertiesFile propertiesFile : propertiesFiles) {
|
||||
for (var propertiesFile : propertiesFiles) {
|
||||
properties.addAll(propertiesFile.findPropertiesByKey(key));
|
||||
}
|
||||
}
|
||||
// put default properties file first
|
||||
ContainerUtil.quickSort(properties, (o1, o2) -> {
|
||||
String name1 = o1.getPropertiesFile().getName();
|
||||
String name2 = o2.getPropertiesFile().getName();
|
||||
return Comparing.compare(name1, name2);
|
||||
});
|
||||
return getResolveResults(properties);
|
||||
}
|
||||
|
||||
private static ResolveResult @NotNull [] getResolveResults(List<? extends IProperty> properties) {
|
||||
if (properties.isEmpty()) return ResolveResult.EMPTY_ARRAY;
|
||||
|
||||
final ResolveResult[] results = new ResolveResult[properties.size()];
|
||||
for (int i = 0; i < properties.size(); i++) {
|
||||
IProperty property = properties.get(i);
|
||||
results[i] = new PsiElementResolveResult(property instanceof PsiElement ? (PsiElement)property : PomService.convertToPsi(
|
||||
(PsiTarget)property));
|
||||
// put default properties file first
|
||||
ContainerUtil.quickSort(properties, (o1, o2) -> {
|
||||
var name1 = o1.getPropertiesFile().getName();
|
||||
var name2 = o2.getPropertiesFile().getName();
|
||||
return Comparing.compare(name1, name2);
|
||||
});
|
||||
|
||||
var results = new ResolveResult[properties.size()];
|
||||
for (var i = 0; i < properties.size(); i++) {
|
||||
var property = properties.get(i);
|
||||
results[i] = new PsiElementResolveResult(property instanceof PsiElement psi ? psi : PomService.convertToPsi((PsiTarget)property));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -50,9 +50,11 @@ fun injectionHostUExpression(strict: Boolean = true): UExpressionPattern<UExpres
|
||||
val requestedPsi = processingContext.get(REQUESTED_PSI_ELEMENT)
|
||||
if (requestedPsi == null) {
|
||||
if (strict && ApplicationManager.getApplication().isUnitTestMode) {
|
||||
throw AssertionError("no ProcessingContext with `REQUESTED_PSI_ELEMENT` passed for `injectionHostUExpression`," +
|
||||
" please consider creating one using `UastPatterns.withRequestedPsi`, providing a source psi for which " +
|
||||
" this pattern was originally created, or make this `injectionHostUExpression` non-strict.")
|
||||
throw AssertionError(
|
||||
"no ProcessingContext with `REQUESTED_PSI_ELEMENT` passed for `injectionHostUExpression`," +
|
||||
" please consider creating one using `UastPatterns.withRequestedPsi`, providing a source psi for which " +
|
||||
" this pattern was originally created, or make this `injectionHostUExpression` non-strict."
|
||||
)
|
||||
}
|
||||
else return@filterWithContext !strict
|
||||
}
|
||||
@@ -109,6 +111,7 @@ open class UElementPattern<T : UElement, Self : UElementPattern<T, Self>>(clazz:
|
||||
it.uastParent?.let { parentPattern.accepts(it, context) } ?: false
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
fun withUastParentOrSelf(parentPattern: ElementPattern<out UElement>): Self = filterWithContext { it, context ->
|
||||
parentPattern.accepts(it, context) || it.uastParent?.let { parentPattern.accepts(it, context) } ?: false
|
||||
}
|
||||
@@ -126,14 +129,15 @@ open class UElementPattern<T : UElement, Self : UElementPattern<T, Self>>(clazz:
|
||||
|
||||
private val constructorOrMethodCall = setOf(UastCallKind.CONSTRUCTOR_CALL, UastCallKind.METHOD_CALL)
|
||||
|
||||
private fun isCallExpressionParameter(argumentExpression: UExpression,
|
||||
parameterIndex: Int,
|
||||
callPattern: ElementPattern<UCallExpression>, context: ProcessingContext): Boolean {
|
||||
private fun isCallExpressionParameter(
|
||||
argumentExpression: UExpression,
|
||||
parameterIndex: Int,
|
||||
callPattern: ElementPattern<UCallExpression>, context: ProcessingContext,
|
||||
): Boolean {
|
||||
val call = argumentExpression.uastParent.getUCallExpression(searchLimit = 2) ?: return false
|
||||
|
||||
return callPattern.accepts(call, context)
|
||||
&& call.kind in constructorOrMethodCall
|
||||
&& call.getArgumentForParameter(parameterIndex) == argumentExpression
|
||||
return callPattern.accepts(call, context) &&
|
||||
call.kind in constructorOrMethodCall &&
|
||||
call.getArgumentForParameter(parameterIndex) == argumentExpression
|
||||
}
|
||||
|
||||
private fun isPropertyAssignCall(argument: UElement, methodPattern: ElementPattern<out PsiMethod>, context: ProcessingContext): Boolean {
|
||||
@@ -158,8 +162,7 @@ class UCallExpressionPattern : UElementPattern<UCallExpression, UCallExpressionP
|
||||
|
||||
fun withAnyResolvedMethod(method: ElementPattern<out PsiMethod>): UCallExpressionPattern = withResolvedMethod(method, true)
|
||||
|
||||
fun withResolvedMethod(method: ElementPattern<out PsiMethod>,
|
||||
multiResolve: Boolean): UCallExpressionPattern {
|
||||
fun withResolvedMethod(method: ElementPattern<out PsiMethod>, multiResolve: Boolean): UCallExpressionPattern {
|
||||
val methodNames = method.condition.conditions
|
||||
.filterIsInstance<PsiNamePatternCondition<*>>()
|
||||
.flatMap { it.namePattern.condition.conditions }
|
||||
@@ -212,14 +215,13 @@ class UCallExpressionPattern : UElementPattern<UCallExpression, UCallExpressionP
|
||||
|
||||
fun constructor(className: String): UCallExpressionPattern = constructor(psiClass().withQualifiedName(className))
|
||||
|
||||
fun constructor(className: String, parameterCount: Int): UCallExpressionPattern = constructor(psiClass().withQualifiedName(className),
|
||||
parameterCount)
|
||||
fun constructor(className: String, parameterCount: Int): UCallExpressionPattern =
|
||||
constructor(psiClass().withQualifiedName(className), parameterCount)
|
||||
}
|
||||
|
||||
private val IS_UAST_ANNOTATION_PARAMETER: Key<Boolean> = Key.create("UAST_ANNOTATION_PARAMETER")
|
||||
|
||||
open class UExpressionPattern<T : UExpression, Self : UExpressionPattern<T, Self>>(clazz: Class<T>) : UElementPattern<T, Self>(clazz) {
|
||||
|
||||
fun annotationParam(@NonNls parameterName: String, annotationPattern: ElementPattern<UAnnotation>): Self =
|
||||
annotationParams(annotationPattern, string().equalTo(parameterName))
|
||||
|
||||
@@ -228,13 +230,13 @@ open class UExpressionPattern<T : UExpression, Self : UExpressionPattern<T, Self
|
||||
override fun accepts(uElement: T, context: ProcessingContext?): Boolean {
|
||||
val sharedContext = context?.sharedContext
|
||||
val isAnnotationParameter = sharedContext?.get(IS_UAST_ANNOTATION_PARAMETER, uElement)
|
||||
if (isAnnotationParameter == java.lang.Boolean.FALSE) {
|
||||
if (isAnnotationParameter == false) {
|
||||
return false
|
||||
}
|
||||
|
||||
val containingUAnnotationEntry = getContainingUAnnotationEntry(uElement)
|
||||
if (containingUAnnotationEntry == null) {
|
||||
sharedContext?.put(IS_UAST_ANNOTATION_PARAMETER, uElement, java.lang.Boolean.FALSE)
|
||||
sharedContext?.put(IS_UAST_ANNOTATION_PARAMETER, uElement, false)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -268,7 +270,6 @@ open class UExpressionPattern<T : UExpression, Self : UExpressionPattern<T, Self
|
||||
|
||||
fun setterParameter(methodPattern: ElementPattern<out PsiMethod>): Self {
|
||||
val callPattern = callExpression().withAnyResolvedMethod(methodPattern)
|
||||
|
||||
return filterWithContext("setterParameter") { it, context ->
|
||||
isPropertyAssignCall(it, methodPattern, context) ||
|
||||
isCallExpressionParameter(it, 0, callPattern, context)
|
||||
@@ -278,7 +279,6 @@ open class UExpressionPattern<T : UExpression, Self : UExpressionPattern<T, Self
|
||||
@JvmOverloads
|
||||
fun methodCallParameter(parameterIndex: Int, methodPattern: ElementPattern<out PsiMethod>, multiResolve: Boolean = true): Self {
|
||||
val callPattern = callExpression().withResolvedMethod(methodPattern, multiResolve)
|
||||
|
||||
return callParameter(parameterIndex, callPattern)
|
||||
}
|
||||
|
||||
@@ -321,7 +321,6 @@ fun uAnnotationQualifiedNamePattern(annotationQualifiedName: ElementPattern<Stri
|
||||
}
|
||||
|
||||
open class UDeclarationPattern<T : UDeclaration>(clazz: Class<T>) : UElementPattern<T, UDeclarationPattern<T>>(clazz) {
|
||||
|
||||
fun annotatedWith(@NotNull annotationQualifiedNames: List<String>): UDeclarationPattern<T> {
|
||||
return this.with(object : PatternCondition<UDeclaration>("annotatedWith") {
|
||||
override fun accepts(uDeclaration: UDeclaration, context: ProcessingContext?): Boolean {
|
||||
@@ -333,4 +332,4 @@ open class UDeclarationPattern<T : UDeclaration>(clazz: Class<T>) : UElementPatt
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@file:JvmName("UastReferenceRegistrar")
|
||||
|
||||
package com.intellij.psi
|
||||
|
||||
import com.intellij.openapi.util.Key
|
||||
@@ -17,55 +16,58 @@ import org.jetbrains.uast.expressions.UInjectionHost
|
||||
* Groups all UAST-based reference providers by chunks with the same priority and supported UElement types.
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun PsiReferenceRegistrar.registerUastReferenceProvider(pattern: (UElement, ProcessingContext) -> Boolean,
|
||||
provider: UastReferenceProvider,
|
||||
priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY) {
|
||||
fun PsiReferenceRegistrar.registerUastReferenceProvider(
|
||||
pattern: (UElement, ProcessingContext) -> Boolean,
|
||||
provider: UastReferenceProvider,
|
||||
priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY,
|
||||
) {
|
||||
val adapter = UastReferenceProviderAdapter(provider.supportedUElementTypes, provider)
|
||||
this.registerReferenceProvider(adaptPattern(pattern, provider.supportedUElementTypes), adapter, priority)
|
||||
registerReferenceProvider(adaptPattern(pattern, provider.supportedUElementTypes), adapter, priority)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun PsiReferenceRegistrar.registerUastReferenceProvider(pattern: ElementPattern<out UElement>,
|
||||
provider: UastReferenceProvider,
|
||||
priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY) {
|
||||
this.registerUastReferenceProvider(pattern::accepts, provider, priority)
|
||||
fun PsiReferenceRegistrar.registerUastReferenceProvider(
|
||||
pattern: ElementPattern<out UElement>,
|
||||
provider: UastReferenceProvider,
|
||||
priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY,
|
||||
) {
|
||||
registerUastReferenceProvider(pattern::accepts, provider, priority)
|
||||
}
|
||||
|
||||
fun uastInjectionHostReferenceProvider(provider: (UExpression, PsiLanguageInjectionHost) -> Array<PsiReference>): UastInjectionHostReferenceProvider =
|
||||
uastInjectionHostReferenceProvider(null, provider)
|
||||
fun uastInjectionHostReferenceProvider(
|
||||
provider: (UExpression, PsiLanguageInjectionHost) -> Array<PsiReference>
|
||||
): UastInjectionHostReferenceProvider = uastInjectionHostReferenceProvider(null, provider)
|
||||
|
||||
fun uastInjectionHostReferenceProvider(targetClass: Class<out PsiElement>?,
|
||||
provider: (UExpression, PsiLanguageInjectionHost) -> Array<PsiReference>): UastInjectionHostReferenceProvider =
|
||||
object : UastInjectionHostReferenceProvider() {
|
||||
override fun getReferencesForInjectionHost(uExpression: UExpression,
|
||||
host: PsiLanguageInjectionHost,
|
||||
context: ProcessingContext): Array<PsiReference> = provider(uExpression, host)
|
||||
fun uastInjectionHostReferenceProvider(
|
||||
targetClass: Class<out PsiElement>?,
|
||||
provider: (UExpression, PsiLanguageInjectionHost) -> Array<PsiReference>,
|
||||
): UastInjectionHostReferenceProvider = object : UastInjectionHostReferenceProvider() {
|
||||
override fun getReferencesForInjectionHost(
|
||||
uExpression: UExpression,
|
||||
host: PsiLanguageInjectionHost,
|
||||
context: ProcessingContext,
|
||||
): Array<PsiReference> = provider(uExpression, host)
|
||||
|
||||
override fun acceptsTarget(target: PsiElement): Boolean {
|
||||
return targetClass?.isInstance(target) ?: true
|
||||
}
|
||||
override fun acceptsTarget(target: PsiElement): Boolean = targetClass?.isInstance(target) ?: true
|
||||
|
||||
override fun toString(): String = "uastInjectionHostReferenceProvider($provider)"
|
||||
}
|
||||
|
||||
fun <T : UElement> uastReferenceProvider(cls: Class<T>, targetClass: Class<out PsiElement>?,
|
||||
provider: (T, PsiElement) -> Array<PsiReference>): UastReferenceProvider =
|
||||
object : UastReferenceProvider(cls) {
|
||||
override fun getReferencesByElement(element: UElement, context: ProcessingContext): Array<PsiReference> {
|
||||
return provider(cls.cast(element), getRequestedPsiElement(context))
|
||||
}
|
||||
|
||||
override fun acceptsTarget(target: PsiElement): Boolean {
|
||||
return targetClass?.isInstance(target) ?: true
|
||||
}
|
||||
|
||||
override fun toString(): String = "uastReferenceProvider($provider)"
|
||||
}
|
||||
|
||||
fun getRequestedPsiElement(context: ProcessingContext): PsiElement {
|
||||
return context[REQUESTED_PSI_ELEMENT]
|
||||
override fun toString(): String = "uastInjectionHostReferenceProvider($provider)"
|
||||
}
|
||||
|
||||
fun <T : UElement> uastReferenceProvider(
|
||||
cls: Class<T>, targetClass: Class<out PsiElement>?,
|
||||
provider: (T, PsiElement) -> Array<PsiReference>,
|
||||
): UastReferenceProvider = object : UastReferenceProvider(cls) {
|
||||
override fun getReferencesByElement(element: UElement, context: ProcessingContext): Array<PsiReference> {
|
||||
return provider(cls.cast(element), getRequestedPsiElement(context))
|
||||
}
|
||||
|
||||
override fun acceptsTarget(target: PsiElement): Boolean = targetClass?.isInstance(target) ?: true
|
||||
|
||||
override fun toString(): String = "uastReferenceProvider($provider)"
|
||||
}
|
||||
|
||||
fun getRequestedPsiElement(context: ProcessingContext): PsiElement = context[REQUESTED_PSI_ELEMENT]
|
||||
|
||||
fun <T : UElement> uastReferenceProvider(cls: Class<T>, provider: (T, PsiElement) -> Array<PsiReference>): UastReferenceProvider =
|
||||
uastReferenceProvider(cls, null, provider)
|
||||
|
||||
@@ -75,11 +77,13 @@ inline fun <reified T : UElement> uastReferenceProvider(noinline provider: (T, P
|
||||
internal val REQUESTED_PSI_ELEMENT: Key<PsiElement> = Key.create("REQUESTED_PSI_ELEMENT")
|
||||
internal val USAGE_PSI_ELEMENT: Key<PsiElement> = Key.create("USAGE_PSI_ELEMENT")
|
||||
|
||||
internal fun adaptPattern(pattern: (UElement, ProcessingContext) -> Boolean,
|
||||
supportedUElementTypes: List<Class<out UElement>>): ElementPattern<out PsiElement> {
|
||||
internal fun adaptPattern(
|
||||
pattern: (UElement, ProcessingContext) -> Boolean,
|
||||
supportedUElementTypes: List<Class<out UElement>>
|
||||
): ElementPattern<out PsiElement> {
|
||||
val uastPatternAdapter = UastPatternAdapter(pattern, supportedUElementTypes)
|
||||
|
||||
// optimisation until IDEA-211738 is implemented
|
||||
// optimization until IDEA-211738 is implemented
|
||||
if (supportedUElementTypes.size == 1 && supportedUElementTypes[0] == UInjectionHost::class.java) {
|
||||
return StandardPatterns.instanceOf(PsiLanguageInjectionHost::class.java).and(uastPatternAdapter)
|
||||
}
|
||||
@@ -88,8 +92,9 @@ internal fun adaptPattern(pattern: (UElement, ProcessingContext) -> Boolean,
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
fun uastReferenceProviderByUsage(provider: (UExpression, referencePsi: PsiLanguageInjectionHost, usagePsi: PsiElement) -> Array<PsiReference>): UastReferenceProvider =
|
||||
uastReferenceProviderByUsage(null, provider)
|
||||
fun uastReferenceProviderByUsage(
|
||||
provider: (UExpression, referencePsi: PsiLanguageInjectionHost, usagePsi: PsiElement) -> Array<PsiReference>
|
||||
): UastReferenceProvider = uastReferenceProviderByUsage(null, provider)
|
||||
|
||||
/**
|
||||
* Creates UAST reference provider that accepts additional PSI element that could be either the same as reference PSI element or reference
|
||||
@@ -98,24 +103,22 @@ fun uastReferenceProviderByUsage(provider: (UExpression, referencePsi: PsiLangua
|
||||
* @see registerReferenceProviderByUsage
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
fun uastReferenceProviderByUsage(targetClass: Class<out PsiElement>?,
|
||||
provider: (UExpression, referencePsi: PsiLanguageInjectionHost, usagePsi: PsiElement) -> Array<PsiReference>): UastReferenceProvider =
|
||||
object : UastReferenceProvider(UInjectionHost::class.java) {
|
||||
override fun getReferencesByElement(element: UElement, context: ProcessingContext): Array<PsiReference> {
|
||||
val uLiteral = element as? UExpression ?: return PsiReference.EMPTY_ARRAY
|
||||
val host = getRequestedPsiElement(context) as? PsiLanguageInjectionHost ?: return PsiReference.EMPTY_ARRAY
|
||||
val usagePsi = context[USAGE_PSI_ELEMENT] ?: getRequestedPsiElement(context)
|
||||
|
||||
return provider(uLiteral, host, usagePsi)
|
||||
}
|
||||
|
||||
override fun acceptsTarget(target: PsiElement): Boolean {
|
||||
return targetClass?.isInstance(target) ?: true
|
||||
}
|
||||
|
||||
override fun toString(): String = "uastByUsageReferenceProvider($provider)"
|
||||
fun uastReferenceProviderByUsage(
|
||||
targetClass: Class<out PsiElement>?,
|
||||
provider: (UExpression, referencePsi: PsiLanguageInjectionHost, usagePsi: PsiElement) -> Array<PsiReference>,
|
||||
): UastReferenceProvider = object : UastReferenceProvider(UInjectionHost::class.java) {
|
||||
override fun getReferencesByElement(element: UElement, context: ProcessingContext): Array<PsiReference> {
|
||||
val uLiteral = element as? UExpression ?: return PsiReference.EMPTY_ARRAY
|
||||
val host = getRequestedPsiElement(context) as? PsiLanguageInjectionHost ?: return PsiReference.EMPTY_ARRAY
|
||||
val usagePsi = context[USAGE_PSI_ELEMENT] ?: getRequestedPsiElement(context)
|
||||
return provider(uLiteral, host, usagePsi)
|
||||
}
|
||||
|
||||
override fun acceptsTarget(target: PsiElement): Boolean = targetClass?.isInstance(target) ?: true
|
||||
|
||||
override fun toString(): String = "uastByUsageReferenceProvider($provider)"
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a provider that will be called on the expressions that directly satisfy the [usagePattern] or at least one of the expression
|
||||
* usages satisfies the pattern if it was assigned to a variable. The provider will search for usages of variables only for expressions that
|
||||
@@ -125,21 +128,25 @@ fun uastReferenceProviderByUsage(targetClass: Class<out PsiElement>?,
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
@JvmOverloads
|
||||
fun PsiReferenceRegistrar.registerReferenceProviderByUsage(expressionPattern: ElementPattern<out UElement>,
|
||||
usagePattern: ElementPattern<out UElement>,
|
||||
provider: UastReferenceProvider,
|
||||
priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY) {
|
||||
this.registerUastReferenceProvider(usagePattern, provider, priority)
|
||||
fun PsiReferenceRegistrar.registerReferenceProviderByUsage(
|
||||
expressionPattern: ElementPattern<out UElement>,
|
||||
usagePattern: ElementPattern<out UElement>,
|
||||
provider: UastReferenceProvider,
|
||||
priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY,
|
||||
) {
|
||||
registerUastReferenceProvider(usagePattern, provider, priority)
|
||||
|
||||
if (Registry.`is`("uast.references.by.usage", true)) {
|
||||
val adapter = UastReferenceByUsageAdapter(expressionPattern, usagePattern, provider)
|
||||
this.registerReferenceProvider(adaptPattern(expressionPattern::accepts, adapter.supportedUElementTypes), adapter, priority)
|
||||
registerReferenceProvider(adaptPattern(expressionPattern::accepts, adapter.supportedUElementTypes), adapter, priority)
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
fun PsiReferenceRegistrar.registerReferenceProviderByUsage(usagePattern: ElementPattern<out UElement>,
|
||||
provider: UastReferenceProvider,
|
||||
priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY) {
|
||||
fun PsiReferenceRegistrar.registerReferenceProviderByUsage(
|
||||
usagePattern: ElementPattern<out UElement>,
|
||||
provider: UastReferenceProvider,
|
||||
priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY,
|
||||
) {
|
||||
registerReferenceProviderByUsage(uExpressionInVariable(), usagePattern, provider, priority)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("UastUtils")
|
||||
|
||||
package org.jetbrains.uast
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
@@ -18,7 +17,6 @@ import com.intellij.util.SmartList
|
||||
import one.util.streamex.StreamEx
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.uast.visitor.AbstractUastVisitor
|
||||
import java.io.File
|
||||
import java.util.stream.Stream
|
||||
|
||||
inline fun <reified T : UElement> UElement.getParentOfType(strict: Boolean = true): T? = getParentOfType(T::class.java, strict)
|
||||
@@ -87,7 +85,7 @@ fun <T : UElement> UElement.getParentOfType(
|
||||
fun UElement?.getUCallExpression(searchLimit: Int = Int.MAX_VALUE): UCallExpression? {
|
||||
if (this == null) return null
|
||||
var u: UElement? = this
|
||||
for (i in 1..searchLimit) {
|
||||
for (@Suppress("unused") i in 1..searchLimit) {
|
||||
if (u == null) break
|
||||
if (u is UCallExpression) return u
|
||||
|
||||
@@ -115,7 +113,7 @@ fun <T : UElement> PsiElement?.findContaining(clazz: Class<T>): T? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun <T : UElement> PsiElement?.findAnyContaining(vararg types: Class<out T>): T? = findAnyContaining(Int.Companion.MAX_VALUE, *types)
|
||||
fun <T : UElement> PsiElement?.findAnyContaining(vararg types: Class<out T>): T? = findAnyContaining(Int.MAX_VALUE, *types)
|
||||
|
||||
fun <T : UElement> PsiElement?.findAnyContaining(depthLimit: Int, vararg types: Class<out T>): T? {
|
||||
var element = this
|
||||
@@ -180,11 +178,10 @@ fun skipParenthesizedExprUp(elem: UElement?): UElement? {
|
||||
return parent
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a physical [File] for this file, or null if there is no such file on disk.
|
||||
*/
|
||||
fun UFile.getIoFile(): File? = sourcePsi.virtualFile?.let { VfsUtilCore.virtualToIoFile(it) }
|
||||
@Deprecated("avoid j.i.File use")
|
||||
@ApiStatus.ScheduledForRemoval
|
||||
@Suppress("IO_FILE_USAGE")
|
||||
fun UFile.getIoFile(): java.io.File? = sourcePsi.virtualFile?.let { VfsUtilCore.virtualToIoFile(it) }
|
||||
|
||||
@Deprecated("use UastFacade", ReplaceWith("UastFacade"))
|
||||
@ApiStatus.ScheduledForRemoval
|
||||
@@ -198,22 +195,9 @@ tailrec fun UElement.getUastContext(): UastContext {
|
||||
return (uastParent ?: error("PsiElement should exist at least for UFile")).getUastContext()
|
||||
}
|
||||
|
||||
@Deprecated("could unexpectedly throw exception", ReplaceWith("UastFacade.findPlugin"))
|
||||
@ApiStatus.ScheduledForRemoval
|
||||
tailrec fun UElement.getLanguagePlugin(): UastLanguagePlugin {
|
||||
val psi = this.sourcePsi
|
||||
if (psi != null) {
|
||||
return UastFacade.findPlugin(psi) ?: error("Language plugin was not found for $this (${this.javaClass.name})")
|
||||
}
|
||||
|
||||
return (uastParent ?: error("PsiElement should exist at least for UFile")).getLanguagePlugin()
|
||||
}
|
||||
|
||||
fun Collection<UElement?>.toPsiElements(): List<PsiElement> = mapNotNull { it?.sourcePsi }
|
||||
|
||||
/**
|
||||
* A helper function for getting parents for given [PsiElement] that could be considered as identifier.
|
||||
* Useful for working with gutter according to recommendations in [com.intellij.codeInsight.daemon.LineMarkerProvider].
|
||||
* Useful for working with gutter according to recommendations in `LineMarkerProvider`.
|
||||
*
|
||||
* @see [getUParentForAnnotationIdentifier] for working with annotations
|
||||
*/
|
||||
@@ -307,4 +291,4 @@ fun nonStructuralChildren(expression: UExpression): Stream<UExpression> {
|
||||
}.remove { e ->
|
||||
e is UBlockExpression || e is UIfExpression || e is UParenthesizedExpression || e is USwitchExpression
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user