From 7225738dae91f8dc31c9cecd3aeeabbd3f7e3fb0 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 3 Jun 2024 17:13:22 +0200 Subject: [PATCH] inspections: more clear presentation for unused declarations GitOrigin-RevId: c60846f8be2cc4e33fa525e6bc39123b3d1e89b3 --- .../reference/RefFunctionalExpression.java | 4 +- .../RefFunctionalExpressionImpl.java | 10 +- .../ex/HTMLJavaHTMLComposerImpl.java | 176 +++++++++--------- .../messages/AnalysisBundle.properties | 9 +- .../analysis-impl/api-dump-unreviewed.txt | 1 - .../codeInspection/ex/HTMLComposerImpl.java | 33 ---- 6 files changed, 111 insertions(+), 122 deletions(-) diff --git a/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefFunctionalExpression.java b/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefFunctionalExpression.java index df54a7498a38..c8262130590c 100644 --- a/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefFunctionalExpression.java +++ b/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefFunctionalExpression.java @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInspection.reference; import org.jetbrains.annotations.NotNull; @@ -29,4 +29,6 @@ public interface RefFunctionalExpression extends RefJavaElement, RefOverridable * Note that a method reference always contains a body. */ boolean hasEmptyBody(); + + boolean isMethodReference(); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFunctionalExpressionImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFunctionalExpressionImpl.java index 77757d99710b..aa6e08154493 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFunctionalExpressionImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFunctionalExpressionImpl.java @@ -18,6 +18,7 @@ import java.util.Collections; import java.util.List; public final class RefFunctionalExpressionImpl extends RefJavaElementImpl implements RefFunctionalExpression { + private static final int IS_METHOD_REFERENCE_MASK = 0b1_00000000_00000000; // 17th bit RefFunctionalExpressionImpl(@NotNull UExpression expr, @NotNull PsiElement psi, @NotNull RefManager manager) { super(expr, psi, manager); @@ -39,6 +40,7 @@ public final class RefFunctionalExpressionImpl extends RefJavaElementImpl implem if (uMethodRef != null) { setParameters(uMethodRef.getUastParameters()); } + setFlag(true, IS_METHOD_REFERENCE_MASK); } else { assert false; @@ -86,7 +88,7 @@ public final class RefFunctionalExpressionImpl extends RefJavaElementImpl implem @Override public void addDerivedReference(@NotNull RefOverridable reference) { - // do nothing + throw new AssertionError("Should not be called!"); } @NotNull @@ -108,6 +110,12 @@ public final class RefFunctionalExpressionImpl extends RefJavaElementImpl implem return checkFlag(RefMethodImpl.IS_BODY_EMPTY_MASK); } + @Override + public boolean isMethodReference() { + LOG.assertTrue(isInitialized()); + return checkFlag(IS_METHOD_REFERENCE_MASK); + } + @Override public void accept(@NotNull RefVisitor visitor) { if (visitor instanceof RefJavaVisitor javaVisitor) { diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/HTMLJavaHTMLComposerImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/HTMLJavaHTMLComposerImpl.java index 504f62cd8b8b..cca3adbcafca 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ex/HTMLJavaHTMLComposerImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/ex/HTMLJavaHTMLComposerImpl.java @@ -5,13 +5,13 @@ import com.intellij.analysis.AnalysisBundle; import com.intellij.codeInspection.HTMLJavaHTMLComposer; import com.intellij.codeInspection.reference.*; import com.intellij.java.JavaBundle; -import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.util.text.Strings; import com.intellij.psi.*; import com.intellij.util.containers.ContainerUtil; import com.intellij.xml.util.XmlStringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.uast.*; +import org.jetbrains.uast.UMethod; import java.util.List; @@ -24,21 +24,26 @@ public class HTMLJavaHTMLComposerImpl extends HTMLJavaHTMLComposer { @Override public void appendClassOrInterface(@NotNull StringBuilder buf, @NotNull RefClass refClass, boolean capitalizeFirstLetter) { - if (refClass.isInterface()) { - buf.append(capitalizeFirstLetter - ? AnalysisBundle.message("inspection.export.results.capitalized.interface") - : AnalysisBundle.message("inspection.export.results.interface")); + String message; + if (refClass.isAnnotationType()) { + message = AnalysisBundle.message("inspection.export.results.annotation.type"); + } + else if (refClass.isInterface()) { + message = AnalysisBundle.message("inspection.export.results.capitalized.interface"); } else if (refClass.isAbstract()) { - buf.append(capitalizeFirstLetter - ? AnalysisBundle.message("inspection.export.results.capitalized.abstract.class") - : AnalysisBundle.message("inspection.export.results.abstract.class")); + message = AnalysisBundle.message("inspection.export.results.capitalized.abstract.class"); + } + else if (refClass.isEnum()) { + message = AnalysisBundle.message("inspection.export.results.enum.class"); + } + else if (refClass.isRecord()) { + message = AnalysisBundle.message("inspection.export.results.record.class"); } else { - buf.append(capitalizeFirstLetter - ? AnalysisBundle.message("inspection.export.results.capitalized.class") - : AnalysisBundle.message("inspection.export.results.class")); + message = AnalysisBundle.message("inspection.export.results.capitalized.class"); } + buf.append(capitalizeFirstLetter ? Strings.capitalize(message) : message); } @Override @@ -116,7 +121,6 @@ public class HTMLJavaHTMLComposerImpl extends HTMLJavaHTMLComposer { buf.append(AnalysisBundle.message("inspection.export.results.field")); buf.append(HTMLComposerImpl.NBSP).append(HTMLComposerImpl.CODE_OPENING); - buf.append(XmlStringUtil.escapeString(psiField.getType().getPresentableText())); buf.append(HTMLComposerImpl.NBSP).append(HTMLComposerImpl.B_OPENING); buf.append(psiField.getName()); @@ -175,25 +179,19 @@ public class HTMLJavaHTMLComposerImpl extends HTMLJavaHTMLComposer { String name = RefJavaUtil.getInstance().getPackageName(entity); assert name != null; // name for default package: - buf.append(StringUtil.escapeXmlEntities(name)); + buf.append(XmlStringUtil.escapeString(name)); buf.append(HTMLComposerImpl.CODE_CLOSING); } else if (owner instanceof RefMethod) { - buf.append(AnalysisBundle.message("inspection.export.results.method")); - buf.append(HTMLComposerImpl.NBSP); - myComposer.appendElementReference(buf, (RefElement)owner); + myComposer.appendElementReference(buf, (RefElement)owner, false); } else if (owner instanceof RefField) { - buf.append(AnalysisBundle.message("inspection.export.results.field")); - buf.append(HTMLComposerImpl.NBSP); - myComposer.appendElementReference(buf, (RefElement)owner); + myComposer.appendElementReference(buf, (RefElement)owner, false); buf.append(HTMLComposerImpl.NBSP); buf.append(AnalysisBundle.message("inspection.export.results.initializer")); } else if (owner instanceof RefClass) { - appendClassOrInterface(buf, (RefClass)owner, false); - buf.append(HTMLComposerImpl.NBSP); - myComposer.appendElementReference(buf, (RefElement)owner); + myComposer.appendElementReference(buf, (RefElement)owner, false); } } @@ -215,89 +213,99 @@ public class HTMLJavaHTMLComposerImpl extends HTMLJavaHTMLComposer { } @Override - public void appendReferencePresentation(RefEntity refElement, @NotNull StringBuilder buf, final boolean isPackageIncluded) { + public void appendReferencePresentation(RefEntity refElement, @NotNull StringBuilder buf, boolean capitalize) { + String message; if (refElement instanceof RefImplicitConstructor) { - buf.append(JavaBundle.message("inspection.export.results.implicit.constructor")); - buf.append(" "); + message = JavaBundle.message("inspection.export.results.implicit.constructor"); refElement = ((RefImplicitConstructor)refElement).getOwnerClass(); } - - buf.append(HTMLComposerImpl.CODE_OPENING); - - if (refElement instanceof RefField field) { - UField psiField = field.getUastElement(); - buf.append(XmlStringUtil.escapeString(psiField.getType().getPresentableText())); - buf.append(HTMLComposerImpl.NBSP); + else if (refElement instanceof RefParameter) { + message = AnalysisBundle.message("inspection.export.results.parameter"); + } + else if (refElement instanceof RefField) { + message = AnalysisBundle.message("inspection.export.results.field"); } else if (refElement instanceof RefMethod method) { - UMethod psiMethod = method.getUastElement(); - PsiType returnType = psiMethod.getReturnType(); - - if (returnType != null) { - buf.append(XmlStringUtil.escapeString(returnType.getPresentableText())); - buf.append(HTMLComposerImpl.NBSP); + message = AnalysisBundle.message( + method.isConstructor() ? "inspection.export.results.constructor" : "inspection.export.results.method"); + } + else if (refElement instanceof RefClass refClass) { + if (refClass.isInterface()) { + message = refClass.isAnnotationType() + ? AnalysisBundle.message("inspection.export.results.annotation.type") + : AnalysisBundle.message("inspection.export.results.interface"); + } + else if (refClass.isEnum()) { + message = AnalysisBundle.message("inspection.export.results.enum.class"); + } + else if (refClass.isRecord()) { + message = AnalysisBundle.message("inspection.export.results.record.class"); + } + else if (refClass.isAbstract()) { + message = AnalysisBundle.message("inspection.export.results.abstract.class"); + } + else { + message = AnalysisBundle.message("inspection.export.results.class"); } } - - buf.append(HTMLComposerImpl.A_HREF_OPENING); - - buf.append(((RefElementImpl)refElement).getURL()); - - buf.append("\""); - - if (isPackageIncluded) { - buf.append(" qualifiedname=\""); - buf.append(refElement.getQualifiedName()); - buf.append("\""); + else if (refElement instanceof RefFunctionalExpression functionalExpression) { + message = functionalExpression.isMethodReference() + ? AnalysisBundle.message("inspection.export.results.method.reference") + : AnalysisBundle.message("inspection.export.results.lambda.expression"); } + else { + message = ""; + } + buf.append(capitalize ? Strings.capitalize(message) : message).append(HTMLComposerImpl.NBSP); + buf.append(HTMLComposerImpl.CODE_OPENING); + buf.append(HTMLComposerImpl.A_HREF_OPENING); + buf.append(((RefElementImpl)refElement).getURL()); + if (refElement instanceof RefClass) { + buf.append("\" qualifiedname=\"").append(XmlStringUtil.escapeString(refElement.getQualifiedName())); + } + buf.append("\">"); - buf.append(">"); - - if (refElement instanceof RefClass && ((RefClass)refElement).isAnonymous()) { - buf.append(AnalysisBundle.message("inspection.reference.anonymous")); + if (refElement instanceof RefClass refClass && refClass.isAnonymous() || + refElement instanceof RefFunctionalExpression) { + buf.append(XmlStringUtil.escapeString(AnalysisBundle.message("inspection.reference.anonymous"))); } else if (refElement instanceof RefJavaElement && ((RefJavaElement)refElement).isSyntheticJSP()) { buf.append(XmlStringUtil.escapeString(refElement.getName())); } - else if (refElement instanceof RefMethod) { - UMethod psiMethod = ((RefMethod)refElement).getUastElement(); - buf.append(psiMethod.getName()); - } - else if (refElement instanceof RefFunctionalExpression) { - UExpression functionalExpr = ((RefFunctionalExpression)refElement).getUastElement(); - if (functionalExpr instanceof ULambdaExpression) { - buf.append(refElement.getName()); - } - else if (functionalExpr instanceof UCallableReferenceExpression) { - buf.append(functionalExpr.asSourceString()); - } + else if (refElement instanceof RefMethod refMethod) { + UMethod uMethod = refMethod.getUastElement(); + buf.append(uMethod.getName()); + appendMethodParameters(buf, uMethod.getJavaPsi(), false); } else { buf.append(refElement.getName()); } buf.append(HTMLComposerImpl.A_CLOSING); - - if (refElement instanceof RefMethod refMethod) { - PsiMethod psiMethod = refMethod.getUastElement().getJavaPsi(); - appendMethodParameters(buf, psiMethod, false); - } - buf.append(HTMLComposerImpl.CODE_CLOSING); final RefEntity owner = refElement.getOwner(); if (owner != null) { - if ((refElement instanceof RefClass && ((RefClass)refElement).isAnonymous())) { - buf.append(" "); - buf.append(AnalysisBundle.message("inspection.export.results.anonymous.ref.in.owner")); - buf.append(" "); - myComposer.appendElementReference(buf, (RefElement) owner, isPackageIncluded); + if (refElement instanceof RefFunctionalExpression || + refElement instanceof RefParameter || + (refElement instanceof RefClass refClass && refClass.isAnonymous())) { + buf.append(" ").append(AnalysisBundle.message("inspection.export.results.anonymous.ref.in.owner")).append(" "); + myComposer.appendElementReference(buf, (RefElement) owner, false); } - else if (isPackageIncluded) { - buf.append(" ").append("").append("("); - myComposer.appendQualifiedName(buf, owner); - // buf.append(RefUtil.getPackageName(refElement)); - buf.append(")").append(HTMLComposerImpl.CODE_CLOSING); + else { + buf.append(" ").append(AnalysisBundle.message("inspection.export.results.anonymous.ref.in.owner")).append(" "); + buf.append(HTMLComposerImpl.CODE_OPENING); + if (owner instanceof RefElementImpl) { + buf.append(HTMLComposerImpl.A_HREF_OPENING); + buf.append(((RefElementImpl)owner).getURL()); + buf.append("\" qualifiedname=\"").append(XmlStringUtil.escapeString(owner.getQualifiedName())); + buf.append("\">"); + } + buf.append(owner.getName()); + if (owner instanceof RefElementImpl) { + buf.append(HTMLComposerImpl.A_CLOSING); + } + buf.append(HTMLComposerImpl.CODE_CLOSING); } } } @@ -310,11 +318,9 @@ public class HTMLJavaHTMLComposerImpl extends HTMLJavaHTMLComposer { PsiParameter param = params[i]; buf.append(XmlStringUtil.escapeString(param.getType().getPresentableText())); if (showNames) { - buf.append(' '); - buf.append(param.getName()); + buf.append(' ').append(param.getName()); } } buf.append(')'); } - } diff --git a/platform/analysis-api/resources/messages/AnalysisBundle.properties b/platform/analysis-api/resources/messages/AnalysisBundle.properties index 1bf889dd0cfd..1ef749863af0 100644 --- a/platform/analysis-api/resources/messages/AnalysisBundle.properties +++ b/platform/analysis-api/resources/messages/AnalysisBundle.properties @@ -72,6 +72,8 @@ inspection.display.name.syntax.error=Syntax error inspection.display.name.generic.error=Generic error inspection.export.results.abstract=abstract inspection.export.results.abstract.class=abstract\\ class +inspection.export.results.enum.class=enum +inspection.export.results.record.class=record inspection.export.results.anonymous.ref.in.owner=in inspection.export.results.at.line=at line inspection.export.results.capitalized.abstract.class=Abstract\\ class @@ -82,14 +84,19 @@ inspection.export.results.class=class inspection.export.results.constructor=constructor inspection.export.results.dead.code=unused declaration inspection.export.results.derived.methods=Derived methods +inspection.export.results.derived.functional.expressions=Derived lambdas and method references inspection.export.results.directory=directory inspection.export.results.extended=Extended by inspection.export.results.extended.implemented=Extended/implemented by inspection.export.results.extends.implements=Extends/implements inspection.export.results.field=field +inspection.export.results.lambda.expression=lambda expression +inspection.export.results.method.reference=method reference +inspection.export.results.parameter=parameter inspection.export.results.file=file inspection.export.results.initializer=initializer inspection.export.results.interface=interface +inspection.export.results.annotation.type=@interface inspection.export.results.method=method inspection.export.results.no.problems.found=No problems found inspection.export.results.overrides.implements=Overrides/implements @@ -107,7 +114,7 @@ inspection.processing.job.descriptor2=Analyzing code in inspection.progress.single.inspection.title=Running inspection ''{0}''\u2026 inspection.progress.profile.title=Inspecting code with profile ''{0}''\u2026 inspection.redirect.template=Injected element has problem: {0} (in {3}). -inspection.reference.anonymous=anonymous +inspection.reference.anonymous= inspection.reference.invalid=element no longer exists local.scopes.node.text=Local Scopes diff --git a/platform/analysis-impl/api-dump-unreviewed.txt b/platform/analysis-impl/api-dump-unreviewed.txt index 43f0879c6f39..cf7c2da6c3b3 100644 --- a/platform/analysis-impl/api-dump-unreviewed.txt +++ b/platform/analysis-impl/api-dump-unreviewed.txt @@ -2748,7 +2748,6 @@ a:com.intellij.codeInspection.ex.HTMLComposerImpl - appendElementReference(java.lang.StringBuilder,java.lang.String,java.lang.String,java.lang.String):V - appendListItem(java.lang.StringBuilder,com.intellij.codeInspection.reference.RefElement):V - appendNoProblems(java.lang.StringBuilder):V -- appendQualifiedName(java.lang.StringBuilder,com.intellij.codeInspection.reference.RefEntity):V - p:appendQuickFix(java.lang.StringBuilder,java.lang.String):V - p:appendResolution(java.lang.StringBuilder,com.intellij.codeInspection.reference.RefEntity,java.lang.String[]):V - a:compose(java.lang.StringBuilder,com.intellij.codeInspection.reference.RefEntity):V diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/HTMLComposerImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/HTMLComposerImpl.java index 4caeb89e95ea..e71769a6bf02 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/HTMLComposerImpl.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/HTMLComposerImpl.java @@ -9,9 +9,7 @@ import com.intellij.codeInspection.lang.InspectionExtensionsFactory; import com.intellij.codeInspection.reference.*; import com.intellij.lang.Language; import com.intellij.openapi.project.ProjectUtilCore; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -104,37 +102,6 @@ public abstract class HTMLComposerImpl extends HTMLComposer { } } - public void appendQualifiedName(@NotNull StringBuilder buf, RefEntity refEntity) { - if (refEntity == null) return; - - StringBuilder qName = new StringBuilder(); - - while (!(refEntity instanceof RefProject)) { - if (!qName.isEmpty()) qName.insert(0, "."); - - String name = null; - if (refEntity instanceof RefElement refElement) { - final HTMLComposerExtension extension = getLanguageExtension(refElement); - if (extension != null) { - name = extension.getQualifiedName(refEntity); - } - } - - if (name == null) { - name = refEntity.getName(); - } - - qName.insert(0, name); - if (Comparing.strEqual(refEntity.getName(), refEntity.getQualifiedName())) { - buf.append(StringUtil.escapeXmlEntities(qName.toString())); - return; - } - refEntity = refEntity.getOwner(); - } - - buf.append(StringUtil.escapeXmlEntities(qName.toString())); - } - @Override public void appendElementReference(@NotNull StringBuilder buf, RefElement refElement) { appendElementReference(buf, refElement, true);