diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9NonAccessibleTypeExposedInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9NonAccessibleTypeExposedInspection.java index 44d0476d689d..ab4cdfb2ed10 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9NonAccessibleTypeExposedInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9NonAccessibleTypeExposedInspection.java @@ -25,6 +25,7 @@ import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; @@ -109,16 +110,19 @@ public class Java9NonAccessibleTypeExposedInspection extends BaseJavaLocalInspec PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement(); if (referenceElement != null) { PsiElement resolved = referenceElement.resolve(); - if (resolved instanceof PsiClass && !isModulePublicApi((PsiClass)resolved)) { - PsiAnnotationOwner owner = annotation.getOwner(); - if (isModulePublicApi(owner)) { - myHolder.registerProblem(referenceElement, CLASS_IS_NOT_EXPORTED); - } - if (owner instanceof PsiParameter) { - PsiElement parent = ((PsiParameter)owner).getParent(); - if (parent instanceof PsiMember && isModulePublicApi((PsiMember)parent)) { + if (resolved instanceof PsiClass) { + PsiClass annotationClass = (PsiClass)resolved; + if (isInModuleSource(annotationClass) && !isModulePublicApi(annotationClass)) { + PsiAnnotationOwner owner = annotation.getOwner(); + if (isModulePublicApi(owner)) { myHolder.registerProblem(referenceElement, CLASS_IS_NOT_EXPORTED); } + if (owner instanceof PsiParameter) { + PsiElement parent = ((PsiParameter)owner).getParent(); + if (parent instanceof PsiMember && isModulePublicApi((PsiMember)parent)) { + myHolder.registerProblem(referenceElement, CLASS_IS_NOT_EXPORTED); + } + } } } } @@ -132,7 +136,7 @@ public class Java9NonAccessibleTypeExposedInspection extends BaseJavaLocalInspec } private void checkType(PsiClass psiClass, @NotNull PsiElement typeElement) { - if (psiClass != null && isInModuleSource(psiClass) && !isModulePublicApi(psiClass)) { + if (psiClass != null && !(psiClass instanceof PsiTypeParameter) && isInModuleSource(psiClass) && !isModulePublicApi(psiClass)) { myHolder.registerProblem(typeElement, CLASS_IS_NOT_EXPORTED); } } @@ -171,6 +175,19 @@ public class Java9NonAccessibleTypeExposedInspection extends BaseJavaLocalInspec if (parent instanceof PsiMember) { return isModulePublicApi((PsiMember)parent); } + if (parent instanceof PsiReferenceParameterList) { + PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class); + return isModulePublicApi(method); + } + } + else if (owner instanceof PsiTypeParameter) { + PsiElement parent = ((PsiTypeParameter)owner).getParent(); + if (parent instanceof PsiTypeParameterList) { + PsiElement grandParent = parent.getParent(); + if (grandParent instanceof PsiMember) { + return isModulePublicApi((PsiMember)grandParent); + } + } } return false; } diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/Java9NonAccessibleTypeExposedTest.kt b/java/java-tests/testSrc/com/intellij/codeInspection/Java9NonAccessibleTypeExposedTest.kt index 0caaef127bdf..21d34e9e27de 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/Java9NonAccessibleTypeExposedTest.kt +++ b/java/java-tests/testSrc/com/intellij/codeInspection/Java9NonAccessibleTypeExposedTest.kt @@ -217,6 +217,7 @@ public class Highlighted { fun testPublicAnnotation() { add("apiPkg", "MyAnnotation", "public @interface MyAnnotation {}") highlight("""package apiPkg; +@MyAnnotation public class Highlighted { @MyAnnotation public PublicApi field; @MyAnnotation public Highlighted() {} @@ -231,6 +232,7 @@ public class Highlighted { fun testPackageLocalAnnotation() { add("apiPkg", "MyAnnotation", "@interface MyAnnotation {}") highlight("""package apiPkg; +@MyAnnotation public class Highlighted { @MyAnnotation public PublicApi field; @MyAnnotation public Highlighted() {} @@ -246,6 +248,7 @@ public class Highlighted { add("implPkg", "MyAnnotation", "public @interface MyAnnotation {}") highlight("""package apiPkg; import implPkg.MyAnnotation; +@MyAnnotation public class Highlighted { @MyAnnotation public PublicApi field; @MyAnnotation public Highlighted() {} @@ -257,6 +260,32 @@ public class Highlighted { """) } + fun testTypeParameterAndUseAnnotation() { + highlight("""package apiPkg; +import java.lang.annotation.*; +import java.util.*; +@Highlighted.PublicAnnotation +@Highlighted.PackageLocalAnnotation +public class Highlighted { + @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface PublicAnnotation {} + @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @interface PackageLocalAnnotation {} + + public class C1<@PublicAnnotation T> { + public void foo(Set<@PublicAnnotation String> s) {} + protected <@PublicAnnotation X> void bar(X x) {} + protected List<@PublicAnnotation T> baz() { return new ArrayList<@PublicAnnotation T>();} + } + public class C2<@PackageLocalAnnotation T> { + public void foo(Set<@PackageLocalAnnotation String> s) {} + protected <@PackageLocalAnnotation X> void bar(X x) {} + protected List<@PackageLocalAnnotation T> baz() { + return new ArrayList<@PackageLocalAnnotation T>(); + } + } +} +""") + } + private fun highlight(@Language("JAVA") @NotNull @NonNls text: String) { val file = addFile("apiPkg/Highlighted.java", text, MAIN) myFixture.configureFromExistingVirtualFile(file)