mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-244325 [devkit] Convert InspectionDescriptionNotFoundInspection to UAST
GitOrigin-RevId: 9e8feeeb5cbd53c37bd43b29c5eaeb3de87329d7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ee78c14d55
commit
bbedc3df3b
+1
-1
@@ -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 "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"/>
|
||||
<localInspection language="JAVA" shortName="InspectionDescriptionNotFoundInspection" displayName="Inspection description checker"
|
||||
<localInspection language="UAST" shortName="InspectionDescriptionNotFoundInspection" displayName="Inspection description checker"
|
||||
groupPath="Plugin DevKit" groupKey="inspections.group.description.file"
|
||||
enabledByDefault="true" level="WARNING"
|
||||
implementationClass="org.jetbrains.idea.devkit.inspections.InspectionDescriptionNotFoundInspection"/>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<UExpression> 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;
|
||||
}
|
||||
}
|
||||
|
||||
+39
-48
@@ -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";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -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";
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -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";
|
||||
}
|
||||
|
||||
|
||||
@@ -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<PsiElement, String> 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;
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
|
||||
public class MyInspectionCustomShortName extends InspectionProfileEntry {
|
||||
public class <warning descr="Inspection does not have a description [getShortName()]">MyInspectionCustomShortName</warning> extends InspectionProfileEntry {
|
||||
|
||||
public String getShortName() {
|
||||
return <warning descr="Inspection does not have a description">"NOT_EXISTING_CUSTOM_SHORT_NAME"</warning>;
|
||||
return "NOT_EXISTING_CUSTOM_SHORT_NAME";
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -7,4 +7,4 @@ class ALocalInspectionTool extends LocalInspectionTool {
|
||||
return com.intellij.codeInspection.InspectionProfileEntry.getShortName(name);
|
||||
}
|
||||
}
|
||||
public class <warning descr="Inspection does not have a description">MyWithDescriptionAndShortNameInBaseInspection</warning> extends ALocalInspectionTool {}
|
||||
public class <warning descr="Inspection does not have a description [getShortName()]">MyWithDescriptionAndShortNameInBaseInspection</warning> extends ALocalInspectionTool {}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
class <warning descr="Inspection does not have a description">MyInspection</warning> : com.intellij.codeInspection.InspectionProfileEntry() {
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class <warning descr="Inspection does not have a description [getShortName()]">MyInspectionCustomShortName</warning> : com.intellij.codeInspection.InspectionProfileEntry() {
|
||||
override fun getShortName(): String {
|
||||
return "NOT_EXISTING_CUSTOM_SHORT_NAME"
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class MyOverridePathMethodInspection : com.intellij.codeInspection.InspectionProfileEntry() {
|
||||
override fun getStaticDescription(): String? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class MyWithDescriptionCustomShortNameInspection : com.intellij.codeInspection.InspectionProfileEntry() {
|
||||
override fun getShortName(): String {
|
||||
return "customShortName"
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
class MyWithDescriptionInspection : com.intellij.codeInspection.InspectionProfileEntry() {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
KtInspectionDescriptionNotFoundInspectionTest.testWithDescription
|
||||
+1
@@ -0,0 +1 @@
|
||||
KtInspectionDescriptionNotFoundInspectionTest.testWithDescriptionCustomShortName
|
||||
+57
@@ -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")
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user