[inspections] IDEA-321711 Use optimized PsiElementVisitor implementations

GitOrigin-RevId: 18ebc32aec877f71cd185ee7072dd139c076e9a3
This commit is contained in:
Yuriy Artamonov
2023-08-20 15:50:01 +02:00
committed by intellij-monorepo-bot
parent f8f9f82c96
commit c53774e2fc
15 changed files with 146 additions and 86 deletions

View File

@@ -36,6 +36,8 @@
<categoryKey>inspection.group.name.regexp</categoryKey> <categoryKey>inspection.group.name.regexp</categoryKey>
</intentionAction> </intentionAction>
<inspection.basicVisitor class="org.intellij.lang.regexp.psi.RegExpElementVisitor"/>
<localInspection shortName="CustomRegExpInspection" enabledByDefault="true" level="NON_SWITCHABLE_WARNING" dynamicGroup="true" <localInspection shortName="CustomRegExpInspection" enabledByDefault="true" level="NON_SWITCHABLE_WARNING" dynamicGroup="true"
bundle="messages.RegExpBundle" groupKey="inspection.group.name.regexp" key="inspection.name.custom.regexp" bundle="messages.RegExpBundle" groupKey="inspection.group.name.regexp" key="inspection.name.custom.regexp"
implementationClass="org.intellij.lang.regexp.inspection.custom.CustomRegExpInspection" language=""/> implementationClass="org.intellij.lang.regexp.inspection.custom.CustomRegExpInspection" language=""/>

View File

@@ -2,6 +2,7 @@
package com.intellij.uast package com.intellij.uast
import com.intellij.lang.Language import com.intellij.lang.Language
import com.intellij.psi.HintedPsiElementVisitor
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor import com.intellij.psi.PsiElementVisitor
import org.jetbrains.uast.UElement import org.jetbrains.uast.UElement
@@ -12,7 +13,13 @@ class UastHintedVisitorAdapter(private val plugin: UastLanguagePlugin,
private val visitor: AbstractUastNonRecursiveVisitor, private val visitor: AbstractUastNonRecursiveVisitor,
private val directOnly: Boolean, private val directOnly: Boolean,
private val uElementTypesHint: Array<Class<out UElement>> private val uElementTypesHint: Array<Class<out UElement>>
) : PsiElementVisitor() { ) : PsiElementVisitor(), HintedPsiElementVisitor {
override fun getHintPsiElements(): List<Class<*>> {
if (uElementTypesHint.isEmpty()) return emptyList()
return plugin.getPossiblePsiSourceTypes(*uElementTypesHint).toList()
}
override fun visitElement(element: PsiElement) { override fun visitElement(element: PsiElement) {
super.visitElement(element) super.visitElement(element)
@@ -30,16 +37,28 @@ class UastHintedVisitorAdapter(private val plugin: UastLanguagePlugin,
directOnly: Boolean = true): PsiElementVisitor { directOnly: Boolean = true): PsiElementVisitor {
val plugin = UastLanguagePlugin.byLanguage(language) ?: return EMPTY_VISITOR val plugin = UastLanguagePlugin.byLanguage(language) ?: return EMPTY_VISITOR
if (uElementTypesHint.size == 1) { if (uElementTypesHint.size == 1) {
return object: PsiElementVisitor() { return SimpleUastHintedVisitorAdapter(plugin, visitor, uElementTypesHint[0], directOnly)
override fun visitElement(element: PsiElement) {
val uElement = plugin.convertElementWithParent(element, uElementTypesHint[0]) ?: return
if (!directOnly || uElement.sourcePsi === element) {
uElement.accept(visitor)
}
}
}
} }
return UastHintedVisitorAdapter(plugin, visitor, directOnly, uElementTypesHint) return UastHintedVisitorAdapter(plugin, visitor, directOnly, uElementTypesHint)
} }
} }
} }
private class SimpleUastHintedVisitorAdapter(val plugin: UastLanguagePlugin,
val visitor: AbstractUastNonRecursiveVisitor,
val uElementTypesHint: Class<out UElement>,
val directOnly: Boolean
) : PsiElementVisitor(), HintedPsiElementVisitor {
override fun visitElement(element: PsiElement) {
val uElement = plugin.convertElementWithParent(element, uElementTypesHint) ?: return
if (!directOnly || uElement.sourcePsi === element) {
uElement.accept(visitor)
}
}
override fun getHintPsiElements(): List<Class<*>> {
return plugin.getPossiblePsiSourceTypes(uElementTypesHint).toList()
}
}

