From bbedc3df3b37723b8e2f9fecee9238cee2596716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Tue, 23 Jun 2020 17:34:01 +0200 Subject: [PATCH] IDEA-244325 [devkit] Convert InspectionDescriptionNotFoundInspection to UAST GitOrigin-RevId: 9e8feeeb5cbd53c37bd43b29c5eaeb3de87329d7 --- .../deadCode/DummyEntryPointsTool.java | 2 +- .../devkit-core/resources/META-INF/plugin.xml | 2 +- .../DescriptionNotFoundInspectionBase.java | 104 ++++++++++-------- .../InspectionDescriptionInfo.java | 69 +++++++++--- ...spectionDescriptionNotFoundInspection.java | 87 +++++++-------- ...ntentionDescriptionNotFoundInspection.java | 3 +- ...TemplateDescriptionNotFoundInspection.java | 3 +- .../devkit/devkit-core/src/util/PsiUtil.java | 67 ----------- .../MyInspectionCustomShortName.java | 4 +- ...scriptionAndShortNameInBaseInspection.java | 2 +- .../inspectionDescription/MyInspection.kt | 3 + .../MyInspectionCustomShortName.kt | 5 + .../MyOverridePathMethodInspection.kt | 5 + ...ithDescriptionCustomShortNameInspection.kt | 5 + .../MyWithDescriptionInspection.kt | 1 + .../MyWithDescription.html | 1 + .../customShortName.html | 1 + ...ectionDescriptionNotFoundInspectionTest.kt | 57 ++++++++++ 18 files changed, 238 insertions(+), 183 deletions(-) create mode 100644 plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyInspection.kt create mode 100644 plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyInspectionCustomShortName.kt create mode 100644 plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyOverridePathMethodInspection.kt create mode 100644 plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyWithDescriptionCustomShortNameInspection.kt create mode 100644 plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyWithDescriptionInspection.kt create mode 100644 plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/inspectionDescriptions/MyWithDescription.html create mode 100644 plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/inspectionDescriptions/customShortName.html create mode 100644 plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/inspections/KtInspectionDescriptionNotFoundInspectionTest.kt diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java index 45d82e4c31cd..e5f1bf3369a0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java @@ -9,6 +9,7 @@ import com.intellij.codeInspection.ex.JobDescriptor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +@SuppressWarnings("InspectionDescriptionNotFoundInspection") public class DummyEntryPointsTool extends UnusedDeclarationInspectionBase { public DummyEntryPointsTool() { } @@ -34,7 +35,6 @@ public class DummyEntryPointsTool extends UnusedDeclarationInspectionBase { @Override @NotNull public String getShortName() { - //noinspection InspectionDescriptionNotFoundInspection return ""; } } diff --git a/plugins/devkit/devkit-core/resources/META-INF/plugin.xml b/plugins/devkit/devkit-core/resources/META-INF/plugin.xml index fd3468e009ba..e465f7e78a57 100644 --- a/plugins/devkit/devkit-core/resources/META-INF/plugin.xml +++ b/plugins/devkit/devkit-core/resources/META-INF/plugin.xml @@ -108,7 +108,7 @@ groupPath="Plugin DevKit" key="inspections.component.not.registered.name" groupKey="inspections.group.code" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.idea.devkit.inspections.ComponentNotRegisteredInspection"/> - diff --git a/plugins/devkit/devkit-core/src/inspections/DescriptionNotFoundInspectionBase.java b/plugins/devkit/devkit-core/src/inspections/DescriptionNotFoundInspectionBase.java index 07d1f6fc39ae..b4c97eddbd2a 100644 --- a/plugins/devkit/devkit-core/src/inspections/DescriptionNotFoundInspectionBase.java +++ b/plugins/devkit/devkit-core/src/inspections/DescriptionNotFoundInspectionBase.java @@ -2,9 +2,9 @@ package org.jetbrains.idea.devkit.inspections; import com.intellij.codeInspection.InspectionManager; -import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInspection.ProblemsHolder; import com.intellij.codeInspection.util.InspectionMessage; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; @@ -29,7 +29,7 @@ abstract class DescriptionNotFoundInspectionBase extends DevKitUastInspectionBas } @Override - public ProblemDescriptor @Nullable [] checkClass(@NotNull UClass uClass, @NotNull InspectionManager manager, boolean isOnTheFly) { + public final ProblemDescriptor @Nullable [] checkClass(@NotNull UClass uClass, @NotNull InspectionManager manager, boolean isOnTheFly) { if (uClass instanceof UAnonymousClass) return null; PsiClass psiClass = uClass.getJavaPsi(); @@ -37,58 +37,72 @@ abstract class DescriptionNotFoundInspectionBase extends DevKitUastInspectionBas final Module module = ModuleUtilCore.findModuleForPsiElement(psiClass); if (nameIdentifier == null || module == null || !PsiUtil.isInstantiable(psiClass)) return null; - final PsiClass base = JavaPsiFacade.getInstance(manager.getProject()).findClass(getClassName(), psiClass.getResolveScope()); + final PsiClass base = JavaPsiFacade.getInstance(manager.getProject()).findClass(myDescriptionType.getClassName(), + psiClass.getResolveScope()); if (base == null || !psiClass.isInheritor(base, true)) return null; - String descriptionDir = DescriptionCheckerUtil.getDescriptionDirName(psiClass); - if (StringUtil.isEmptyOrSpaces(descriptionDir)) { + if (skipIfNotRegistered(psiClass)) { return null; } + ProblemsHolder holder = new ProblemsHolder(manager, psiClass.getContainingFile(), isOnTheFly); + boolean registered; + if (myDescriptionType.isFixedDescriptionFilename()) { + registered = checkFixedDescription(holder, module, psiClass, uClass); + } + else { + registered = checkDynamicDescription(holder, module, psiClass); + } + + if (registered) return holder.getResultsArray(); + + + final PsiElement highlightElement = getInspectionHighlightElement(uClass); + if (highlightElement == null) return null; + + holder.registerProblem(highlightElement, getHasNotDescriptionError(module, psiClass), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + new CreateHtmlDescriptionFix(getDescriptionDir(module, psiClass), module, myDescriptionType)); + return holder.getResultsArray(); + } + + @Nullable + private static PsiElement getInspectionHighlightElement(UClass uClass) { + return UElementKt.getSourcePsiElement(uClass.getUastAnchor()); + } + + protected abstract boolean skipIfNotRegistered(PsiClass epClass); + + protected boolean checkDynamicDescription(ProblemsHolder holder, Module module, PsiClass psiClass) { + throw new IllegalStateException("must be implemented for " + getClass()); + } + + protected boolean checkFixedDescription(ProblemsHolder holder, + Module module, + PsiClass psiClass, + UClass uClass) { + String descriptionDir = getDescriptionDir(module, psiClass); + if (StringUtil.isEmptyOrSpaces(descriptionDir)) { + return false; + } + for (PsiDirectory description : getDescriptionsDirs(module)) { PsiDirectory dir = description.findSubdirectory(descriptionDir); if (dir == null) continue; final PsiFile descr = dir.findFile("description.html"); - if (descr != null) { - if (!skipIfNotRegistered(psiClass) && - !hasBeforeAndAfterTemplate(dir.getVirtualFile())) { - final PsiElement highlightElement = getInspectionHighlightElement(uClass); - if (highlightElement == null) return null; - ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(highlightElement, - getHasNotBeforeAfterError(), - isOnTheFly, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false); - return new ProblemDescriptor[]{problemDescriptor}; + if (descr == null) continue; + + if (!hasBeforeAndAfterTemplate(dir.getVirtualFile())) { + final PsiElement highlightElement = getInspectionHighlightElement(uClass); + if (highlightElement != null) { + holder.registerProblem(highlightElement, getHasNotBeforeAfterError(), ProblemHighlightType.GENERIC_ERROR_OR_WARNING); } - return null; } + return true; } - - if (skipIfNotRegistered(psiClass)) { - return null; - } - - final PsiElement highlightElement = getInspectionHighlightElement(uClass); - if (highlightElement == null) return null; - - final ProblemDescriptor problemDescriptor = manager - .createProblemDescriptor(highlightElement, - getHasNotDescriptionError(), isOnTheFly, new LocalQuickFix[]{getFix(module, descriptionDir)}, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - return new ProblemDescriptor[]{problemDescriptor}; + return false; } - @Nullable - private static PsiElement getInspectionHighlightElement(@NotNull UClass uClass) { - return UElementKt.getSourcePsiElement(uClass.getUastAnchor()); - } - - protected CreateHtmlDescriptionFix getFix(Module module, String descriptionDir) { - return new CreateHtmlDescriptionFix(descriptionDir, module, myDescriptionType); - } - - protected abstract boolean skipIfNotRegistered(PsiClass epClass); - private static boolean hasBeforeAndAfterTemplate(@NotNull VirtualFile dir) { boolean hasBefore = false; boolean hasAfter = false; @@ -108,18 +122,18 @@ abstract class DescriptionNotFoundInspectionBase extends DevKitUastInspectionBas return hasBefore && hasAfter; } - @NotNull - protected String getClassName() { - return myDescriptionType.getClassName(); + @Nullable + protected String getDescriptionDir(Module module, PsiClass psiClass) { + return DescriptionCheckerUtil.getDescriptionDirName(psiClass); } - protected PsiDirectory @NotNull [] getDescriptionsDirs(@NotNull Module module) { + protected PsiDirectory @NotNull [] getDescriptionsDirs(Module module) { return DescriptionCheckerUtil.getDescriptionsDirs(module, myDescriptionType); } @InspectionMessage @NotNull - protected abstract String getHasNotDescriptionError(); + protected abstract String getHasNotDescriptionError(Module module, PsiClass psiClass); @InspectionMessage @NotNull diff --git a/plugins/devkit/devkit-core/src/inspections/InspectionDescriptionInfo.java b/plugins/devkit/devkit-core/src/inspections/InspectionDescriptionInfo.java index cb562399fc17..d14ef92e1025 100644 --- a/plugins/devkit/devkit-core/src/inspections/InspectionDescriptionInfo.java +++ b/plugins/devkit/devkit-core/src/inspections/InspectionDescriptionInfo.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2019 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.idea.devkit.inspections; import com.intellij.codeInspection.InspectionEP; @@ -31,7 +17,9 @@ import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.util.ObjectUtils; import com.intellij.util.Query; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xml.DomElement; import com.intellij.util.xml.DomFileElement; import com.intellij.util.xml.DomService; @@ -42,6 +30,7 @@ import org.jetbrains.idea.devkit.dom.ExtensionPoint; import org.jetbrains.idea.devkit.dom.IdeaPlugin; import org.jetbrains.idea.devkit.inspections.quickfix.PluginDescriptorChooser; import org.jetbrains.idea.devkit.util.PsiUtil; +import org.jetbrains.uast.*; import java.util.HashSet; import java.util.List; @@ -85,7 +74,7 @@ public class InspectionDescriptionInfo { } else { shortNameInXml = false; - filename = PsiUtil.getReturnedLiteral(getShortNameMethod, psiClass); + filename = getReturnedLiteral(getShortNameMethod, psiClass); } if (filename == null) { @@ -183,4 +172,52 @@ public class InspectionDescriptionInfo { public boolean isShortNameInXml() { return myShortNameInXml; } + + @Nullable + private static String getReturnedLiteral(PsiMethod method, PsiClass cls) { + final UExpression expression = getReturnedExpression(method); + if (expression == null) return null; + + if (expression instanceof UReferenceExpression) { + final String methodName = ((UReferenceExpression)expression).getResolvedName(); + if ("getSimpleName".equals(methodName)) { + return cls.getName(); + } + } + + return UastUtils.evaluateString(expression); + } + + @Nullable + private static UExpression getReturnedExpression(PsiMethod method) { + UMethod uMethod = UastContextKt.toUElement(method, UMethod.class); + if (uMethod == null) return null; + + final UExpression uBody = uMethod.getUastBody(); + if (!(uBody instanceof UBlockExpression)) return null; + final List expressions = ((UBlockExpression)uBody).getExpressions(); + final UExpression singleExpression = ContainerUtil.getOnlyItem(expressions); + if (singleExpression == null) return null; + + if (!(singleExpression instanceof UReturnExpression)) return null; + UReturnExpression uReturnExpression = (UReturnExpression)singleExpression; + final UExpression returnValue = uReturnExpression.getReturnExpression(); + if (returnValue == null) return null; + + if (returnValue instanceof UReferenceExpression) { + UReferenceExpression referenceExpression = (UReferenceExpression)returnValue; + final UField uField = ObjectUtils.tryCast(UResolvableKt.resolveToUElement(referenceExpression), UField.class); + if (uField != null && uField.isFinal()) { + return uField.getUastInitializer(); + } + } + else if (returnValue instanceof UCallExpression) { + UCallExpression uCallExpression = (UCallExpression)returnValue; + final PsiMethod psiMethod = uCallExpression.resolve(); + if (psiMethod == null) return null; + return getReturnedExpression(psiMethod); + } + + return returnValue; + } } diff --git a/plugins/devkit/devkit-core/src/inspections/InspectionDescriptionNotFoundInspection.java b/plugins/devkit/devkit-core/src/inspections/InspectionDescriptionNotFoundInspection.java index f4b665615305..68433ba8b9fa 100644 --- a/plugins/devkit/devkit-core/src/inspections/InspectionDescriptionNotFoundInspection.java +++ b/plugins/devkit/devkit-core/src/inspections/InspectionDescriptionNotFoundInspection.java @@ -2,79 +2,70 @@ package org.jetbrains.idea.devkit.inspections; -import com.intellij.codeInspection.InspectionManager; -import com.intellij.codeInspection.LocalQuickFix; -import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.codeInspection.util.InspectionMessage; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtilCore; -import com.intellij.openapi.project.Project; -import com.intellij.psi.*; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.devkit.inspections.quickfix.CreateHtmlDescriptionFix; -import org.jetbrains.idea.devkit.util.PsiUtil; /** * @author Konstantin Bulenkov */ -public class InspectionDescriptionNotFoundInspection extends DevKitInspectionBase { +public class InspectionDescriptionNotFoundInspection extends DescriptionNotFoundInspectionBase { @NonNls private static final String INSPECTION_PROFILE_ENTRY = DescriptionType.INSPECTION.getClassName(); + public InspectionDescriptionNotFoundInspection() { + super(DescriptionType.INSPECTION); + } + @Override - public ProblemDescriptor[] checkClass(@NotNull PsiClass psiClass, @NotNull InspectionManager manager, boolean isOnTheFly) { - final Project project = psiClass.getProject(); - final PsiIdentifier nameIdentifier = psiClass.getNameIdentifier(); - final Module module = ModuleUtilCore.findModuleForPsiElement(psiClass); - - if (nameIdentifier == null || module == null || !PsiUtil.isInstantiable(psiClass)) return null; - - final PsiClass base = JavaPsiFacade.getInstance(project).findClass(INSPECTION_PROFILE_ENTRY, psiClass.getResolveScope()); - if (base == null || !psiClass.isInheritor(base, true) || isPathMethodsAreOverridden(psiClass)) return null; + protected boolean skipIfNotRegistered(PsiClass epClass) { + return isAnyPathMethodOverridden(epClass); + } + @Override + protected boolean checkDynamicDescription(ProblemsHolder holder, + Module module, + PsiClass psiClass) { final InspectionDescriptionInfo info = InspectionDescriptionInfo.create(module, psiClass); - if (!info.isValid() || info.hasDescriptionFile()) return null; - - final PsiElement problemElement = getProblemElement(psiClass, info.getShortNameMethod()); - final ProblemDescriptor problemDescriptor = manager - .createProblemDescriptor(problemElement == null ? nameIdentifier : problemElement, - "Inspection does not have a description", isOnTheFly, - new LocalQuickFix[]{new CreateHtmlDescriptionFix(info.getFilename(), module, DescriptionType.INSPECTION)}, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - return new ProblemDescriptor[]{problemDescriptor}; + return info.isValid() && info.hasDescriptionFile(); } - @Nullable - private static PsiElement getProblemElement(PsiClass psiClass, @Nullable PsiMethod method) { - if (method != null && method.getContainingClass() == psiClass) { - return PsiUtil.getReturnedExpression(method); - } - return psiClass.getNameIdentifier(); + @Override + protected @Nullable String getDescriptionDir(Module module, PsiClass psiClass) { + return InspectionDescriptionInfo.create(module, psiClass).getFilename(); } - private static boolean isPathMethodsAreOverridden(PsiClass psiClass) { - return !(isLastMethodDefinitionIn("getStaticDescription", INSPECTION_PROFILE_ENTRY, psiClass) - && isLastMethodDefinitionIn("getDescriptionContextClass", INSPECTION_PROFILE_ENTRY, psiClass) - && isLastMethodDefinitionIn("getDescriptionFileName", INSPECTION_PROFILE_ENTRY, psiClass)); + @Override + protected @InspectionMessage @NotNull String getHasNotDescriptionError(Module module, + PsiClass psiClass) { + final InspectionDescriptionInfo info = InspectionDescriptionInfo.create(module, psiClass); + final PsiMethod shortNameMethod = info.getShortNameMethod(); + return "Inspection does not have a description" + (shortNameMethod == null ? "" : " [" + shortNameMethod.getName() + "()]"); + } + + @Override + protected @InspectionMessage @NotNull String getHasNotBeforeAfterError() { + return ""; + } + + private static boolean isAnyPathMethodOverridden(PsiClass psiClass) { + return !(isLastMethodDefinitionIn("getStaticDescription", psiClass) + && isLastMethodDefinitionIn("getDescriptionContextClass", psiClass) + && isLastMethodDefinitionIn("getDescriptionFileName", psiClass)); } private static boolean isLastMethodDefinitionIn(@NotNull String methodName, - @NotNull String classFQN, @Nullable PsiClass psiClass) { if (psiClass == null) return false; for (PsiMethod method : psiClass.findMethodsByName(methodName, false)) { final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) return false; - return classFQN.equals(containingClass.getQualifiedName()); + return INSPECTION_PROFILE_ENTRY.equals(containingClass.getQualifiedName()); } - return isLastMethodDefinitionIn(methodName, classFQN, psiClass.getSuperClass()); + return isLastMethodDefinitionIn(methodName, psiClass.getSuperClass()); } - - @Override - @NotNull - public String getShortName() { - return "InspectionDescriptionNotFoundInspection"; - } - } diff --git a/plugins/devkit/devkit-core/src/inspections/IntentionDescriptionNotFoundInspection.java b/plugins/devkit/devkit-core/src/inspections/IntentionDescriptionNotFoundInspection.java index 9d3e2c6b5d46..25a776401acc 100644 --- a/plugins/devkit/devkit-core/src/inspections/IntentionDescriptionNotFoundInspection.java +++ b/plugins/devkit/devkit-core/src/inspections/IntentionDescriptionNotFoundInspection.java @@ -1,6 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.idea.devkit.inspections; +import com.intellij.openapi.module.Module; import com.intellij.psi.PsiClass; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.devkit.util.ExtensionCandidate; @@ -25,7 +26,7 @@ public class IntentionDescriptionNotFoundInspection extends DescriptionNotFoundI @Override @NotNull - protected String getHasNotDescriptionError() { + protected String getHasNotDescriptionError(Module module, PsiClass psiClass) { return "Intention does not have a description"; } diff --git a/plugins/devkit/devkit-core/src/inspections/PostfixTemplateDescriptionNotFoundInspection.java b/plugins/devkit/devkit-core/src/inspections/PostfixTemplateDescriptionNotFoundInspection.java index 6e84946fb259..eaa8ef6f82bc 100644 --- a/plugins/devkit/devkit-core/src/inspections/PostfixTemplateDescriptionNotFoundInspection.java +++ b/plugins/devkit/devkit-core/src/inspections/PostfixTemplateDescriptionNotFoundInspection.java @@ -15,6 +15,7 @@ */ package org.jetbrains.idea.devkit.inspections; +import com.intellij.openapi.module.Module; import com.intellij.psi.PsiClass; import org.jetbrains.annotations.NotNull; @@ -31,7 +32,7 @@ public class PostfixTemplateDescriptionNotFoundInspection extends DescriptionNot @NotNull @Override - protected String getHasNotDescriptionError() { + protected String getHasNotDescriptionError(Module module, PsiClass psiClass) { return "Postfix template does not have a description"; } diff --git a/plugins/devkit/devkit-core/src/util/PsiUtil.java b/plugins/devkit/devkit-core/src/util/PsiUtil.java index 7d5ad7897d92..1997e2c8ba33 100644 --- a/plugins/devkit/devkit-core/src/util/PsiUtil.java +++ b/plugins/devkit/devkit-core/src/util/PsiUtil.java @@ -2,13 +2,11 @@ package org.jetbrains.idea.devkit.util; import com.intellij.codeInsight.AnnotationUtil; -import com.intellij.codeInspection.dataFlow.StringExpressionHelper; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -62,71 +60,6 @@ public class PsiUtil { (cls.getContainingClass() == null || modifiers.hasModifierProperty(PsiModifier.STATIC)); } - @Nullable - public static String getReturnedLiteral(PsiMethod method, PsiClass cls) { - PsiExpression value = getReturnedExpression(method); - if (value instanceof PsiLiteralExpression) { - Object str = ((PsiLiteralExpression)value).getValue(); - return str == null ? null : str.toString(); - } - else if (value instanceof PsiMethodCallExpression) { - if (isSimpleClassNameExpression((PsiMethodCallExpression)value)) { - return cls.getName(); - } - } - else if (value != null) { - Pair evaluateResult = StringExpressionHelper.evaluateConstantExpression(value); - if (evaluateResult != null && value.equals(evaluateResult.first)) { - return evaluateResult.second; - } - } - return null; - } - - private static boolean isSimpleClassNameExpression(PsiMethodCallExpression expr) { - String text = expr.getText(); - if (text == null) return false; - if (!StringUtil.contains(text, "getSimpleName")) return false; - - text = text.replaceAll(" ", "") - .replaceAll("\n", "") - .replaceAll("\t", "") - .replaceAll("\r", ""); - return "getClass().getSimpleName()".equals(text) || "this.getClass().getSimpleName()".equals(text); - } - - @Nullable - public static PsiExpression getReturnedExpression(PsiMethod method) { - PsiCodeBlock body = method.getBody(); - if (body != null) { - PsiStatement[] statements = body.getStatements(); - if (statements.length != 1) return null; - - PsiStatement statement = statements[0]; - if (statement instanceof PsiReturnStatement) { - PsiExpression value = ((PsiReturnStatement)statement).getReturnValue(); - if (value instanceof PsiReferenceExpression) { - PsiElement element = ((PsiReferenceExpression)value).resolve(); - if (element instanceof PsiField) { - PsiField field = (PsiField)element; - if (field.hasModifierProperty(PsiModifier.FINAL)) { - return field.getInitializer(); - } - } - } - else if (value instanceof PsiMethodCallExpression && - !isSimpleClassNameExpression((PsiMethodCallExpression)value)) { - final PsiMethod calledMethod = ((PsiMethodCallExpression)value).resolveMethod(); - return calledMethod != null ? getReturnedExpression(calledMethod) : null; - } - - return value; - } - } - - return null; - } - @Nullable public static PsiMethod findNearestMethod(String name, @Nullable PsiClass cls) { if (cls == null) return null; diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/inspectionDescription/MyInspectionCustomShortName.java b/plugins/devkit/devkit-java-tests/testData/inspections/inspectionDescription/MyInspectionCustomShortName.java index 6330060de26d..cebc4c10ac11 100644 --- a/plugins/devkit/devkit-java-tests/testData/inspections/inspectionDescription/MyInspectionCustomShortName.java +++ b/plugins/devkit/devkit-java-tests/testData/inspections/inspectionDescription/MyInspectionCustomShortName.java @@ -1,8 +1,8 @@ import com.intellij.codeInspection.InspectionProfileEntry; -public class MyInspectionCustomShortName extends InspectionProfileEntry { +public class MyInspectionCustomShortName extends InspectionProfileEntry { public String getShortName() { - return "NOT_EXISTING_CUSTOM_SHORT_NAME"; + return "NOT_EXISTING_CUSTOM_SHORT_NAME"; } } \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/inspectionDescription/MyWithDescriptionAndShortNameInBaseInspection.java b/plugins/devkit/devkit-java-tests/testData/inspections/inspectionDescription/MyWithDescriptionAndShortNameInBaseInspection.java index 0f86879550f7..fc7b50dd88ee 100644 --- a/plugins/devkit/devkit-java-tests/testData/inspections/inspectionDescription/MyWithDescriptionAndShortNameInBaseInspection.java +++ b/plugins/devkit/devkit-java-tests/testData/inspections/inspectionDescription/MyWithDescriptionAndShortNameInBaseInspection.java @@ -7,4 +7,4 @@ class ALocalInspectionTool extends LocalInspectionTool { return com.intellij.codeInspection.InspectionProfileEntry.getShortName(name); } } -public class MyWithDescriptionAndShortNameInBaseInspection extends ALocalInspectionTool {} \ No newline at end of file +public class MyWithDescriptionAndShortNameInBaseInspection extends ALocalInspectionTool {} \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyInspection.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyInspection.kt new file mode 100644 index 000000000000..7db8e5f178a7 --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyInspection.kt @@ -0,0 +1,3 @@ +class MyInspection : com.intellij.codeInspection.InspectionProfileEntry() { + +} diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyInspectionCustomShortName.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyInspectionCustomShortName.kt new file mode 100644 index 000000000000..1cc88bbfaddb --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyInspectionCustomShortName.kt @@ -0,0 +1,5 @@ +class MyInspectionCustomShortName : com.intellij.codeInspection.InspectionProfileEntry() { + override fun getShortName(): String { + return "NOT_EXISTING_CUSTOM_SHORT_NAME" + } +} diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyOverridePathMethodInspection.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyOverridePathMethodInspection.kt new file mode 100644 index 000000000000..f2601673d1df --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyOverridePathMethodInspection.kt @@ -0,0 +1,5 @@ +class MyOverridePathMethodInspection : com.intellij.codeInspection.InspectionProfileEntry() { + override fun getStaticDescription(): String? { + return null + } +} \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyWithDescriptionCustomShortNameInspection.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyWithDescriptionCustomShortNameInspection.kt new file mode 100644 index 000000000000..0babf61fb9fc --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyWithDescriptionCustomShortNameInspection.kt @@ -0,0 +1,5 @@ +class MyWithDescriptionCustomShortNameInspection : com.intellij.codeInspection.InspectionProfileEntry() { + override fun getShortName(): String { + return "customShortName" + } +} \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyWithDescriptionInspection.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyWithDescriptionInspection.kt new file mode 100644 index 000000000000..e86b4f382c6a --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/MyWithDescriptionInspection.kt @@ -0,0 +1 @@ +class MyWithDescriptionInspection : com.intellij.codeInspection.InspectionProfileEntry() {} diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/inspectionDescriptions/MyWithDescription.html b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/inspectionDescriptions/MyWithDescription.html new file mode 100644 index 000000000000..2eef79ca6b97 --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/inspectionDescriptions/MyWithDescription.html @@ -0,0 +1 @@ +KtInspectionDescriptionNotFoundInspectionTest.testWithDescription \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/inspectionDescriptions/customShortName.html b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/inspectionDescriptions/customShortName.html new file mode 100644 index 000000000000..82d5950f46e9 --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/inspectionDescription/inspectionDescriptions/customShortName.html @@ -0,0 +1 @@ +KtInspectionDescriptionNotFoundInspectionTest.testWithDescriptionCustomShortName \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/inspections/KtInspectionDescriptionNotFoundInspectionTest.kt b/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/inspections/KtInspectionDescriptionNotFoundInspectionTest.kt new file mode 100644 index 000000000000..90f69e738da5 --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/inspections/KtInspectionDescriptionNotFoundInspectionTest.kt @@ -0,0 +1,57 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.idea.devkit.kotlin.inspections + +import com.intellij.codeInspection.LocalInspectionEP +import com.intellij.lang.LanguageExtensionPoint +import com.intellij.testFramework.TestDataPath +import com.intellij.testFramework.builders.JavaModuleFixtureBuilder +import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase +import com.intellij.util.PathUtil +import org.jetbrains.idea.devkit.inspections.InspectionDescriptionNotFoundInspection +import org.jetbrains.idea.devkit.kotlin.DevkitKtTestsUtil +import java.nio.file.Paths + +@TestDataPath("\$CONTENT_ROOT/testData/inspections/inspectionDescription") +class KtInspectionDescriptionNotFoundInspectionTest : JavaCodeInsightFixtureTestCase() { + + override fun getBasePath(): String? { + return DevkitKtTestsUtil.TESTDATA_PATH + "inspections/inspectionDescription" + } + + override fun tuneFixture(moduleBuilder: JavaModuleFixtureBuilder<*>) { + moduleBuilder.addLibrary("core-api", PathUtil.getJarPathForClass(LanguageExtensionPoint::class.java)) + moduleBuilder.addLibrary("analysis-api", PathUtil.getJarPathForClass(LocalInspectionEP::class.java)) + moduleBuilder.addLibrary("platform-resources", + Paths.get(PathUtil.getJarPathForClass(LocalInspectionEP::class.java)) + .resolveSibling("intellij.platform.resources").toString()) + } + + @Throws(Exception::class) + override fun setUp() { + super.setUp() + myFixture.enableInspections(InspectionDescriptionNotFoundInspection::class.java) + } + + fun testHighlightingForDescription() { + myFixture.testHighlighting("MyInspection.kt") + } + + fun testOverridePathMethod() { + myFixture.testHighlighting("MyOverridePathMethodInspection.kt") + } + + fun testHighlightingForDescriptionCustomShortName() { + myFixture.testHighlighting("MyInspectionCustomShortName.kt"); + } + + fun testWithDescription() { + myFixture.copyDirectoryToProject("inspectionDescriptions", "inspectionDescriptions") + myFixture.testHighlighting("MyWithDescriptionInspection.kt") + } + + fun testWithDescriptionCustomShortName() { + myFixture.copyDirectoryToProject("inspectionDescriptions", "inspectionDescriptions") + myFixture.testHighlighting("MyWithDescriptionCustomShortNameInspection.kt") + } + +} \ No newline at end of file