IDEA-65566 Allow 'NotNull' as the default element behavior for a given class or package

This commit is contained in:
peter
2014-01-17 17:25:13 +01:00
parent 0b9321bc2f
commit 9ffaba9293
4 changed files with 66 additions and 3 deletions
@@ -23,7 +23,7 @@ import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizableStringList;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiModifierListOwner;
import com.intellij.psi.*;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -126,11 +126,38 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
}
public boolean isNullable(PsiModifierListOwner owner, boolean checkBases) {
return AnnotationUtil.isAnnotated(owner, getNullables(), checkBases, false);
if (AnnotationUtil.isAnnotated(owner, getNullables(), checkBases, false)) {
return true;
}
return owner instanceof PsiParameter && isContainerAnnotated(owner, "javax.annotation.ParametersAreNullableByDefault");
}
public boolean isNotNull(PsiModifierListOwner owner, boolean checkBases) {
return AnnotationUtil.isAnnotated(owner, getNotNulls(), checkBases, false);
if (AnnotationUtil.isAnnotated(owner, getNotNulls(), checkBases, false)) {
return true;
}
return owner instanceof PsiParameter && isContainerAnnotated(owner, "javax.annotation.ParametersAreNonnullByDefault");
}
private static boolean isContainerAnnotated(PsiModifierListOwner owner, String annotationFQN) {
PsiElement element = owner.getParent();
while (element != null) {
if (element instanceof PsiModifierListOwner &&
AnnotationUtil.isAnnotated((PsiModifierListOwner)element, annotationFQN, false, false)) {
return true;
}
if (element instanceof PsiClassOwner) {
String packageName = ((PsiClassOwner)element).getPackageName();
PsiPackage psiPackage = JavaPsiFacade.getInstance(element.getProject()).findPackage(packageName);
return psiPackage != null && AnnotationUtil.isAnnotated(psiPackage, annotationFQN, false, false);
}
element = element.getContext();
}
return false;
}
public List<String> getNullables() {
@@ -0,0 +1,25 @@
import foo.*;
class Some {
void foo() {
NotNullClass.foo(<warning descr="Passing 'null' argument to parameter annotated as @NotNull">null</warning>);
NotNullClass.foo("a");
NullableClass.foo(null);
NullableClass.foo("a");
AnotherPackageNotNull.foo(<warning descr="Passing 'null' argument to parameter annotated as @NotNull">null</warning>);
AnotherPackageNotNull.foo("a");
}
}
@javax.annotation.ParametersAreNonnullByDefault
class NotNullClass {
static void foo(String s) {}
}
@javax.annotation.ParametersAreNullableByDefault
class NullableClass {
static void foo(String s) {}
}
@@ -303,6 +303,16 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
public void testNotEqualsTypo() { doTest(); }
public void testAndEquals() { doTest(); }
public void testParametersAreNonnullByDefault() {
myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
myFixture.addClass("package javax.annotation; public @interface ParametersAreNullableByDefault {}");
myFixture.addClass("package foo; public class AnotherPackageNotNull { public static void foo(String s) {}}");
myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
doTest();
}
public void _testNullCheckBeforeInstanceof() { doTest(); } // http://youtrack.jetbrains.com/issue/IDEA-113220
}
@@ -305,6 +305,7 @@ nominvalue
nomonitoring
nonatomic
noninfingement
nonnull
nonschema
noorder
noparallel