View File

@@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages import com.intellij.openapi.ui.Messages
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.PsiJvmConversionHelper.MODIFIERS import com.intellij.psi.PsiJvmConversionHelper.MODIFIERS
import com.intellij.uast.UastHintedVisitorAdapter
import com.intellij.uast.UastSmartPointer import com.intellij.uast.UastSmartPointer
import com.intellij.uast.createUastSmartPointer import com.intellij.uast.createUastSmartPointer
import com.intellij.util.IncorrectOperationException import com.intellij.util.IncorrectOperationException
@@ -27,7 +28,7 @@ import com.intellij.util.SmartList
import org.jetbrains.annotations.Nls import org.jetbrains.annotations.Nls
import org.jetbrains.uast.UClass import org.jetbrains.uast.UClass
import org.jetbrains.uast.UDeclaration import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.toUElementOfType import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor
class ImplicitSubclassInspection : LocalInspectionTool() { class ImplicitSubclassInspection : LocalInspectionTool() {
private val allModifiers = listOf(PsiModifier.PRIVATE, PsiModifier.PROTECTED, PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC) private val allModifiers = listOf(PsiModifier.PRIVATE, PsiModifier.PROTECTED, PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC)
@@ -230,15 +231,15 @@ class ImplicitSubclassInspection : LocalInspectionTool() {
} }
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor = object : PsiElementVisitor() { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
override fun visitElement(element: PsiElement) { return UastHintedVisitorAdapter.create(holder.file.language, object : AbstractUastNonRecursiveVisitor() {
super.visitElement(element) override fun visitClass(node: UClass): Boolean {
val uClass = element.toUElementOfType<UClass>() ?: return val problems = checkClass(node, holder.manager, isOnTheFly)
val problems = checkClass(uClass, holder.manager, isOnTheFly)
for (problem in problems) { for (problem in problems) {
holder.registerProblem(problem) holder.registerProblem(problem)
} }
return true
}
}, arrayOf(UClass::class.java))
} }
} }
}

View File

