From 0f1d1622f794f721e1e062f21bcdca8860168fcb Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 3 Sep 2010 14:55:09 +0400 Subject: [PATCH] nullity: initial tests --- .../inferNullity/NullityInferrer.java | 8 +- .../afterFieldsAssignment.java | 51 ++++++++++ .../afterMethodReturnValue.java | 84 ++++++++++++++++ .../afterParameterCheckedForNull.java | 37 +++++++ .../afterParameterDereferenced.java | 15 +++ .../afterParameterPassed2NotNull.java | 10 ++ .../beforeFieldsAssignment.java | 41 ++++++++ .../beforeMethodReturnValue.java | 74 ++++++++++++++ .../beforeParameterCheckedForNull.java | 34 +++++++ .../beforeParameterDereferenced.java | 15 +++ .../beforeParameterPassed2NotNull.java | 10 ++ .../nullityinferrer/lib/annotations.jar | Bin 0 -> 9958 bytes .../codeInsight/NullityInferrerTest.java | 91 ++++++++++++++++++ 13 files changed, 466 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/nullityinferrer/afterFieldsAssignment.java create mode 100644 java/java-tests/testData/codeInsight/nullityinferrer/afterMethodReturnValue.java create mode 100644 java/java-tests/testData/codeInsight/nullityinferrer/afterParameterCheckedForNull.java create mode 100644 java/java-tests/testData/codeInsight/nullityinferrer/afterParameterDereferenced.java create mode 100644 java/java-tests/testData/codeInsight/nullityinferrer/afterParameterPassed2NotNull.java create mode 100644 java/java-tests/testData/codeInsight/nullityinferrer/beforeFieldsAssignment.java create mode 100644 java/java-tests/testData/codeInsight/nullityinferrer/beforeMethodReturnValue.java create mode 100644 java/java-tests/testData/codeInsight/nullityinferrer/beforeParameterCheckedForNull.java create mode 100644 java/java-tests/testData/codeInsight/nullityinferrer/beforeParameterDereferenced.java create mode 100644 java/java-tests/testData/codeInsight/nullityinferrer/beforeParameterPassed2NotNull.java create mode 100644 java/java-tests/testData/codeInsight/nullityinferrer/lib/annotations.jar create mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/NullityInferrerTest.java diff --git a/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java b/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java index 742de47610f5..0804819b0b45 100644 --- a/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java +++ b/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java @@ -33,7 +33,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.HashSet; -class NullityInferrer { +public class NullityInferrer { private static final Logger LOG = Logger.getInstance("#" + NullityInferrer.class.getName()); private static final int MAX_PASSES = 10; @@ -248,13 +248,13 @@ class NullityInferrer { @Override public void visitAssignmentExpression(@NotNull PsiAssignmentExpression expression) { - super.visitExpression(expression.getRExpression()); + sometimesNull = expressionIsSometimesNull(expression.getRExpression()); } @Override public void visitConditionalExpression(@NotNull PsiConditionalExpression expression) { - super.visitExpression(expression.getThenExpression()); - super.visitExpression(expression.getElseExpression()); + sometimesNull = expressionIsSometimesNull(expression.getThenExpression()) || + expressionIsSometimesNull(expression.getElseExpression()); } @Override diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/afterFieldsAssignment.java b/java/java-tests/testData/codeInsight/nullityinferrer/afterFieldsAssignment.java new file mode 100644 index 000000000000..a262cbebf9da --- /dev/null +++ b/java/java-tests/testData/codeInsight/nullityinferrer/afterFieldsAssignment.java @@ -0,0 +1,51 @@ +import org.jetbrains.annotations.*; + +class Test { + @NotNull + String myFoo = ""; + + @Nullable + String myFoo1 = null; + + @NotNull + String myFoo2 = foo2(); + @NotNull String foo2() { return "";} + + @Nullable + String myFoo3 = foo3(); + @Nullable String foo3() { return null;} + + String myFoo4; + void setFoo4() { + myFoo4 = ""; + } + + @NotNull + final String myFoo5; + @Nullable + final String myFoo6; + @NotNull + final String myFoo7; + @Nullable + final String myFoo8; + final String myFoo9; + @Nullable + final String myFoo10; + + /** + * {@link #myFoo6} + */ + Test(@NotNull String param, @Nullable String paramNullable, String simpleParam) { + myFoo5 = ""; + myFoo6 = null; + myFoo7 = param; + myFoo8 = paramNullable; + myFoo9 = simpleParam; + myFoo10 = foo10(false); + } + + @Nullable + String foo10(boolean flag) { + return flag ? foo2() : foo3(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/afterMethodReturnValue.java b/java/java-tests/testData/codeInsight/nullityinferrer/afterMethodReturnValue.java new file mode 100644 index 000000000000..6ae0b5b7994f --- /dev/null +++ b/java/java-tests/testData/codeInsight/nullityinferrer/afterMethodReturnValue.java @@ -0,0 +1,84 @@ +import org.jetbrains.annotations.*; + +class Test { + @Nullable + String foo1() { + return null; + } + + @NotNull + String foo2() { + return ""; + } + + String foo3(String s) { + return s; + } + + String foo4(@NotNull String s) { + return s.substring(0); + } + + @NotNull + Integer foo5(Integer i) { + return i++; + } + + @NotNull + Integer foo6(Integer i) { + if (i == 0) return 1; + return i * foo6(i--); + } + + @Nullable + Integer foo7(boolean flag) { + return flag ? null : 1; + } + + @Nullable + Integer foo8(boolean flag) { + if (flag) { + return null; + } + else { + return 1; + } + } + + @Nullable + String bar9() { + return foo3(""); + } + + @Nullable + String foo9() { + return bar9(); + } + + + @Nullable + String bar10() { + return foo3(""); + } + + @NotNull + String bar101() { + return foo3(""); + } + + @Nullable + String foo10(boolean flag) { + return flag ? bar10() : bar101(); + } + + @NotNull + String foo11() { + class Foo{ + @Nullable + String mess() { + return null; + } + } + return ""; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/afterParameterCheckedForNull.java b/java/java-tests/testData/codeInsight/nullityinferrer/afterParameterCheckedForNull.java new file mode 100644 index 000000000000..264201b0308c --- /dev/null +++ b/java/java-tests/testData/codeInsight/nullityinferrer/afterParameterCheckedForNull.java @@ -0,0 +1,37 @@ +import org.jetbrains.annotations.*; + +class Test { + void bar(@Nullable String str) { + if (str == null) { + foo(str); + } + } + + String foo(String str) { + return str; + } + + @Nullable + String foo1(@Nullable String str) { + if (str == null); + return (str); + } + + @NotNull + String foo2(@Nullable String str) { + if (str == null); + return ((String)str); + } + + @Nullable + String fram(@Nullable String str, boolean b) { + if (str != null) { + return b ? str : "not null strimg"; + } + return "str was null"; + } + + + + +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/afterParameterDereferenced.java b/java/java-tests/testData/codeInsight/nullityinferrer/afterParameterDereferenced.java new file mode 100644 index 000000000000..facf5ede5ed3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/nullityinferrer/afterParameterDereferenced.java @@ -0,0 +1,15 @@ +import org.jetbrains.annotations.*; + +class Test { + void foo(@NotNull String s) { + s.substring(0); + } + + /** + * @param str + */ + void bar(@NotNull String str) { + if (str.substring(0) == null) { + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/afterParameterPassed2NotNull.java b/java/java-tests/testData/codeInsight/nullityinferrer/afterParameterPassed2NotNull.java new file mode 100644 index 000000000000..90113c2eb2fd --- /dev/null +++ b/java/java-tests/testData/codeInsight/nullityinferrer/afterParameterPassed2NotNull.java @@ -0,0 +1,10 @@ +import org.jetbrains.annotations.*; + +class Test { + void foo(@NotNull String s) { + } + + void bar(@NotNull String str) { + foo(str); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/beforeFieldsAssignment.java b/java/java-tests/testData/codeInsight/nullityinferrer/beforeFieldsAssignment.java new file mode 100644 index 000000000000..d08d088af2f2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/nullityinferrer/beforeFieldsAssignment.java @@ -0,0 +1,41 @@ +import org.jetbrains.annotations.*; + +class Test { + String myFoo = ""; + + String myFoo1 = null; + + String myFoo2 = foo2(); + @NotNull String foo2() { return "";} + + String myFoo3 = foo3(); + @Nullable String foo3() { return null;} + + String myFoo4; + void setFoo4() { + myFoo4 = ""; + } + + final String myFoo5; + final String myFoo6; + final String myFoo7; + final String myFoo8; + final String myFoo9; + final String myFoo10; + + /** + * {@link #myFoo6} + */ + Test(@NotNull String param, @Nullable String paramNullable, String simpleParam) { + myFoo5 = ""; + myFoo6 = null; + myFoo7 = param; + myFoo8 = paramNullable; + myFoo9 = simpleParam; + myFoo10 = foo10(false); + } + + String foo10(boolean flag) { + return flag ? foo2() : foo3(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/beforeMethodReturnValue.java b/java/java-tests/testData/codeInsight/nullityinferrer/beforeMethodReturnValue.java new file mode 100644 index 000000000000..405e31c84158 --- /dev/null +++ b/java/java-tests/testData/codeInsight/nullityinferrer/beforeMethodReturnValue.java @@ -0,0 +1,74 @@ +import org.jetbrains.annotations.*; + +class Test { + String foo1() { + return null; + } + + String foo2() { + return ""; + } + + String foo3(String s) { + return s; + } + + String foo4(String s) { + return s.substring(0); + } + + Integer foo5(Integer i) { + return i++; + } + + Integer foo6(Integer i) { + if (i == 0) return 1; + return i * foo6(i--); + } + + Integer foo7(boolean flag) { + return flag ? null : 1; + } + + Integer foo8(boolean flag) { + if (flag) { + return null; + } + else { + return 1; + } + } + + @Nullable + String bar9() { + return foo3(""); + } + + String foo9() { + return bar9(); + } + + + @Nullable + String bar10() { + return foo3(""); + } + + @NotNull + String bar101() { + return foo3(""); + } + + String foo10(boolean flag) { + return flag ? bar10() : bar101(); + } + + String foo11() { + class Foo{ + String mess() { + return null; + } + } + return ""; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/beforeParameterCheckedForNull.java b/java/java-tests/testData/codeInsight/nullityinferrer/beforeParameterCheckedForNull.java new file mode 100644 index 000000000000..cb4bb0bfabfc --- /dev/null +++ b/java/java-tests/testData/codeInsight/nullityinferrer/beforeParameterCheckedForNull.java @@ -0,0 +1,34 @@ +import org.jetbrains.annotations.*; + +class Test { + void bar(String str) { + if (str == null) { + foo(str); + } + } + + String foo(String str) { + return str; + } + + String foo1(String str) { + if (str == null); + return (str); + } + + String foo2(String str) { + if (str == null); + return ((String)str); + } + + String fram(String str, boolean b) { + if (str != null) { + return b ? str : "not null strimg"; + } + return "str was null"; + } + + + + +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/beforeParameterDereferenced.java b/java/java-tests/testData/codeInsight/nullityinferrer/beforeParameterDereferenced.java new file mode 100644 index 000000000000..dac5998473b6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/nullityinferrer/beforeParameterDereferenced.java @@ -0,0 +1,15 @@ +import org.jetbrains.annotations.*; + +class Test { + void foo(String s) { + s.substring(0); + } + + /** + * @param str + */ + void bar(String str) { + if (str.substring(0) == null) { + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/beforeParameterPassed2NotNull.java b/java/java-tests/testData/codeInsight/nullityinferrer/beforeParameterPassed2NotNull.java new file mode 100644 index 000000000000..1046c6119376 --- /dev/null +++ b/java/java-tests/testData/codeInsight/nullityinferrer/beforeParameterPassed2NotNull.java @@ -0,0 +1,10 @@ +import org.jetbrains.annotations.*; + +class Test { + void foo(@NotNull String s) { + } + + void bar(String str) { + foo(str); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/lib/annotations.jar b/java/java-tests/testData/codeInsight/nullityinferrer/lib/annotations.jar new file mode 100644 index 0000000000000000000000000000000000000000..54041925d764f9edca3ba12a758205f056d7f8fd GIT binary patch literal 9958 zcmeHN-ESLN6+h!R@kipu`A+%)Zkn`q(>TqpDAjIv%hYkYrjBiFZz!Z6Oq@yT%CRHQ zxN4yLu;OvwkQNDE5Yh^PkdSyl2(;pX4k+7E^c04jzkNMYGkcks@JrAO;>ldNUB4{h$5}gam)l~ISSu1Z=R9OswL>JOLJ?+6a zMzo{#imt2m>dO-KKT;|U)Ntj_-d9-jXOTo@1zoA@Z#X{6@so=ZMcr!>x+Ds71xrR_ zvYQXpk}lCFMV4salIY8Mi6rtM^w6v| zPM09*-o`Wl*HCs;+iaZn(TtBy`skDxrtxSjEt*`=>*eYWM$vsXW{uepm=itKmNKWKXXgJ?PBv-4HOZyP)Po(8SL83Fx1&T_2N7W%W>-;=fQFl>kaeq(cuEWN?mc`oX zUri;`_zmRbyo}6bUZNA}Y(h@oUzhVK`9?a4wIF9Q*`i!bWi$7SU&tZn{Nbke_yFwl zN&sL#&jvs>V8D-%=SQB00?6yrC}?{)*!3aG455sNLd1q?33tQL=~XFABQ(ml8`Q7T z7>)B~f-jSNnc~ZIC*)rZ%B!~lcTNk?<~}Al(*W2I54cbIXv#;^$3%Rzhy7`xmM1^2 z?j#@Y*$m!LtAYQ=u%18E6doVdQU|JAM%AkU)+VSu!1Q1fphG4=8Lo0BG zo4@;He*Ot==aKGgE!>%lUFQdj=N2NDFGa82y=eT$6Z1FTy4%o;cTG`c@yqh!7w7NB zVlnv8SdW<&{W|_^AKr=n?$YwsFX4ANT{+5xwbpJYxmgIpiJ$e+tdGvY#LM}c_fwgb zr7DmG}p_^9>M0cNKf1L^slDnn*~43!|r`PwNiY|PhcK_ zTt1md72s(6bO8n`k2w`!Ic0m*IZf>eJJaU zBCu!7BSGp6H|{Y!wFm$G$YsM9KniNOJqgduKArtM`)3D%6BdDCCxNgqU!j)+Z(G;D=m90Aj=nU~L z3-laU4@Ei+`RD!?`_?zWGB{m?fIFB>_inS{XG~u0qtjR_E#ljSTOWxJ4>qg&KxjkD zOgx{g*xmOX!CJPhW`dVUaUvMoc~ik5g>q0C*xU;4y~%nZ?idfB)XVEEoo-3qA0oXBw4? z4M5YT-9b2`rwQ)DFgh&rP^M=Ye&cb%U2NUdP8*%RyPZzsI1u9Gu`ImN*O+ zhbIn(Cd^2hEi}<-rv99N_v#!V#wqF!GhmE2X&)}mLJVc2nva2I3Hr{u0IfM-&pOgx zjxOJWt7UiF4$wNg^<2HSr`GlTTk5_IY+zEOJ{kk7LSVeEYQ_=KjYf5gV+mdMPaS3q z5doq5BSYB#mVddPCKy51p40HbVT-5V3@VsWhq>lfCJ2f(sKSPEWEHm?uK%qsvbGIbVcwhH73t(UH3DaL>{%yZJ zV7_M{iaNb%zyno1aij8I;Fe9cTM2$g!2ED?-@`4JXdha; z73FsZ%nuh0Vdxld9mN*Hwwhi**nfhcS6^brY>Pp+{$uTPL%!b zfwJA&;PlQxOVc}V{-I}o#HqaLV61I)IzJb>_YgomIM&v7w$ApPHQSFVh2|2>qPymf za|L^o?Z-<(u@|AD9*V^Qi*u{(M@M9bd*%jIY214QA@g9_mLQD9-uG7AW6gpo- z2+&QZWlL#SYTq&lrQe)!RoY_qj@`G@L!s4+$b9#vS_z$_Vmnd>`ZPc7*@^2MI$RNB{r; literal 0 HcmV?d00001 diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/NullityInferrerTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/NullityInferrerTest.java new file mode 100644 index 000000000000..cfdc7473b289 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/NullityInferrerTest.java @@ -0,0 +1,91 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight; + +import com.intellij.JavaTestUtil; +import com.intellij.codeInspection.inferNullity.NullityInferrer; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.roots.libraries.LibraryTable; +import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; + +/** + * User: anna + * Date: Sep 2, 2010 + */ +public class NullityInferrerTest extends CodeInsightTestCase { + @Override + protected String getTestDataPath() { + return JavaTestUtil.getJavaTestDataPath(); + } + + //-----------------------params and return values--------------------------------- + public void testParameterPassed2NotNull() throws Exception { + doTest(false); + } + + public void testParameterCheckedForNull() throws Exception { + doTest(false); + } + + public void testParameterDereferenced() throws Exception { + doTest(false); + } + + //-----------------------fields--------------------------------------------------- + public void testFieldsAssignment() throws Exception { + doTest(false); + } + + //-----------------------methods--------------------------------------------------- + public void testMethodReturnValue() throws Exception { + doTest(false); + } + + + private void doTest(boolean annotateLocalVariables) throws Exception { + final String nullityPath = "/codeInsight/nullityinferrer"; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final VirtualFile aLib = LocalFileSystem.getInstance().findFileByPath(getTestDataPath() + nullityPath + "/lib/annotations.jar"); + if (aLib != null) { + final VirtualFile file = JarFileSystem.getInstance().getJarRootForLocalFile(aLib); + if (file != null) { + final ModifiableRootModel model = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final LibraryTable libraryTable = model.getModuleLibraryTable(); + final Library library = libraryTable.createLibrary("test"); + + final Library.ModifiableModel libraryModel = library.getModifiableModel(); + libraryModel.addRoot(file.getUrl(), OrderRootType.CLASSES); + libraryModel.commit(); + model.commit(); + } + } + } + }); + + configureByFile(nullityPath + "/before" + getTestName(false) + ".java"); + final NullityInferrer nullityInferrer = new NullityInferrer(annotateLocalVariables, getProject()); + nullityInferrer.collect(getFile()); + nullityInferrer.apply(getProject()); + checkResultByFile(nullityPath + "/after" + getTestName(false)+ ".java"); + } +}