[java-highlighting] IDEA-363260 Report javadoc parse errors as inspection warnings

GitOrigin-RevId: fd66c5f727623b919af048b5bb7b428edcf71ad2
This commit is contained in:
Tagir Valeev
2024-11-14 17:05:05 +00:00
committed by intellij-monorepo-bot
parent 515d32af52
commit 9341e35ff6
7 changed files with 75 additions and 9 deletions
@@ -5,15 +5,22 @@ import com.intellij.codeInsight.highlighting.HighlightErrorFilter;
import com.intellij.core.JavaPsiBundle;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.JavaDocElementType;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
public final class JavaHighlightErrorFilter extends HighlightErrorFilter {
@Override
public boolean shouldHighlightErrorElement(@NotNull PsiErrorElement element) {
String description = element.getErrorDescription();
if (isJavaDocProblem(element)) return false;
if (description.equals(JavaPsiBundle.message("expected.semicolon"))) {
PsiElement parent = element.getParent();
if (parent instanceof PsiExpressionStatement && !PsiUtil.isStatement(parent)) {
@@ -41,6 +48,16 @@ public final class JavaHighlightErrorFilter extends HighlightErrorFilter {
return true;
}
/**
* @param element error element to check
* @return true if this error is javadoc parsing problem. In this case, it's covered by JavadocParsingInspection.
*/
public static boolean isJavaDocProblem(@NotNull PsiErrorElement element) {
PsiElement parent = element.getParent();
return parent instanceof PsiDocComment || parent instanceof PsiDocTag || parent instanceof PsiDocTagValue ||
parent != null && parent.getNode().getElementType() == JavaDocElementType.DOC_REFERENCE_HOLDER;
}
private static boolean isAfterUnclosedStringLiteral(@NotNull PsiErrorElement element) {
PsiElement prevLeaf = PsiTreeUtil.prevCodeLeaf(element);
if (prevLeaf instanceof PsiJavaToken token) {
@@ -2,6 +2,7 @@
package com.intellij.codeInspection.javaDoc;
import com.intellij.codeInsight.daemon.impl.analysis.IncreaseLanguageLevelFix;
import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightErrorFilter;
import com.intellij.codeInsight.daemon.impl.quickfix.DeleteElementFix;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.codeInsight.javadoc.SnippetMarkup;
@@ -13,6 +14,8 @@ import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.PsiUpdateModCommandQuickFix;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.HtmlChunk;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
@@ -44,6 +47,7 @@ public final class JavadocDeclarationInspection extends LocalInspectionTool {
public boolean IGNORE_PERIOD_PROBLEM = true;
public boolean IGNORE_SELF_REFS = false;
public boolean IGNORE_DEPRECATED_ELEMENTS = false;
public boolean IGNORE_SYNTAX_ERRORS = false;
private boolean myIgnoreEmptyDescriptions = false;
@@ -66,11 +70,18 @@ public final class JavadocDeclarationInspection extends LocalInspectionTool {
@Override
public @NotNull OptPane getOptionsPane() {
return pane(
expandableString("ADDITIONAL_TAGS", JavaBundle.message("inspection.javadoc.label.text"), ","),
checkbox("IGNORE_THROWS_DUPLICATE", JavaBundle.message("inspection.javadoc.option.ignore.throws")),
checkbox("IGNORE_PERIOD_PROBLEM", JavaBundle.message("inspection.javadoc.option.ignore.period")),
checkbox("IGNORE_SELF_REFS", JavaBundle.message("inspection.javadoc.option.ignore.self.ref")),
expandableString("ADDITIONAL_TAGS", JavaBundle.message("inspection.javadoc.additional.tags"), ",")
.description(JavaBundle.message("inspection.javadoc.additional.tags.description")),
checkbox("IGNORE_THROWS_DUPLICATE", JavaBundle.message("inspection.javadoc.option.ignore.throws"))
.description(HtmlChunk.raw(JavaBundle.message("inspection.javadoc.option.ignore.throws.description"))),
checkbox("IGNORE_PERIOD_PROBLEM", JavaBundle.message("inspection.javadoc.option.ignore.period"))
.description(JavaBundle.message("inspection.javadoc.option.ignore.period.description")),
checkbox("IGNORE_SELF_REFS", JavaBundle.message("inspection.javadoc.option.ignore.self.ref"))
.description(JavaBundle.message("inspection.javadoc.option.ignore.self.ref.description")),
checkbox("IGNORE_DEPRECATED_ELEMENTS", JavaBundle.message("inspection.javadoc.option.ignore.deprecated"))
.description(JavaBundle.message("inspection.javadoc.option.ignore.deprecated.description")),
checkbox("IGNORE_SYNTAX_ERRORS", JavaBundle.message("inspection.javadoc.option.ignore.syntax.errors"))
.description(JavaBundle.message("inspection.javadoc.option.ignore.syntax.errors.description"))
);
}
@@ -84,6 +95,25 @@ public final class JavadocDeclarationInspection extends LocalInspectionTool {
}
}
@Override
public void visitErrorElement(@NotNull PsiErrorElement element) {
if (IGNORE_SYNTAX_ERRORS || !JavaHighlightErrorFilter.isJavaDocProblem(element)) return;
PsiElement parent = element.getParent();
TextRange range = element.getTextRangeInParent();
if (range.isEmpty()) {
range = new TextRange(range.getStartOffset(), range.getEndOffset() + 1);
if (range.getEndOffset() > parent.getTextLength()) {
range = range.shiftLeft(1);
}
}
holder.problem(parent, element.getErrorDescription())
.range(range)
.highlight(ProblemHighlightType.GENERIC_ERROR)
.fix(new UpdateInspectionOptionFix(JavadocDeclarationInspection.this, "IGNORE_SYNTAX_ERRORS",
JavaBundle.message("inspection.javadoc.option.ignore.syntax.errors"), true))
.register();
}
@Override
public void visitModule(@NotNull PsiJavaModule module) {
checkModule(module, holder);
@@ -26,9 +26,5 @@ Reports Javadoc comments and tags with the following problems:
</code></pre>
<p>Quick-fix adds the unknown Javadoc tag to the list of user defined additional tags.</p>
<!-- tooltip end -->
<p>Use textfield below to define additional Javadoc tags.</p>
<p>Use first checkbox to ignore duplicated 'throws' tag.</p>
<p>Use second checkbox to ignore problem with missing or incomplete first sentence in the description.</p>
<p>Use third checkbox to ignore references pointing to itself.</p>
</body>
</html>
@@ -0,0 +1,7 @@
class Foo {
/**
* <warning descr="'@throws' tag description is missing">@throws</warning> RuntimeException<error descr="Identifier expected">.</error>
*/
void foo() {
}
}
@@ -0,0 +1,7 @@
class Foo {
/**
* <warning descr="'@throws' tag description is missing">@throws</warning> RuntimeException.
*/
void foo() {
}
}
@@ -74,6 +74,8 @@ public class JavadocDeclarationHighlightingTest extends LightDaemonAnalyzerTestC
public void testException2() { doTest(); }
public void testException3() { doTest(); }
public void testException4() { doTest(); }
public void testExceptionWrongDot() { doTest(); }
public void testExceptionWrongDotIgnored() { myInspection.IGNORE_SYNTAX_ERRORS = true; doTest(); }
public void testInheritJavaDoc() { setLanguageLevel(LanguageLevel.JDK_1_3); doTest(); }
public void testLink0() { doTest(); }
public void testLinkFromInnerClassToSelfMethod() { doTest(); }
@@ -498,15 +498,22 @@ inspection.replace.javadoc.display.name=Comment replaceable with Javadoc
inspection.missingJavadoc.label.minimalVisibility=Minimal visibility:
inspection.missingJavadoc.label.requiredTags=Required tags:
inspection.javadocDeclaration.display.name=Javadoc declaration problems
inspection.javadoc.label.text=Additional Javadoc tags:
inspection.javadoc.additional.tags=Additional Javadoc tags:
inspection.javadoc.additional.tags.description=List of known non-standard tags
inspection.javadoc.lint.display.name=HTML problems in Javadoc (DocLint)
inspection.javadoc.method.problem.missing.param.tag=Required tag <code>@param</code> is missing for parameter {0}
inspection.javadoc.method.problem.missing.tag.description={0} tag description is missing
inspection.javadoc.option.ignore.deprecated=Ignore elements marked as @deprecated
inspection.javadoc.option.ignore.deprecated.description=Do not report any problems in Javadoc describing deprecated classes or members
inspection.javadoc.option.ignore.syntax.errors=Ignore Javadoc syntax errors
inspection.javadoc.option.ignore.syntax.errors.description=Do not report Javadoc parse errors, such as malformed references
inspection.javadoc.option.ignore.period=Ignore period problems
inspection.javadoc.option.ignore.period.description=Do not report problems related to missing or incomplete first sentence of the description.
inspection.javadoc.option.ignore.self.ref=Ignore Javadoc pointing to itself
inspection.javadoc.option.ignore.self.ref.description=Do not report references in Javadoc pointing to the same element
inspection.javadoc.option.ignore.simple=Ignore simple property accessors
inspection.javadoc.option.ignore.throws=Ignore duplicate 'throws' tag
inspection.javadoc.option.ignore.throws.description=Do not report repeating <code>@throws</code> tags describing the same exception
inspection.javadoc.option.tab.title=Class
inspection.javadoc.option.tab.title.field=Field
inspection.javadoc.option.tab.title.inner.class=Inner class