diff --git a/RegExpSupport/resources/META-INF/RegExpPlugin.xml b/RegExpSupport/resources/META-INF/RegExpPlugin.xml index e783ebf4379f..d83b31589c81 100644 --- a/RegExpSupport/resources/META-INF/RegExpPlugin.xml +++ b/RegExpSupport/resources/META-INF/RegExpPlugin.xml @@ -36,6 +36,8 @@ inspection.group.name.regexp + + diff --git a/java/java-analysis-api/src/com/intellij/uast/UastHintedVisitorAdapter.kt b/java/java-analysis-api/src/com/intellij/uast/UastHintedVisitorAdapter.kt index 622654c2336e..992c877e5be7 100644 --- a/java/java-analysis-api/src/com/intellij/uast/UastHintedVisitorAdapter.kt +++ b/java/java-analysis-api/src/com/intellij/uast/UastHintedVisitorAdapter.kt @@ -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> -) : PsiElementVisitor() { + private val visitor: AbstractUastNonRecursiveVisitor, + private val directOnly: Boolean, + private val uElementTypesHint: Array> +) : PsiElementVisitor(), HintedPsiElementVisitor { + + override fun getHintPsiElements(): List> { + 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, + 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> { + return plugin.getPossiblePsiSourceTypes(uElementTypesHint).toList() + } } \ No newline at end of file diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplicitSubclassInspection.kt b/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplicitSubclassInspection.kt index 13754c8e016e..77b91357eb69 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplicitSubclassInspection.kt +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplicitSubclassInspection.kt @@ -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() ?: 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 diff --git a/java/java-impl-inspections/src/com/intellij/codeInspection/JoinDeclarationAndAssignmentJavaInspection.java b/java/java-impl-inspections/src/com/intellij/codeInspection/JoinDeclarationAndAssignmentJavaInspection.java index 104326bc442b..d06490ecb609 100644 --- a/java/java-impl-inspections/src/com/intellij/codeInspection/JoinDeclarationAndAssignmentJavaInspection.java +++ b/java/java-impl-inspections/src/com/intellij/codeInspection/JoinDeclarationAndAssignmentJavaInspection.java @@ -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; diff --git a/java/java-impl/src/META-INF/InspectionGadgets.xml b/java/java-impl/src/META-INF/InspectionGadgets.xml index df08176fd639..5df611e8cd13 100644 --- a/java/java-impl/src/META-INF/InspectionGadgets.xml +++ b/java/java-impl/src/META-INF/InspectionGadgets.xml @@ -7,6 +7,7 @@ + diff --git a/java/java-impl/src/META-INF/JavaPlugin.xml b/java/java-impl/src/META-INF/JavaPlugin.xml index cbc7ca381a6f..53a7de7472cc 100644 --- a/java/java-impl/src/META-INF/JavaPlugin.xml +++ b/java/java-impl/src/META-INF/JavaPlugin.xml @@ -1401,6 +1401,8 @@ + + + + [] 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 myBlockingMethodCheckers; private final List 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 checkers, BlockingCallInspectionSettings settings) { diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index 0a738f983ce1..3506cf7d8b44 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -379,6 +379,8 @@ + + > 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); + } } } diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 3a2e8fde0e75..17eaf3edf579 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -511,6 +511,7 @@ + diff --git a/plugins/kotlin/plugin/common/resources/META-INF/language.xml b/plugins/kotlin/plugin/common/resources/META-INF/language.xml index 36e082fbe775..7bb384e04e2e 100644 --- a/plugins/kotlin/plugin/common/resources/META-INF/language.xml +++ b/plugins/kotlin/plugin/common/resources/META-INF/language.xml @@ -6,6 +6,9 @@ + + + diff --git a/plugins/yaml/resources/META-INF/plugin.xml b/plugins/yaml/resources/META-INF/plugin.xml index 0661a69e12f4..6869bf9a79d8 100644 --- a/plugins/yaml/resources/META-INF/plugin.xml +++ b/plugins/yaml/resources/META-INF/plugin.xml @@ -73,6 +73,8 @@ bundle="messages.YAMLBundle" key="yaml.smartkeys.option.title"/> + +