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 extends PsiClass> originalClasses;
- public AddQualifierFix(final List originalClasses) {
+ public AddQualifierFix(final List extends PsiClass> 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