@@ -54,7 +54,7 @@ public class JoinDeclarationAndAssignmentJavaInspection extends AbstractBaseJava
} }
} }
public void visitLocation(@Nullable PsiElement location) { private void visitLocation(@Nullable PsiElement location) {
Context context = getContext(location); Context context = getContext(location);
if (context != null) { if (context != null) {
PsiLocalVariable variable = context.myVariable; PsiLocalVariable variable = context.myVariable;

View File

@@ -7,6 +7,7 @@
<extensionPoint qualifiedName="com.intellij.implicit.resource.closer" interface="com.intellij.codeInspection.resources.ImplicitResourceCloser" dynamic="true"/> <extensionPoint qualifiedName="com.intellij.implicit.resource.closer" interface="com.intellij.codeInspection.resources.ImplicitResourceCloser" dynamic="true"/>
</extensionPoints> </extensionPoints>
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<inspection.basicVisitor class="com.siyeh.ig.BaseInspectionVisitor"/>
<inspectionElementsMerger implementation="com.siyeh.ig.visibility.MethodOverridesInaccessibleMethodMerger"/> <inspectionElementsMerger implementation="com.siyeh.ig.visibility.MethodOverridesInaccessibleMethodMerger"/>
<inspectionElementsMerger implementation="com.siyeh.ig.redundancy.RedundantStringOperationMerger"/> <inspectionElementsMerger implementation="com.siyeh.ig.redundancy.RedundantStringOperationMerger"/>

View File

@@ -1401,6 +1401,8 @@
<java.error.fix errorCode="guarded.pattern.variable.must.be.final" implementationClass="com.intellij.codeInsight.daemon.impl.quickfix.VariableAccessFromInnerClassJava10Fix"/> <java.error.fix errorCode="guarded.pattern.variable.must.be.final" implementationClass="com.intellij.codeInsight.daemon.impl.quickfix.VariableAccessFromInnerClassJava10Fix"/>
<stripTrailingSpacesFilterFactory implementation="com.intellij.codeEditor.JavaStripTrailingSpacesFilterFactory"/> <stripTrailingSpacesFilterFactory implementation="com.intellij.codeEditor.JavaStripTrailingSpacesFilterFactory"/>
<inspection.basicVisitor class="com.intellij.psi.JavaElementVisitor"/>
<localInspection language="JAVA" shortName="MoveFieldAssignmentToInitializer" enabledByDefault="true" level="INFORMATION" <localInspection language="JAVA" shortName="MoveFieldAssignmentToInitializer" enabledByDefault="true" level="INFORMATION"
groupPath="Java" groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues" groupPath="Java" groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues"
implementationClass="com.intellij.codeInspection.MoveFieldAssignmentToInitializerInspection" implementationClass="com.intellij.codeInspection.MoveFieldAssignmentToInitializerInspection"

View File

@@ -7,7 +7,7 @@ import com.intellij.codeInspection.ProblemsHolder
import com.intellij.java.JavaBundle import com.intellij.java.JavaBundle
import com.intellij.modcommand.ModPsiUpdater import com.intellij.modcommand.ModPsiUpdater
import com.intellij.modcommand.PsiUpdateModCommandQuickFix import com.intellij.modcommand.PsiUpdateModCommandQuickFix
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.* import com.intellij.psi.*
@@ -18,19 +18,14 @@ import org.jetbrains.annotations.Contract
import java.util.* import java.util.*
import java.util.function.Predicate import java.util.function.Predicate
import java.util.stream.Collectors import java.util.stream.Collectors
import java.util.stream.Stream
class ReplaceWithJavadocInspection : LocalInspectionTool() { class ReplaceWithJavadocInspection : LocalInspectionTool() {
companion object {
private val LOGGER = Logger.getInstance(
ReplaceWithJavadocInspection::class.java.name)
}
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() { return object : JavaElementVisitor() {
override fun visitElement(element: PsiElement) { override fun visitComment(element: PsiComment) {
if (element !is PsiComment) return super.visitComment(element)
if (element is PsiDocComment) return if (element is PsiDocComment) return
val parent: PsiElement = element.getParent() val parent: PsiElement = element.getParent()
@@ -66,7 +61,7 @@ class ReplaceWithJavadocInspection : LocalInspectionTool() {
val javadoc = factory.createDocCommentFromText(javadocText) val javadoc = factory.createDocCommentFromText(javadocText)
if (commentNodes.isEmpty()) { if (commentNodes.isEmpty()) {
LOGGER.error("The set of visited node comments is empty") thisLogger().error("The set of visited node comments is empty")
return return
} }

View File

@@ -4,7 +4,6 @@ package com.intellij.json.psi;
import org.jetbrains.annotations.*; import org.jetbrains.annotations.*;
import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
public class JsonElementVisitor extends PsiElementVisitor { public class JsonElementVisitor extends PsiElementVisitor {

View File

@@ -81,6 +81,8 @@
<annotator language="JSON" implementationClass="com.intellij.json.codeinsight.JsonLiteralAnnotator"/> <annotator language="JSON" implementationClass="com.intellij.json.codeinsight.JsonLiteralAnnotator"/>
<!-- Inspections --> <!-- Inspections -->
<inspection.basicVisitor class="com.intellij.json.psi.JsonElementVisitor"/>
<localInspection language="JSON" shortName="JsonStandardCompliance" <localInspection language="JSON" shortName="JsonStandardCompliance"
bundle="messages.JsonBundle" key="inspection.compliance.name" groupKey="json.inspection.group" bundle="messages.JsonBundle" key="inspection.compliance.name" groupKey="json.inspection.group"
enabledByDefault="true" level="ERROR" enabledByDefault="true" level="ERROR"

View File

@@ -13,11 +13,13 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*; import com.intellij.psi.*;
import com.intellij.uast.UastHintedVisitorAdapter;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
import one.util.streamex.StreamEx; import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.uast.*; import org.jetbrains.uast.*;
import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor;
import java.util.*; import java.util.*;
@@ -52,6 +54,9 @@ public final class BlockingMethodInNonBlockingContextInspection extends Abstract
public boolean myConsiderUnknownContextBlocking; public boolean myConsiderUnknownContextBlocking;
public boolean myConsiderSuspendContextNonBlocking; public boolean myConsiderSuspendContextNonBlocking;
@SuppressWarnings("unchecked")
private final Class<? extends UElement>[] hints = new Class[]{UMethod.class, UCallExpression.class};
@Override @Override
public @NotNull OptPane getOptionsPane() { public @NotNull OptPane getOptionsPane() {
return pane( return pane(
@@ -84,7 +89,21 @@ public final class BlockingMethodInNonBlockingContextInspection extends Abstract
getBlockingMethodCheckers(holder.getFile(), blockingAnnotations, nonBlockingAnnotations); getBlockingMethodCheckers(holder.getFile(), blockingAnnotations, nonBlockingAnnotations);
if (blockingMethodCheckers.isEmpty()) return PsiElementVisitor.EMPTY_VISITOR; if (blockingMethodCheckers.isEmpty()) return PsiElementVisitor.EMPTY_VISITOR;
return new BlockingMethodInNonBlockingContextVisitor(holder, blockingMethodCheckers, nonBlockingContextCheckers, getSettings()); var visitor = new BlockingMethodInNonBlockingContextVisitor(holder, blockingMethodCheckers, nonBlockingContextCheckers, getSettings());
return UastHintedVisitorAdapter.create(holder.getFile().getLanguage(), new AbstractUastNonRecursiveVisitor() {
@Override
public boolean visitMethod(@NotNull UMethod node) {
visitor.visitMethod(node);
return super.visitMethod(node);
}
@Override
public boolean visitCallExpression(@NotNull UCallExpression node) {
visitor.visitCall(node);
return super.visitCallExpression(node);
}
}, hints);
} }
public BlockingCallInspectionSettings getSettings() { public BlockingCallInspectionSettings getSettings() {
@@ -115,7 +134,7 @@ public final class BlockingMethodInNonBlockingContextInspection extends Abstract
return result; return result;
} }
private class BlockingMethodInNonBlockingContextVisitor extends PsiElementVisitor { private class BlockingMethodInNonBlockingContextVisitor {
private final ProblemsHolder myHolder; private final ProblemsHolder myHolder;
private final List<BlockingMethodChecker> myBlockingMethodCheckers; private final List<BlockingMethodChecker> myBlockingMethodCheckers;
private final List<NonBlockingContextChecker> myNonBlockingContextCheckers; private final List<NonBlockingContextChecker> myNonBlockingContextCheckers;
@@ -131,13 +150,12 @@ public final class BlockingMethodInNonBlockingContextInspection extends Abstract
mySettings = settings; mySettings = settings;
} }
@Override public void visitCall(UCallExpression callExpression) {
public void visitElement(@NotNull PsiElement element) {
super.visitElement(element);
if (visitConstructor(element)) return;
UCallExpression callExpression = AnalysisUastUtil.getUCallExpression(element);
if (callExpression == null) return; if (callExpression == null) return;
var element = callExpression.getSourcePsi();
if (element == null) return;
PsiElement elementToHighLight = AnalysisUastUtil.getMethodIdentifierSourcePsi(callExpression); PsiElement elementToHighLight = AnalysisUastUtil.getMethodIdentifierSourcePsi(callExpression);
if (elementToHighLight == null) return; if (elementToHighLight == null) return;
@@ -188,44 +206,45 @@ public final class BlockingMethodInNonBlockingContextInspection extends Abstract
myHolder.registerProblem(elementToHighLight, message, fixesStream.toArray(LocalQuickFix.EMPTY_ARRAY)); myHolder.registerProblem(elementToHighLight, message, fixesStream.toArray(LocalQuickFix.EMPTY_ARRAY));
} }
private boolean visitConstructor(@NotNull PsiElement element) { public void visitMethod(UMethod method) {
var method = UastContextKt.toUElement(element, UMethod.class); if (method == null || !method.isConstructor()) return;
if (method == null || !method.isConstructor()) return false;
var element = method.getSourcePsi();
if (element == null) return;
var anchor = method.getUastAnchor(); var anchor = method.getUastAnchor();
if (anchor == null) return false; if (anchor == null) return;
var elementToHighlight = anchor.getSourcePsi(); var elementToHighlight = anchor.getSourcePsi();
if (elementToHighlight == null) return false; if (elementToHighlight == null) return;
if (!(method.getUastParent() instanceof UClass containingClass)) return false; if (!(method.getUastParent() instanceof UClass containingClass)) return;
if (containingClass.getJavaPsi().getSuperClass() == null) return false; if (containingClass.getJavaPsi().getSuperClass() == null) return;
if (!(method.getUastBody() instanceof UBlockExpression body)) return false; if (!(method.getUastBody() instanceof UBlockExpression body)) return;
var firstExpression = ContainerUtil.getFirstItem(body.getExpressions()); var firstExpression = ContainerUtil.getFirstItem(body.getExpressions());
if (firstExpression != null && isExplicitSuperCall(firstExpression)) return false; if (firstExpression != null && isExplicitSuperCall(firstExpression)) return;
ContextType contextType = isContextNonBlockingFor(element, myNonBlockingContextCheckers, mySettings); ContextType contextType = isContextNonBlockingFor(element, myNonBlockingContextCheckers, mySettings);
if (contextType instanceof ContextType.Blocking) { if (contextType instanceof ContextType.Blocking) {
return true; return;
} }
if (!(contextType instanceof ContextType.NonBlocking nonBlockingContext)) return true; if (!(contextType instanceof ContextType.NonBlocking nonBlockingContext)) return;
var implicitlyCalledCtr = findFirstExplicitNoArgConstructor(containingClass.getJavaPsi().getSuperClass()); var implicitlyCalledCtr = findFirstExplicitNoArgConstructor(containingClass.getJavaPsi().getSuperClass());
if (implicitlyCalledCtr == null) return true; if (implicitlyCalledCtr == null) return;
if (!isMethodBlocking(implicitlyCalledCtr, myBlockingMethodCheckers, mySettings)) return true; if (!isMethodBlocking(implicitlyCalledCtr, myBlockingMethodCheckers, mySettings)) return;
String message; String message;
if (StringUtil.isNotEmpty(nonBlockingContext.getDescription())) { if (StringUtil.isNotEmpty(nonBlockingContext.getDescription())) {
String contextDescription = nonBlockingContext.getDescription(); String contextDescription = nonBlockingContext.getDescription();
message = JvmAnalysisBundle.message("jvm.inspections.blocking.method.in.implicit.ctr.problem.wildcard.descriptor", contextDescription); message =
JvmAnalysisBundle.message("jvm.inspections.blocking.method.in.implicit.ctr.problem.wildcard.descriptor", contextDescription);
} }
else { else {
message = JvmAnalysisBundle.message("jvm.inspections.blocking.method.in.implicit.ctr.problem.descriptor"); message = JvmAnalysisBundle.message("jvm.inspections.blocking.method.in.implicit.ctr.problem.descriptor");
} }
myHolder.registerProblem(elementToHighlight, message); myHolder.registerProblem(elementToHighlight, message);
return true;
} }
private static @Nullable PsiMethod findFirstExplicitNoArgConstructor(@NotNull PsiClass currentClass) { private static @Nullable PsiMethod findFirstExplicitNoArgConstructor(@NotNull PsiClass currentClass) {
@@ -242,14 +261,15 @@ public final class BlockingMethodInNonBlockingContextInspection extends Abstract
private static boolean isExplicitSuperCall(@NotNull UExpression expression) { private static boolean isExplicitSuperCall(@NotNull UExpression expression) {
if (!(expression instanceof USuperExpression) && if (!(expression instanceof USuperExpression) &&
!(expression instanceof UCallExpression call && call.getKind() == UastCallKind.CONSTRUCTOR_CALL)) return true; !(expression instanceof UCallExpression call && call.getKind() == UastCallKind.CONSTRUCTOR_CALL)) {
return true;
}
var sourcePsi = expression.getSourcePsi(); var sourcePsi = expression.getSourcePsi();
if (sourcePsi == null) return false; if (sourcePsi == null) return false;
return !sourcePsi.getTextRange().isEmpty(); return !sourcePsi.getTextRange().isEmpty();
} }
} }
private static boolean isMethodOrSupersBlocking(PsiMethod referencedMethod, private static boolean isMethodOrSupersBlocking(PsiMethod referencedMethod,
List<BlockingMethodChecker> checkers, List<BlockingMethodChecker> checkers,
BlockingCallInspectionSettings settings) { BlockingCallInspectionSettings settings) {

View File

@@ -379,6 +379,8 @@
<iconProvider implementation="com.intellij.xml.util.XmlIconProvider"/> <iconProvider implementation="com.intellij.xml.util.XmlIconProvider"/>
<inspection.basicVisitor class="com.intellij.psi.XmlElementVisitor"/>
<localInspection language="XML" shortName="CheckTagEmptyBody" enabledByDefault="true" level="WARNING" <localInspection language="XML" shortName="CheckTagEmptyBody" enabledByDefault="true" level="WARNING"
bundle="messages.XmlBundle" key="xml.inspections.check.tag.empty.body" bundle="messages.XmlBundle" key="xml.inspections.check.tag.empty.body"
groupBundle="messages.XmlBundle" groupKey="xml.inspections.group.name" groupBundle="messages.XmlBundle" groupKey="xml.inspections.group.name"

View File

@@ -19,23 +19,35 @@ import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder; import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement; import com.intellij.psi.*;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiReference;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.List;
/** /**
* @author Dmitry Avdeev * @author Dmitry Avdeev
*/ */
public class InjectedReferencesInspection extends LocalInspectionTool { public class InjectedReferencesInspection extends LocalInspectionTool {
@NotNull @NotNull
@Override @Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new PsiElementVisitor() { return new InjectedReferencesVisitor(holder);
}
private static class InjectedReferencesVisitor extends PsiElementVisitor implements HintedPsiElementVisitor {
private final ProblemsHolder myHolder;
private InjectedReferencesVisitor(ProblemsHolder holder) {
myHolder = holder;
}
@Override
public List<Class<?>> getHintPsiElements() {
return List.of(PsiLanguageInjectionHost.class, ContributedReferenceHost.class);
}
@Override @Override
public void visitElement(@NotNull PsiElement element) { public void visitElement(@NotNull PsiElement element) {
PsiReference[] injected = InjectedReferencesContributor.getInjectedReferences(element); PsiReference[] injected = InjectedReferencesContributor.getInjectedReferences(element);
if (injected != null) { if (injected != null) {
for (PsiReference reference : injected) { for (PsiReference reference : injected) {
@@ -43,10 +55,10 @@ public class InjectedReferencesInspection extends LocalInspectionTool {
TextRange range = reference.getRangeInElement(); TextRange range = reference.getRangeInElement();
if (range.isEmpty() && range.getStartOffset() == 1 && "\"\"".equals(element.getText())) { if (range.isEmpty() && range.getStartOffset() == 1 && "\"\"".equals(element.getText())) {
String message = ProblemsHolder.unresolvedReferenceMessage(reference); String message = ProblemsHolder.unresolvedReferenceMessage(reference);
holder.registerProblem(element, message, ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, TextRange.create(0, 2)); myHolder.registerProblem(element, message, ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, TextRange.create(0, 2));
} }
else { else {
holder.registerProblem(reference); myHolder.registerProblem(reference);
} }
} }
} }
@@ -54,6 +66,5 @@ public class InjectedReferencesInspection extends LocalInspectionTool {
super.visitElement(element); super.visitElement(element);
} }
};
} }
} }

View File

@@ -511,6 +511,7 @@
<lang.formatter language="Groovy" implementationClass="org.jetbrains.plugins.groovy.formatter.GroovyFormattingModelBuilder"/> <lang.formatter language="Groovy" implementationClass="org.jetbrains.plugins.groovy.formatter.GroovyFormattingModelBuilder"/>
<lang.whiteSpaceFormattingStrategy language="Groovy" <lang.whiteSpaceFormattingStrategy language="Groovy"
implementationClass="org.jetbrains.plugins.groovy.formatter.GroovyWhiteSpaceFormattingStrategy"/> implementationClass="org.jetbrains.plugins.groovy.formatter.GroovyWhiteSpaceFormattingStrategy"/>
<inspection.basicVisitor class="org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor"/>
<focusModeProvider language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.GrFocusModeProvider" /> <focusModeProvider language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.GrFocusModeProvider" />
<postFormatProcessor implementation="org.jetbrains.plugins.groovy.formatter.GroovyBracePostFormatProcessor"/> <postFormatProcessor implementation="org.jetbrains.plugins.groovy.formatter.GroovyBracePostFormatProcessor"/>

View File

@@ -6,6 +6,9 @@
<lang.commenter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinCommenter"/> <lang.commenter language="kotlin" implementationClass="org.jetbrains.kotlin.idea.KotlinCommenter"/>
<inspection.basicVisitor class="org.jetbrains.kotlin.psi.KtVisitorVoid"/>
<inspection.basicVisitor class="org.jetbrains.kotlin.psi.KtVisitor"/>
<itemPresentationProvider <itemPresentationProvider
implementationClass="org.jetbrains.kotlin.idea.presentation.KtFunctionPresenter" implementationClass="org.jetbrains.kotlin.idea.presentation.KtFunctionPresenter"
forClass="org.jetbrains.kotlin.psi.KtFunction"/> forClass="org.jetbrains.kotlin.psi.KtFunction"/>

View File

@@ -73,6 +73,8 @@
bundle="messages.YAMLBundle" bundle="messages.YAMLBundle"
key="yaml.smartkeys.option.title"/> key="yaml.smartkeys.option.title"/>
<inspection.basicVisitor class="org.jetbrains.yaml.psi.YamlPsiElementVisitor"/>
<localInspection language="yaml" bundle="messages.YAMLBundle" <localInspection language="yaml" bundle="messages.YAMLBundle"
shortName="YAMLUnresolvedAlias" shortName="YAMLUnresolvedAlias"
key="inspections.unresolved.alias.name" level="ERROR" key="inspections.unresolved.alias.name" level="ERROR"