Commit c53774e2 authored by Yuriy Artamonov's avatar Yuriy Artamonov Committed by intellij-monorepo-bot
Browse files

[inspections] IDEA-321711 Use optimized PsiElementVisitor implementations

GitOrigin-RevId: 18ebc32aec877f71cd185ee7072dd139c076e9a3
parent f8f9f82c
Showing with 147 additions and 87 deletions
+147 -87
......@@ -36,6 +36,8 @@
<categoryKey>inspection.group.name.regexp</categoryKey>
</intentionAction>
<inspection.basicVisitor class="org.intellij.lang.regexp.psi.RegExpElementVisitor"/>
<localInspection shortName="CustomRegExpInspection" enabledByDefault="true" level="NON_SWITCHABLE_WARNING" dynamicGroup="true"
bundle="messages.RegExpBundle" groupKey="inspection.group.name.regexp" key="inspection.name.custom.regexp"
implementationClass="org.intellij.lang.regexp.inspection.custom.CustomRegExpInspection" language=""/>
......
......@@ -2,6 +2,7 @@
package com.intellij.uast
import com.intellij.lang.Language
import com.intellij.psi.HintedPsiElementVisitor
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import org.jetbrains.uast.UElement
......@@ -9,10 +10,16 @@ import org.jetbrains.uast.UastLanguagePlugin
import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor
class UastHintedVisitorAdapter(private val plugin: UastLanguagePlugin,
private val visitor: AbstractUastNonRecursiveVisitor,
private val directOnly: Boolean,
private val uElementTypesHint: Array<Class<out UElement>>
) : PsiElementVisitor() {
private val visitor: AbstractUastNonRecursiveVisitor,
private val directOnly: Boolean,
private val uElementTypesHint: Array<Class<out UElement>>
) : PsiElementVisitor(), HintedPsiElementVisitor {
override fun getHintPsiElements(): List<Class<*>> {
if (uElementTypesHint.isEmpty()) return emptyList()
return plugin.getPossiblePsiSourceTypes(*uElementTypesHint).toList()
}
override fun visitElement(element: PsiElement) {
super.visitElement(element)
......@@ -30,16 +37,28 @@ class UastHintedVisitorAdapter(private val plugin: UastLanguagePlugin,
directOnly: Boolean = true): PsiElementVisitor {
val plugin = UastLanguagePlugin.byLanguage(language) ?: return EMPTY_VISITOR
if (uElementTypesHint.size == 1) {
return object: PsiElementVisitor() {
override fun visitElement(element: PsiElement) {
val uElement = plugin.convertElementWithParent(element, uElementTypesHint[0]) ?: return
if (!directOnly || uElement.sourcePsi === element) {
uElement.accept(visitor)
}
}
}
return SimpleUastHintedVisitorAdapter(plugin, visitor, uElementTypesHint[0], directOnly)
}
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()
}
}
\ No newline at end of file
......@@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages
import com.intellij.psi.*
import com.intellij.psi.PsiJvmConversionHelper.MODIFIERS
import com.intellij.uast.UastHintedVisitorAdapter
import com.intellij.uast.UastSmartPointer
import com.intellij.uast.createUastSmartPointer
import com.intellij.util.IncorrectOperationException
......@@ -27,7 +28,7 @@ import com.intellij.util.SmartList
import org.jetbrains.annotations.Nls
import org.jetbrains.uast.UClass
import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.toUElementOfType
import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor
class ImplicitSubclassInspection : LocalInspectionTool() {
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 visitElement(element: PsiElement) {
super.visitElement(element)
val uClass = element.toUElementOfType<UClass>() ?: return
val problems = checkClass(uClass, holder.manager, isOnTheFly)
for (problem in problems) {
holder.registerProblem(problem)
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return UastHintedVisitorAdapter.create(holder.file.language, object : AbstractUastNonRecursiveVisitor() {
override fun visitClass(node: UClass): Boolean {
val problems = checkClass(node, holder.manager, isOnTheFly)
for (problem in problems) {
holder.registerProblem(problem)
}
return true
}
}
}, arrayOf(UClass::class.java))
}
}
\ No newline at end of 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);
if (context != null) {
PsiLocalVariable variable = context.myVariable;
......
......@@ -7,6 +7,7 @@
<extensionPoint qualifiedName="com.intellij.implicit.resource.closer" interface="com.intellij.codeInspection.resources.ImplicitResourceCloser" dynamic="true"/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
<inspection.basicVisitor class="com.siyeh.ig.BaseInspectionVisitor"/>
<inspectionElementsMerger implementation="com.siyeh.ig.visibility.MethodOverridesInaccessibleMethodMerger"/>
<inspectionElementsMerger implementation="com.siyeh.ig.redundancy.RedundantStringOperationMerger"/>
......
......@@ -1401,6 +1401,8 @@
<java.error.fix errorCode="guarded.pattern.variable.must.be.final" implementationClass="com.intellij.codeInsight.daemon.impl.quickfix.VariableAccessFromInnerClassJava10Fix"/>
<stripTrailingSpacesFilterFactory implementation="com.intellij.codeEditor.JavaStripTrailingSpacesFilterFactory"/>
<inspection.basicVisitor class="com.intellij.psi.JavaElementVisitor"/>
<localInspection language="JAVA" shortName="MoveFieldAssignmentToInitializer" enabledByDefault="true" level="INFORMATION"
groupPath="Java" groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues"
implementationClass="com.intellij.codeInspection.MoveFieldAssignmentToInitializerInspection"
......
......@@ -7,7 +7,7 @@ import com.intellij.codeInspection.ProblemsHolder
import com.intellij.java.JavaBundle
import com.intellij.modcommand.ModPsiUpdater
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.util.text.StringUtil
import com.intellij.psi.*
......@@ -18,19 +18,14 @@ import org.jetbrains.annotations.Contract
import java.util.*
import java.util.function.Predicate
import java.util.stream.Collectors
import java.util.stream.Stream
class ReplaceWithJavadocInspection : LocalInspectionTool() {
companion object {
private val LOGGER = Logger.getInstance(
ReplaceWithJavadocInspection::class.java.name)
}
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitElement(element: PsiElement) {
if (element !is PsiComment) return
override fun visitComment(element: PsiComment) {
super.visitComment(element)
if (element is PsiDocComment) return
val parent: PsiElement = element.getParent()
......@@ -66,7 +61,7 @@ class ReplaceWithJavadocInspection : LocalInspectionTool() {
val javadoc = factory.createDocCommentFromText(javadocText)
if (commentNodes.isEmpty()) {
LOGGER.error("The set of visited node comments is empty")
thisLogger().error("The set of visited node comments is empty")
return
}
......
......@@ -4,7 +4,6 @@ package com.intellij.json.psi;
import org.jetbrains.annotations.*;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
public class JsonElementVisitor extends PsiElementVisitor {
......
......@@ -81,6 +81,8 @@
<annotator language="JSON" implementationClass="com.intellij.json.codeinsight.JsonLiteralAnnotator"/>
<!-- Inspections -->
<inspection.basicVisitor class="com.intellij.json.psi.JsonElementVisitor"/>
<localInspection language="JSON" shortName="JsonStandardCompliance"
bundle="messages.JsonBundle" key="inspection.compliance.name" groupKey="json.inspection.group"
enabledByDefault="true" level="ERROR"
......
......@@ -13,11 +13,13 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.uast.UastHintedVisitorAdapter;
import com.intellij.util.containers.ContainerUtil;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.uast.*;
import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor;
import java.util.*;
......@@ -52,6 +54,9 @@ public final class BlockingMethodInNonBlockingContextInspection extends Abstract
public boolean myConsiderUnknownContextBlocking;
public boolean myConsiderSuspendContextNonBlocking;
@SuppressWarnings("unchecked")
private final Class<? extends UElement>[] hints = new Class[]{UMethod.class, UCallExpression.class};
@Override
public @NotNull OptPane getOptionsPane() {
return pane(
......@@ -61,12 +66,12 @@ public final class BlockingMethodInNonBlockingContextInspection extends Abstract
JvmAnalysisBundle.message("jvm.inspections.blocking.method.consider.suspend.context.non.blocking")),
stringList("myBlockingAnnotations", JvmAnalysisBundle.message("jvm.inspections.blocking.method.annotation.blocking"),
new JavaClassValidator().withTitle(
JvmAnalysisBundle.message("jvm.inspections.blocking.method.annotation.configure.add.blocking.title"))
.annotationsOnly()),
JvmAnalysisBundle.message("jvm.inspections.blocking.method.annotation.configure.add.blocking.title"))
.annotationsOnly()),
stringList("myNonBlockingAnnotations", JvmAnalysisBundle.message("jvm.inspections.blocking.method.annotation.non-blocking"),
new JavaClassValidator().withTitle(
JvmAnalysisBundle.message("jvm.inspections.blocking.method.annotation.configure.add.non-blocking.title"))
.annotationsOnly())
JvmAnalysisBundle.message("jvm.inspections.blocking.method.annotation.configure.add.non-blocking.title"))
.annotationsOnly())
);
}
......@@ -84,7 +89,21 @@ public final class BlockingMethodInNonBlockingContextInspection extends Abstract
getBlockingMethodCheckers(holder.getFile(), blockingAnnotations, nonBlockingAnnotations);
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() {
......@@ -115,7 +134,7 @@ public final class BlockingMethodInNonBlockingContextInspection extends Abstract
return result;
}
private class BlockingMethodInNonBlockingContextVisitor extends PsiElementVisitor {
private class BlockingMethodInNonBlockingContextVisitor {
private final ProblemsHolder myHolder;
private final List<BlockingMethodChecker> myBlockingMethodCheckers;
private final List<NonBlockingContextChecker> myNonBlockingContextCheckers;
......@@ -131,13 +150,12 @@ public final class BlockingMethodInNonBlockingContextInspection extends Abstract
mySettings = settings;
}
@Override
public void visitElement(@NotNull PsiElement element) {
super.visitElement(element);
if (visitConstructor(element)) return;
UCallExpression callExpression = AnalysisUastUtil.getUCallExpression(element);
public void visitCall(UCallExpression callExpression) {
if (callExpression == null) return;
var element = callExpression.getSourcePsi();
if (element == null) return;
PsiElement elementToHighLight = AnalysisUastUtil.getMethodIdentifierSourcePsi(callExpression);
if (elementToHighLight == null) return;
......@@ -188,44 +206,45 @@ public final class BlockingMethodInNonBlockingContextInspection extends Abstract
myHolder.registerProblem(elementToHighLight, message, fixesStream.toArray(LocalQuickFix.EMPTY_ARRAY));
}
private boolean visitConstructor(@NotNull PsiElement element) {
var method = UastContextKt.toUElement(element, UMethod.class);
if (method == null || !method.isConstructor()) return false;
public void visitMethod(UMethod method) {
if (method == null || !method.isConstructor()) return;
var element = method.getSourcePsi();
if (element == null) return;
var anchor = method.getUastAnchor();
if (anchor == null) return false;
if (anchor == null) return;
var elementToHighlight = anchor.getSourcePsi();
if (elementToHighlight == null) return false;
if (elementToHighlight == null) return;
if (!(method.getUastParent() instanceof UClass containingClass)) return false;
if (containingClass.getJavaPsi().getSuperClass() == null) return false;
if (!(method.getUastBody() instanceof UBlockExpression body)) return false;
if (!(method.getUastParent() instanceof UClass containingClass)) return;
if (containingClass.getJavaPsi().getSuperClass() == null) return;
if (!(method.getUastBody() instanceof UBlockExpression body)) return;
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);
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());
if (implicitlyCalledCtr == null) return true;
if (!isMethodBlocking(implicitlyCalledCtr, myBlockingMethodCheckers, mySettings)) return true;
if (implicitlyCalledCtr == null) return;
if (!isMethodBlocking(implicitlyCalledCtr, myBlockingMethodCheckers, mySettings)) return;
String message;
if (StringUtil.isNotEmpty(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 {
message = JvmAnalysisBundle.message("jvm.inspections.blocking.method.in.implicit.ctr.problem.descriptor");
}
myHolder.registerProblem(elementToHighlight, message);
return true;
}
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) {
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();
if (sourcePsi == null) return false;
return !sourcePsi.getTextRange().isEmpty();
}
}
private static boolean isMethodOrSupersBlocking(PsiMethod referencedMethod,
List<BlockingMethodChecker> checkers,
BlockingCallInspectionSettings settings) {
......
......@@ -379,6 +379,8 @@
<iconProvider implementation="com.intellij.xml.util.XmlIconProvider"/>
<inspection.basicVisitor class="com.intellij.psi.XmlElementVisitor"/>
<localInspection language="XML" shortName="CheckTagEmptyBody" enabledByDefault="true" level="WARNING"
bundle="messages.XmlBundle" key="xml.inspections.check.tag.empty.body"
groupBundle="messages.XmlBundle" groupKey="xml.inspections.group.name"
......
......@@ -19,41 +19,52 @@ import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiReference;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author Dmitry Avdeev
*/
public class InjectedReferencesInspection extends LocalInspectionTool {
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new PsiElementVisitor() {
@Override
public void visitElement(@NotNull PsiElement element) {
PsiReference[] injected = InjectedReferencesContributor.getInjectedReferences(element);
if (injected != null) {
for (PsiReference reference : injected) {
if (reference.resolve() == null) {
TextRange range = reference.getRangeInElement();
if (range.isEmpty() && range.getStartOffset() == 1 && "\"\"".equals(element.getText())) {
String message = ProblemsHolder.unresolvedReferenceMessage(reference);
holder.registerProblem(element, message, ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, TextRange.create(0, 2));
}
else {
holder.registerProblem(reference);
}
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
public void visitElement(@NotNull PsiElement element) {
PsiReference[] injected = InjectedReferencesContributor.getInjectedReferences(element);
if (injected != null) {
for (PsiReference reference : injected) {
if (reference.resolve() == null) {
TextRange range = reference.getRangeInElement();
if (range.isEmpty() && range.getStartOffset() == 1 && "\"\"".equals(element.getText())) {
String message = ProblemsHolder.unresolvedReferenceMessage(reference);
myHolder.registerProblem(element, message, ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, TextRange.create(0, 2));
}
else {
myHolder.registerProblem(reference);
}
}
}
super.visitElement(element);
}
};
super.visitElement(element);
}
}
}
......@@ -511,6 +511,7 @@
<lang.formatter language="Groovy" implementationClass="org.jetbrains.plugins.groovy.formatter.GroovyFormattingModelBuilder"/>
<lang.whiteSpaceFormattingStrategy language="Groovy"
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" />
<postFormatProcessor implementation="org.jetbrains.plugins.groovy.formatter.GroovyBracePostFormatProcessor"/>
......
......@@ -6,6 +6,9 @@
<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
implementationClass="org.jetbrains.kotlin.idea.presentation.KtFunctionPresenter"
forClass="org.jetbrains.kotlin.psi.KtFunction"/>
......
......@@ -73,6 +73,8 @@
bundle="messages.YAMLBundle"
key="yaml.smartkeys.option.title"/>
<inspection.basicVisitor class="org.jetbrains.yaml.psi.YamlPsiElementVisitor"/>
<localInspection language="yaml" bundle="messages.YAMLBundle"
shortName="YAMLUnresolvedAlias"
key="inspections.unresolved.alias.name" level="ERROR"
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment