diff --git a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocReferenceInspection.java b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocReferenceInspection.java index f09c9ee28451..2c36c5dbd873 100644 --- a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocReferenceInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocReferenceInspection.java @@ -8,6 +8,7 @@ import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInspection.*; +import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.ide.DataManager; import com.intellij.ide.util.FQNameCellRenderer; import com.intellij.openapi.actionSystem.CommonDataKeys; @@ -17,12 +18,16 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.javadoc.*; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtilCore; import com.intellij.psi.util.proximity.PsiProximityComparator; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.util.*; import static com.intellij.codeInspection.ProblemHighlightType.LIKE_UNKNOWN_SYMBOL; @@ -30,6 +35,15 @@ import static com.intellij.codeInspection.ProblemHighlightType.LIKE_UNKNOWN_SYMB public class JavaDocReferenceInspection extends LocalInspectionTool { private static final String SHORT_NAME = "JavadocReference"; + @SuppressWarnings("WeakerAccess") + public boolean REPORT_INACCESSIBLE; + + @Nullable + @Override + public JComponent createOptionsPanel() { + return new SingleCheckboxOptionsPanel("Report inaccessible symbols
(javadoc tool maybe unable to create hyperlink)", this, "REPORT_INACCESSIBLE"); + } + protected LocalQuickFix createAddQualifierFix(PsiJavaCodeReferenceElement reference) { List classesToImport = new ImportClassFix(reference).getClassesToImport(); return classesToImport.isEmpty() ? null : new AddQualifierFix(classesToImport); @@ -39,6 +53,29 @@ public class JavaDocReferenceInspection extends LocalInspectionTool { return new RenameReferenceQuickFix(unboundParams); } + private String getResolveErrorMessage(PsiElement resolved, @NotNull PsiElement context, CharSequence referenceText) { + if (resolved == null) { + return InspectionsBundle.message("inspection.javadoc.problem.cannot.resolve", "" + referenceText + ""); + } + + if (REPORT_INACCESSIBLE && !isAccessible(resolved, context)) { + return InspectionsBundle.message("inspection.javadoc.problem.inaccessible", "" + referenceText + ""); + } + + return null; + } + + private static boolean isAccessible(@NotNull PsiElement resolved, @NotNull PsiElement context) { + if (!(resolved instanceof PsiMember)) { + return true; + } + if (!PsiResolveHelper.SERVICE.getInstance(resolved.getProject()).isAccessible((PsiMember)resolved, context, null)) { + return false; + } + VirtualFile file = PsiUtilCore.getVirtualFile(resolved); + return file == null || context.getResolveScope().contains(file); + } + private void visitRefInDocTag(PsiDocTag tag, JavadocManager manager, PsiElement context, ProblemsHolder holder, boolean isOnTheFly) { PsiDocTagValue value = tag.getValueElement(); if (value == null) return; @@ -57,14 +94,19 @@ public class JavaDocReferenceInspection extends LocalInspectionTool { PsiReference reference = value.getReference(); if (reference == null) return; PsiElement element = reference.resolve(); - if (element != null) return; + int textOffset = value.getTextOffset(); if (textOffset == value.getTextRange().getEndOffset()) return; PsiDocTagValue valueElement = tag.getValueElement(); if (valueElement == null) return; - CharSequence paramName = value.getContainingFile().getViewProvider().getContents().subSequence(textOffset, value.getTextRange().getEndOffset()); String params = "" + paramName + ""; + + String message = getResolveErrorMessage(element, context, paramName); + if (message == null) { + return; + } + List fixes = new ArrayList<>(); if (isOnTheFly && "param".equals(tagName)) { PsiDocCommentOwner commentOwner = PsiTreeUtil.getParentOfType(tag, PsiDocCommentOwner.class); @@ -85,9 +127,8 @@ public class JavaDocReferenceInspection extends LocalInspectionTool { } fixes.add(new RemoveTagFix(tagName, paramName)); - LocalQuickFix[] array = fixes.toArray(LocalQuickFix.EMPTY_ARRAY); - holder.registerProblem(holder.getManager().createProblemDescriptor( - valueElement, reference.getRangeInElement(), cannotResolveSymbolMessage(params), LIKE_UNKNOWN_SYMBOL, isOnTheFly, array)); + holder.registerProblem(holder.getManager().createProblemDescriptor(valueElement, reference.getRangeInElement(), message, + LIKE_UNKNOWN_SYMBOL, isOnTheFly, fixes.toArray(LocalQuickFix.EMPTY_ARRAY))); } @Override @@ -152,7 +193,7 @@ public class JavaDocReferenceInspection extends LocalInspectionTool { }; } - private void checkComment(PsiDocComment comment, PsiElement context, ProblemsHolder holder, boolean isOnTheFly) { + private void checkComment(PsiDocComment comment, @NotNull PsiElement context, ProblemsHolder holder, boolean isOnTheFly) { if (comment == null) return; JavadocManager javadocManager = JavadocManager.SERVICE.getInstance(holder.getProject()); @@ -166,10 +207,12 @@ public class JavaDocReferenceInspection extends LocalInspectionTool { public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { super.visitReferenceElement(reference); JavaResolveResult result = reference.advancedResolve(false); - if (result.getElement() == null && !result.isPackagePrefixPackageReference()) { + PsiElement resolved = result.getElement(); + String message = getResolveErrorMessage(resolved, context, reference.getText()); + if (message != null && !result.isPackagePrefixPackageReference()) { PsiElement referenceNameElement = reference.getReferenceNameElement(); PsiElement element = referenceNameElement != null ? referenceNameElement : reference; - String message = cannotResolveSymbolMessage("" + reference.getText() + ""); + LocalQuickFix fix = isOnTheFly ? createAddQualifierFix(reference) : null; holder.registerProblem(holder.getManager().createProblemDescriptor(element, message, fix, LIKE_UNKNOWN_SYMBOL, isOnTheFly)); } @@ -199,10 +242,6 @@ public class JavaDocReferenceInspection extends LocalInspectionTool { }); } - private static String cannotResolveSymbolMessage(String params) { - return InspectionsBundle.message("inspection.javadoc.problem.cannot.resolve", params); - } - private static class RenameReferenceQuickFix implements LocalQuickFix { private final Set myUnboundParams; @@ -240,9 +279,9 @@ public class JavaDocReferenceInspection extends LocalInspectionTool { } private static class AddQualifierFix implements LocalQuickFix { - private final List originalClasses; + private final List originalClasses; - public AddQualifierFix(final List originalClasses) { + public AddQualifierFix(final List originalClasses) { this.originalClasses = originalClasses; } diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index 48ee14c8024d..691a4ec27dcd 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -315,6 +315,7 @@ inspection.javadoc.problem.missing.tag=Required tag {0} is missing inspection.javadoc.problem.missing.tag.description={0} is missing after @{1} tag inspection.javadoc.problem.see.tag.expecting.ref=Class/method reference, quoted text, or HTML link are expected after @see tag inspection.javadoc.problem.cannot.resolve=Cannot resolve symbol {0} +inspection.javadoc.problem.inaccessible=Symbol {0} is inaccessible from here inspection.javadoc.problem.name.expected=Name expected inspection.javadoc.problem.wrong.tag=Wrong tag {0} inspection.javadoc.problem.disallowed.tag=Tag {0} is not allowed here