diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java index 58ca12a62866..d6de5a38b1e9 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java @@ -191,7 +191,7 @@ public class VisibilityInspection extends GlobalJavaBatchInspectionTool { //ignore anonymous classes. They do not have access modifiers. if (refElement instanceof RefClass) { RefClass refClass = (RefClass) refElement; - if (refClass.isAnonymous() || refClass.isTestCase() || refClass.isServlet() || refClass.isApplet() || refClass.isLocalClass()) return null; + if (refClass.isAnonymous() || refClass.isServlet() || refClass.isApplet() || refClass.isLocalClass()) return null; } @@ -208,7 +208,7 @@ public class VisibilityInspection extends GlobalJavaBatchInspectionTool { } if (refElement instanceof RefClass) { - if (isTopLevelClass(refElement) && !SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES) return null; + if (isTopLevelClass(refElement) && minLevel <= 0 && !SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES) return null; } //ignore interface members. They always have public access modifier. @@ -478,6 +478,10 @@ public class VisibilityInspection extends GlobalJavaBatchInspectionTool { @NotNull final ProblemDescriptionsProcessor processor) { final EntryPointsManager entryPointsManager = globalContext.getEntryPointsManager(manager); for (RefElement entryPoint : entryPointsManager.getEntryPoints()) { + //don't ignore entry points with explicit visibility requirements + if (entryPoint instanceof RefJavaElement && getMinVisibilityLevel((RefJavaElement)entryPoint) > 0) { + continue; + } ignoreElement(processor, entryPoint); } diff --git a/java/java-tests/testData/inspection/visibility/entryPointWithPredefinedVisibility/expected.xml b/java/java-tests/testData/inspection/visibility/entryPointWithPredefinedVisibility/expected.xml new file mode 100644 index 000000000000..29832e5d86ae --- /dev/null +++ b/java/java-tests/testData/inspection/visibility/entryPointWithPredefinedVisibility/expected.xml @@ -0,0 +1,8 @@ + + + + ThisClass.java + 2 + Can be package-private + + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/visibility/entryPointWithPredefinedVisibility/src/ThisClass.java b/java/java-tests/testData/inspection/visibility/entryPointWithPredefinedVisibility/src/ThisClass.java new file mode 100644 index 000000000000..95af44b7ae42 --- /dev/null +++ b/java/java-tests/testData/inspection/visibility/entryPointWithPredefinedVisibility/src/ThisClass.java @@ -0,0 +1,6 @@ +public class ThisClass { + public void foo() {} + public void bar() {} + + public static void main(String[] args) {} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/VisibilityInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/VisibilityInspectionTest.java index 02d3552cb264..655f8a47220a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/VisibilityInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/VisibilityInspectionTest.java @@ -1,8 +1,23 @@ package com.intellij.codeInspection; import com.intellij.JavaTestUtil; +import com.intellij.ToolExtensionPoints; +import com.intellij.codeInspection.reference.RefElement; +import com.intellij.codeInspection.visibility.EntryPointWithVisibilityLevel; import com.intellij.codeInspection.visibility.VisibilityInspection; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.WriteExternalException; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMember; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.util.PsiUtil; import com.intellij.testFramework.InspectionTestCase; +import com.intellij.testFramework.PlatformTestUtil; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; public class VisibilityInspectionTest extends InspectionTestCase { private VisibilityInspection myTool = new VisibilityInspection(); @@ -122,4 +137,57 @@ public class VisibilityInspectionTest extends InspectionTestCase { myTool.SUGGEST_PRIVATE_FOR_INNERS = true; doTest("visibility/usedFromAnotherPackage", myTool, false, true); } + + public void testEntryPointWithPredefinedVisibility() throws Exception { + PlatformTestUtil.registerExtension(Extensions.getRootArea(), ExtensionPointName.create(ToolExtensionPoints.DEAD_CODE_TOOL), new EntryPointWithVisibilityLevel() { + @Override + public void readExternal(Element element) throws InvalidDataException {} + + @Override + public void writeExternal(Element element) throws WriteExternalException {} + + @NotNull + @Override + public String getDisplayName() { + return "accepted visibility"; + } + + @Override + public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) { + return isEntryPoint(psiElement); + } + + @Override + public boolean isEntryPoint(@NotNull PsiElement psiElement) { + return psiElement instanceof PsiMethod && "foo".equals(((PsiMethod)psiElement).getName()) || psiElement instanceof PsiClass; + } + + @Override + public int getMinVisibilityLevel(PsiMember member) { + return member instanceof PsiMethod && isEntryPoint(member) ? PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL : -1; + } + + @Override + public boolean isSelected() { + return true; + } + + @Override + public void setSelected(boolean selected) {} + + @Override + public String getTitle() { + return getDisplayName(); + } + + @Override + public String getId() { + return getDisplayName(); + } + }, getTestRootDisposable()); + myTool.SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS = false; + myTool.SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES = false; + myTool.SUGGEST_PRIVATE_FOR_INNERS = true; + doTest("visibility/entryPointWithPredefinedVisibility", myTool, false, true); + } }