diff --git a/java/java-tests/testData/nullableAnnotations/lib_1.0/pkg/Conflict.class b/java/java-tests/testData/nullableAnnotations/lib_1.0/pkg/Conflict.class new file mode 100644 index 000000000000..832b67b9e0e8 Binary files /dev/null and b/java/java-tests/testData/nullableAnnotations/lib_1.0/pkg/Conflict.class differ diff --git a/java/java-tests/testData/nullableAnnotations/lib_1.0/pkg/Conflict.java b/java/java-tests/testData/nullableAnnotations/lib_1.0/pkg/Conflict.java new file mode 100644 index 000000000000..a2e736f6486c --- /dev/null +++ b/java/java-tests/testData/nullableAnnotations/lib_1.0/pkg/Conflict.java @@ -0,0 +1,5 @@ +package pkg; + +interface Conflict { + String getNullableSomething(); +} \ No newline at end of file diff --git a/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/Conflict.class b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/Conflict.class new file mode 100644 index 000000000000..2eaec7647d67 Binary files /dev/null and b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/Conflict.class differ diff --git a/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/Conflict.java b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/Conflict.java new file mode 100644 index 000000000000..07c8c8856ec5 --- /dev/null +++ b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/Conflict.java @@ -0,0 +1,5 @@ +package pkg; + +interface Conflict { + @javax.annotation.Nullable String getNullableSomething(); +} \ No newline at end of file diff --git a/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/NonNullApi.class b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/NonNullApi.class new file mode 100644 index 000000000000..83091db30b7f Binary files /dev/null and b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/NonNullApi.class differ diff --git a/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/NonNullApi.java b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/NonNullApi.java new file mode 100644 index 000000000000..913f6368ed05 --- /dev/null +++ b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/NonNullApi.java @@ -0,0 +1,10 @@ +package pkg; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@Target(ElementType.PACKAGE) +@javax.annotation.Nonnull +@javax.annotation.meta.TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER}) +public @interface NonNullApi { +} diff --git a/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/Test.class b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/Test.class new file mode 100644 index 000000000000..a6db593f4821 Binary files /dev/null and b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/Test.class differ diff --git a/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/Test.java b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/Test.java new file mode 100644 index 000000000000..a42e4afd0e80 --- /dev/null +++ b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/Test.java @@ -0,0 +1,5 @@ +package pkg; + +class Test { + String foo() {return "foo";} +} \ No newline at end of file diff --git a/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/package-info.class b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/package-info.class new file mode 100644 index 000000000000..2b68e6d8f646 Binary files /dev/null and b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/package-info.class differ diff --git a/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/package-info.java b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/package-info.java new file mode 100644 index 000000000000..d9ba35e190c7 --- /dev/null +++ b/java/java-tests/testData/nullableAnnotations/lib_2.0/pkg/package-info.java @@ -0,0 +1,4 @@ +// Recompile if necessary adding jsr305-3.0.2.jar to classpath +// e.g. javac -cp %USERPROFILE%\.m2\repository\com\google\code\findbugs\jsr305\3.0.2\jsr305-3.0.2.jar pkg/*.java +@NonNullApi +package pkg; \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/NullableNotNullManagerTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/NullableNotNullManagerTest.java index c54324d22603..d7bfca298af0 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/NullableNotNullManagerTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/NullableNotNullManagerTest.java @@ -1,11 +1,24 @@ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.java.codeInsight; -import com.intellij.codeInsight.AnnotationUtil; -import com.intellij.codeInsight.NullableNotNullManager; -import com.intellij.codeInsight.NullableNotNullManagerImpl; +import com.intellij.JavaTestUtil; +import com.intellij.codeInsight.*; +import com.intellij.java.testutil.MavenDependencyUtil; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.testFramework.LightPlatformTestCase; +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.PsiTestUtil; +import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import org.junit.Assume; import java.util.List; @@ -21,6 +34,23 @@ public class NullableNotNullManagerTest extends LightPlatformTestCase { myManager = (NullableNotNullManagerImpl)manager; } + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return new DefaultLightProjectDescriptor() { + @Override + public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) { + super.configureModule(module, model, contentEntry); + VirtualFile file = + LocalFileSystem.getInstance().refreshAndFindFileByPath(JavaTestUtil.getJavaTestDataPath() + "/nullableAnnotations/"); + MavenDependencyUtil.addFromMaven(model, "com.google.code.findbugs:jsr305:3.0.2"); + // Library order is important + PsiTestUtil.newLibrary("lib_2.0").classesRoot(file.findChild("lib_2.0")).addTo(model); + PsiTestUtil.newLibrary("lib_1.0").classesRoot(file.findChild("lib_1.0")).addTo(model); + } + }; + } + @Override protected void tearDown() throws Exception { try { @@ -33,6 +63,29 @@ public class NullableNotNullManagerTest extends LightPlatformTestCase { super.tearDown(); } } + + public void testSplitPackageContainerAnnotation() { + // Check that annotations work normally + NullabilityAnnotationInfo fooNullability = getMethodReturnNullability("pkg.Test", "foo"); + assertNotNull(fooNullability); + assertEquals(Nullability.NOT_NULL, fooNullability.getNullability()); + assertTrue(fooNullability.isContainer()); + + // Check the conflicting case + NullabilityAnnotationInfo nullability = getMethodReturnNullability("pkg.Conflict", "getNullableSomething"); + assertNull(nullability); + } + + private static NullabilityAnnotationInfo getMethodReturnNullability(String className, String methodName) { + JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); + GlobalSearchScope scope = GlobalSearchScope.allScope(getProject()); + NullableNotNullManager manager = NullableNotNullManager.getInstance(getProject()); + PsiClass testClass = facade.findClass(className, scope); + assertNotNull(testClass); + PsiMethod[] fooMethods = testClass.findMethodsByName(methodName, false); + assertSize(1, fooMethods); + return manager.findEffectiveNullabilityInfo(fooMethods[0]); + } public void testCannotAddNotNullToNullable() { assertNotNull(myManager);