Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2012-01-28 19:42:28 +0000
committerStephan Herrmann2012-01-28 19:42:28 +0000
commit2c38ab4d76d7def0495e781b84c159ff2b585512 (patch)
treed4e6d53cca5f3dd7402b444af6018b432d29887f /org.eclipse.jdt.core.tests.compiler
parent8574731a0f2dc482cebc92613334e05b97ad83d0 (diff)
downloadorg.eclipse.objectteams-2c38ab4d76d7def0495e781b84c159ff2b585512.tar.gz
org.eclipse.objectteams-2c38ab4d76d7def0495e781b84c159ff2b585512.tar.xz
org.eclipse.objectteams-2c38ab4d76d7def0495e781b84c159ff2b585512.zip
Basic merge to M5 using jdt.core v20120125-1544
Diffstat (limited to 'org.eclipse.jdt.core.tests.compiler')
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AnnotationDietRecoveryTest.java57
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AmbiguousMethodTest.java30
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java677
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java432
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java29
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java66
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java117
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java86
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InitializationTests.java40
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java239
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java42
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java633
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java18
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java2816
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java3192
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java529
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java7
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java1870
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/XLargeTest.java96
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java28
20 files changed, 9168 insertions, 1836 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AnnotationDietRecoveryTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AnnotationDietRecoveryTest.java
index 695aa4656..6e8ba3610 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AnnotationDietRecoveryTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AnnotationDietRecoveryTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -1909,4 +1909,59 @@ public void test0040() {
expectedCompletionDietUnitToString,
testName);
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=366003
+public void test0041() {
+
+ String s =
+ "package snippet;\n" +
+ "public class Bug366003 {\n" +
+ " void foo(Object o1){}\n" +
+ " @Blah org.User(@Bla String str){}\n" +
+ "}\n";
+
+ String expectedDietUnitToString =
+ "package snippet;\n" +
+ "public class Bug366003 {\n" +
+ " public Bug366003() {\n" +
+ " }\n" +
+ " void foo(Object o1) {\n" +
+ " }\n" +
+ " @Blah User(@Bla String str) {\n" +
+ " }\n" +
+ "}\n";
+
+ String expectedDietPlusBodyUnitToString =
+ "package snippet;\n" +
+ "public class Bug366003 {\n" +
+ " public Bug366003() {\n" +
+ " super();\n" +
+ " }\n" +
+ " void foo(Object o1) {\n" +
+ " }\n" +
+ " @Blah User(@Bla String str) {\n" +
+ " }\n" +
+ "}\n";
+
+ String expectedFullUnitToString = expectedDietUnitToString;
+
+ String expectedCompletionDietUnitToString =
+ "package snippet;\n" +
+ "public class Bug366003 {\n" +
+ " public Bug366003() {\n" +
+ " }\n" +
+ " void foo(Object o1) {\n" +
+ " }\n" +
+ " User(@Bla String str) {\n" +
+ " }\n" +
+ "}\n";
+
+ String testName = "<annotation recovery>";
+ checkParse(
+ s.toCharArray(),
+ expectedDietUnitToString,
+ expectedDietPlusBodyUnitToString,
+ expectedFullUnitToString,
+ expectedCompletionDietUnitToString,
+ testName);
+}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AmbiguousMethodTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AmbiguousMethodTest.java
index d2471118d..0c6446f88 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AmbiguousMethodTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AmbiguousMethodTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -76,6 +76,7 @@ public class AmbiguousMethodTest extends AbstractComparableTest {
}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=122881
public void test002() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_7) {
this.runConformTest(
new String[] {
"X.java",
@@ -92,8 +93,31 @@ public class AmbiguousMethodTest extends AbstractComparableTest {
" }\n" +
"}"
},
- "works"
- );
+ "works");
+ } else {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static interface I1<E1> { void method(E1 o); }\n" +
+ " static interface I2<E2> { void method(E2 o); }\n" +
+ " static interface I3<E3, E4> extends I1<E3>, I2<E4> {}\n" +
+ " static class Class1 implements I3<String, String> {\n" +
+ " public void method(String o) { System.out.println(o); }\n" +
+ " }\n" +
+ " public static void main(String[] args) {\n" +
+ " I3<String, String> i = new Class1();\n" +
+ " i.method(\"works\");\n" +
+ " }\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " static interface I3<E3, E4> extends I1<E3>, I2<E4> {}\n" +
+ " ^^\n" +
+ "Name clash: The method method(E1) of type X.I1<E1> has the same erasure as method(E2) of type X.I2<E2> but does not override it\n" +
+ "----------\n");
+ }
}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=122881
public void test002a() {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java
index 36aaf2e15..4a8b0fadc 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,8 +7,10 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 295551
- * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 185682 - Increment/decrement operators mark local variables as read
+ * Stephan Herrmann - Contributions for
+ * bug 295551 - Add option to automatically promote all warnings to error
+ * bug 185682 - Increment/decrement operators mark local variables as read
+ * bug 366003 - CCE in ASTNode.resolveAnnotations(ASTNode.java:639)
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -45,7 +47,7 @@ public class AnnotationTest extends AbstractComparableTest {
// Static initializer to specify tests subset using TESTS_* static variables
// All specified tests which do not belong to the class are skipped...
static {
-// TESTS_NAMES = new String[] { "test293" };
+// TESTS_NAMES = new String[] { "testBug365437" };
// TESTS_NUMBERS = new int[] { 297 };
// TESTS_RANGE = new int[] { 294, -1 };
}
@@ -9848,4 +9850,671 @@ public void test297() {
true,
customOptions);
}
+// Bug 366003 - CCE in ASTNode.resolveAnnotations(ASTNode.java:639)
+// many syntax errors fixed, does not trigger CCE
+public void testBug366003() {
+ runNegativeTest(
+ new String[] {
+ "snippet/Bug366003.java",
+ "package snippet;\n" +
+ "public class Bug366003 {\n" +
+ " public void foo(@NonNull Object o1) {\n" +
+ " System.out.println(o1.toString()); // OK: o1 cannot be null\n" +
+ " } \n" +
+ " @NonNull Object bar(@Nullable String s1) {\n" +
+ " foo(null); // cannot pass null argument\n" +
+ " @NonNull String s= null; // cannot assign null value\n" +
+ " @NonNull String t= s1; // cannot assign potentially null value\n" +
+ " return null; // cannot return null value\n" +
+ " }\n" +
+ "}\n" +
+ "org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ ""
+ },
+ "----------\n" +
+ "1. ERROR in snippet\\Bug366003.java (at line 3)\n" +
+ " public void foo(@NonNull Object o1) {\n" +
+ " ^^^^^^^\n" +
+ "NonNull cannot be resolved to a type\n" +
+ "----------\n" +
+ "2. ERROR in snippet\\Bug366003.java (at line 6)\n" +
+ " @NonNull Object bar(@Nullable String s1) {\n" +
+ " ^^^^^^^\n" +
+ "NonNull cannot be resolved to a type\n" +
+ "----------\n" +
+ "3. ERROR in snippet\\Bug366003.java (at line 6)\n" +
+ " @NonNull Object bar(@Nullable String s1) {\n" +
+ " ^^^^^^^^\n" +
+ "Nullable cannot be resolved to a type\n" +
+ "----------\n" +
+ "4. ERROR in snippet\\Bug366003.java (at line 8)\n" +
+ " @NonNull String s= null; // cannot assign null value\n" +
+ " ^^^^^^^\n" +
+ "NonNull cannot be resolved to a type\n" +
+ "----------\n" +
+ "5. ERROR in snippet\\Bug366003.java (at line 9)\n" +
+ " @NonNull String t= s1; // cannot assign potentially null value\n" +
+ " ^^^^^^^\n" +
+ "NonNull cannot be resolved to a type\n" +
+ "----------\n" +
+ "6. ERROR in snippet\\Bug366003.java (at line 12)\n" +
+ " }\n" +
+ " ^\n" +
+ "Syntax error on token \"}\", delete this token\n" +
+ "----------\n" +
+ "7. ERROR in snippet\\Bug366003.java (at line 13)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Syntax error on tokens, delete these tokens\n" +
+ "----------\n" +
+ "8. ERROR in snippet\\Bug366003.java (at line 13)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^\n" +
+ "Syntax error, insert \"enum Identifier\" to complete EnumHeaderName\n" +
+ "----------\n" +
+ "9. ERROR in snippet\\Bug366003.java (at line 13)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^\n" +
+ "Syntax error, insert \"EnumBody\" to complete EnumDeclaration\n" +
+ "----------\n" +
+ "10. ERROR in snippet\\Bug366003.java (at line 13)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^\n" +
+ "Syntax error, insert \"}\" to complete ClassBody\n" +
+ "----------\n" +
+ "11. ERROR in snippet\\Bug366003.java (at line 13)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Return type for the method is missing\n" +
+ "----------\n" +
+ "12. ERROR in snippet\\Bug366003.java (at line 13)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^^^^\n" +
+ "NonNull cannot be resolved to a type\n" +
+ "----------\n" +
+ "13. ERROR in snippet\\Bug366003.java (at line 13)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^^^^^\n" +
+ "Nullable cannot be resolved to a type\n" +
+ "----------\n" +
+ "14. ERROR in snippet\\Bug366003.java (at line 13)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^\n" +
+ "Syntax error, insert \";\" to complete ConstructorDeclaration\n" +
+ "----------\n");
+}
+// Bug 366003 - CCE in ASTNode.resolveAnnotations(ASTNode.java:639)
+// code is garbage, triggers CCE
+public void testBug366003b() {
+ runNegativeTest(
+ new String[] {
+ "snippet/Bug366003.java",
+ "package snippet;\n" +
+ "public class Bug366003 {\n" +
+ " public void foo(@Blah Object o1) { \n" +
+ "System.out.println(o1.toString()); // OK: o1 cannot be null } \n" +
+ "@Blah Object bar(@BlahBlah String s1) { foo(null); // cannot pass\n" +
+ "null argument @Blah String s= null; // cannot assign null value \n" +
+ " @Blah String t= s1; // cannot assign potentially null value \n" +
+ "return null; // cannot return null value }\n" +
+ "}\n" +
+ "\n" +
+ "org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ ""
+ },
+ "----------\n" +
+ "1. ERROR in snippet\\Bug366003.java (at line 3)\n" +
+ " public void foo(@Blah Object o1) { \n" +
+ " ^^^^\n" +
+ "Blah cannot be resolved to a type\n" +
+ "----------\n" +
+ "2. ERROR in snippet\\Bug366003.java (at line 4)\n" +
+ " System.out.println(o1.toString()); // OK: o1 cannot be null } \n" +
+ " ^\n" +
+ "Syntax error, insert \"}\" to complete MethodBody\n" +
+ "----------\n" +
+ "3. ERROR in snippet\\Bug366003.java (at line 5)\n" +
+ " @Blah Object bar(@BlahBlah String s1) { foo(null); // cannot pass\n" +
+ " ^^^^\n" +
+ "Blah cannot be resolved to a type\n" +
+ "----------\n" +
+ "4. ERROR in snippet\\Bug366003.java (at line 5)\n" +
+ " @Blah Object bar(@BlahBlah String s1) { foo(null); // cannot pass\n" +
+ " ^^^^^^^^\n" +
+ "BlahBlah cannot be resolved to a type\n" +
+ "----------\n" +
+ "5. ERROR in snippet\\Bug366003.java (at line 6)\n" +
+ " null argument @Blah String s= null; // cannot assign null value \n" +
+ " ^^^^\n" +
+ "Syntax error on token \"null\", @ expected\n" +
+ "----------\n" +
+ "6. ERROR in snippet\\Bug366003.java (at line 11)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Syntax error on tokens, delete these tokens\n" +
+ "----------\n" +
+ "7. ERROR in snippet\\Bug366003.java (at line 11)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^\n" +
+ "Syntax error, insert \"enum Identifier\" to complete EnumHeaderName\n" +
+ "----------\n" +
+ "8. ERROR in snippet\\Bug366003.java (at line 11)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^\n" +
+ "Syntax error, insert \"EnumBody\" to complete EnumDeclaration\n" +
+ "----------\n" +
+ "9. ERROR in snippet\\Bug366003.java (at line 11)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^\n" +
+ "Syntax error, insert \"}\" to complete ClassBody\n" +
+ "----------\n" +
+ "10. ERROR in snippet\\Bug366003.java (at line 11)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Return type for the method is missing\n" +
+ "----------\n" +
+ "11. ERROR in snippet\\Bug366003.java (at line 11)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^^^^\n" +
+ "NonNull cannot be resolved to a type\n" +
+ "----------\n" +
+ "12. ERROR in snippet\\Bug366003.java (at line 11)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^^^^^^^^\n" +
+ "Nullable cannot be resolved to a type\n" +
+ "----------\n" +
+ "13. ERROR in snippet\\Bug366003.java (at line 11)\n" +
+ " org.eclipse.User.User(@NonNull String name, int uid, @Nullable String email)\n" +
+ " ^\n" +
+ "Syntax error, insert \";\" to complete ConstructorDeclaration\n" +
+ "----------\n");
+}
+// Bug 366003 - CCE in ASTNode.resolveAnnotations(ASTNode.java:639)
+// minimal syntax error to trigger CCE
+public void testBug366003c() {
+ runNegativeTest(
+ new String[] {
+ "snippet/Bug366003.java",
+ "package snippet;\n" +
+ "public class Bug366003 {\n" +
+ " void foo(Object o1) {\n" +
+ " }\n" +
+ "org.User(@Bla String a)"
+ },
+ "----------\n" +
+ "1. ERROR in snippet\\Bug366003.java (at line 5)\n" +
+ " org.User(@Bla String a)\n" +
+ " ^^^\n" +
+ "Syntax error on token \"org\", delete this token\n" +
+ "----------\n" +
+ "2. ERROR in snippet\\Bug366003.java (at line 5)\n" +
+ " org.User(@Bla String a)\n" +
+ " ^^^\n" +
+ "Syntax error, insert \"enum Identifier\" to complete EnumHeaderName\n" +
+ "----------\n" +
+ "3. ERROR in snippet\\Bug366003.java (at line 5)\n" +
+ " org.User(@Bla String a)\n" +
+ " ^^^\n" +
+ "Syntax error, insert \"EnumBody\" to complete EnumDeclaration\n" +
+ "----------\n" +
+ "4. ERROR in snippet\\Bug366003.java (at line 5)\n" +
+ " org.User(@Bla String a)\n" +
+ " ^^^\n" +
+ "Syntax error, insert \"}\" to complete ClassBody\n" +
+ "----------\n" +
+ "5. ERROR in snippet\\Bug366003.java (at line 5)\n" +
+ " org.User(@Bla String a)\n" +
+ " ^^^^^^^^^^^^^^^^^^^\n" +
+ "Return type for the method is missing\n" +
+ "----------\n" +
+ "6. ERROR in snippet\\Bug366003.java (at line 5)\n" +
+ " org.User(@Bla String a)\n" +
+ " ^^^\n" +
+ "Bla cannot be resolved to a type\n" +
+ "----------\n" +
+ "7. ERROR in snippet\\Bug366003.java (at line 5)\n" +
+ " org.User(@Bla String a)\n" +
+ " ^\n" +
+ "Syntax error, insert \";\" to complete ConstructorDeclaration\n" +
+ "----------\n");
+}
+// unfinished attempt to trigger the same CCE via catch formal parameters
+public void testBug366003d() {
+ runNegativeTest(
+ new String[] {
+ "snippet/Bug366003.java",
+ "package snippet; \n" +
+ "public class Bug366003 {\n" +
+ " void foo() {\n" +
+ " try {\n" +
+ " System.out.println(\"\");\n" +
+ " } catch (Exeption eFirst) {\n" +
+ " e } catch (@Blah Exception eSecond) {\n" +
+ " e }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in snippet\\Bug366003.java (at line 7)\n" +
+ " e } catch (@Blah Exception eSecond) {\n" +
+ " ^\n" +
+ "Syntax error, insert \"AssignmentOperator Expression\" to complete Assignment\n" +
+ "----------\n" +
+ "2. ERROR in snippet\\Bug366003.java (at line 7)\n" +
+ " e } catch (@Blah Exception eSecond) {\n" +
+ " ^\n" +
+ "Syntax error, insert \";\" to complete BlockStatements\n" +
+ "----------\n" +
+ "3. ERROR in snippet\\Bug366003.java (at line 8)\n" +
+ " e }\n" +
+ " ^\n" +
+ "Syntax error, insert \"AssignmentOperator Expression\" to complete Expression\n" +
+ "----------\n" +
+ "4. ERROR in snippet\\Bug366003.java (at line 8)\n" +
+ " e }\n" +
+ " ^\n" +
+ "Syntax error, insert \";\" to complete BlockStatements\n" +
+ "----------\n");
+}
+public void testBug366003e() {
+ runNegativeTest(
+ new String[] {
+ "snippet/Bug366003.java",
+ "package snippet;\n" +
+ "public class Bug366003 {\n" +
+ " void foo(Object o1){}\n" +
+ " @Blah org.User(@Bla String str){}\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in snippet\\Bug366003.java (at line 4)\n" +
+ " @Blah org.User(@Bla String str){}\n" +
+ " ^^^^\n" +
+ "Blah cannot be resolved to a type\n" +
+ "----------\n" +
+ "2. ERROR in snippet\\Bug366003.java (at line 4)\n" +
+ " @Blah org.User(@Bla String str){}\n" +
+ " ^^^^\n" +
+ "Syntax error on token \"User\", Identifier expected after this token\n" +
+ "----------\n" +
+ "3. ERROR in snippet\\Bug366003.java (at line 4)\n" +
+ " @Blah org.User(@Bla String str){}\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Return type for the method is missing\n" +
+ "----------\n" +
+ "4. ERROR in snippet\\Bug366003.java (at line 4)\n" +
+ " @Blah org.User(@Bla String str){}\n" +
+ " ^^^\n" +
+ "Bla cannot be resolved to a type\n" +
+ "----------\n");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=365437
+public void testBug365437a() {
+ Map customOptions = getCompilerOptions();
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR);
+ String testFiles [] = new String[] {
+ "p/A.java",
+ "package p;\n" +
+ "import p1.*;\n" +
+ "public class A {\n" +
+ " @p1.PreDestroy\n" +
+ " private void foo1(){}\n" +
+ " @PreDestroy\n" +
+ " private void foo2(){}\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " @PostConstruct\n" +
+ " private void foo1a(){}\n" +
+ " @PostConstruct\n" +
+ " private void foo2a(){}\n" +
+ " @Deprecated" +
+ " private void foo3(){}" +
+ "}\n",
+ "p1/PreDestroy.java",
+ "package p1;\n" +
+ "public @interface PreDestroy{}",
+ "p1/PostConstruct.java",
+ "package p1;\n" +
+ "public @interface PostConstruct{}"
+ };
+ String expectedErrorString =
+ "----------\n" +
+ "1. WARNING in p\\A.java (at line 8)\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " ^^^^^^\n" +
+ "Unnecessary @SuppressWarnings(\"null\")\n" +
+ "----------\n" +
+ "2. ERROR in p\\A.java (at line 13)\n" +
+ " @Deprecated private void foo3(){}}\n" +
+ " ^^^^^^\n" +
+ "The method foo3() from the type A is never used locally\n" +
+ "----------\n";
+ runNegativeTest(
+ true,
+ testFiles,
+ null,
+ customOptions,
+ expectedErrorString,
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=365437
+public void testBug365437b() {
+ Map customOptions = getCompilerOptions();
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR);
+ customOptions.put(CompilerOptions.OPTION_AnnotationBasedNullAnalysis, CompilerOptions.ENABLED);
+ customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "p.NonNull");
+ String testFiles [] = new String[] {
+ "A.java",
+ "import javax.annotation.*;\n" +
+ "public class A {\n" +
+ " @javax.annotation.PreDestroy\n" +
+ " private void foo1(){}\n" +
+ " @PreDestroy\n" +
+ " private void foo2(){}\n" +
+ " @javax.annotation.Resource\n" +
+ " private void foo1a(){}\n" +
+ " @Resource\n" +
+ " @p.NonNull\n" +
+ " private Object foo2a(){ return new Object();}\n" +
+ " @javax.annotation.PostConstruct\n" +
+ " @Deprecated\n" +
+ " private void foo3(){}\n" +
+ " @p.NonNull\n" +
+ " private Object foo3a(){ return new Object();}\n" +
+ "}\n",
+ "p/NonNull.java",
+ "package p;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "import java.lang.annotation.*;\n" +
+ "@Target({TYPE, METHOD,PARAMETER,LOCAL_VARIABLE})\n" +
+ "public @interface NonNull {\n" +
+ "}"
+ };
+ String expectedErrorString =
+ "----------\n" +
+ "1. ERROR in A.java (at line 16)\n" +
+ " private Object foo3a(){ return new Object();}\n" +
+ " ^^^^^^^\n" +
+ "The method foo3a() from the type A is never used locally\n" +
+ "----------\n";
+ runNegativeTest(
+ true,
+ testFiles,
+ null,
+ customOptions,
+ expectedErrorString,
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=365437
+// @SafeVarargs
+public void testBug365437c() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return;
+ Map customOptions = getCompilerOptions();
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR);
+ String testFiles [] = new String[] {
+ "p/A.java",
+ "package p;\n" +
+ "import p1.*;\n" +
+ "public class A {\n" +
+ " @p1.PreDestroy\n" +
+ " private void foo1(){}\n" +
+ " @PreDestroy\n" +
+ " private void foo2(){}\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " @PostConstruct\n" +
+ " private void foo1a(){}\n" +
+ " @PostConstruct\n" +
+ " private void foo2a(){}\n" +
+ " @SafeVarargs" +
+ " private final void foo3(Object... o){}" +
+ "}\n",
+ "p1/PreDestroy.java",
+ "package p1;\n" +
+ "public @interface PreDestroy{}",
+ "p1/PostConstruct.java",
+ "package p1;\n" +
+ "public @interface PostConstruct{}"
+ };
+ String expectedErrorString =
+ "----------\n" +
+ "1. WARNING in p\\A.java (at line 8)\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " ^^^^^^\n" +
+ "Unnecessary @SuppressWarnings(\"null\")\n" +
+ "----------\n" +
+ "2. ERROR in p\\A.java (at line 13)\n" +
+ " @SafeVarargs private final void foo3(Object... o){}}\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "The method foo3(Object...) from the type A is never used locally\n" +
+ "----------\n";
+ runNegativeTest(
+ true,
+ testFiles,
+ null,
+ customOptions,
+ expectedErrorString,
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=365437
+// unused constructor
+public void testBug365437d() {
+ Map customOptions = getCompilerOptions();
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR);
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR);
+ customOptions.put(CompilerOptions.OPTION_AnnotationBasedNullAnalysis, CompilerOptions.ENABLED);
+ customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "p.NonNull");
+ this.runNegativeTest(
+ true,
+ new String[] {
+ "Example.java",
+ "class Example {\n" +
+ " @p.Annot\n" +
+ " private Example() {\n" +
+ " }\n" +
+ " public Example(int i) {\n" +
+ " }\n" +
+ "}\n" +
+ "class E1 {\n" +
+ " @Deprecated\n" +
+ " private E1() {}\n" +
+ " public E1(long l) {}\n" +
+ "}\n" +
+ "class E2 {\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " private E2() {}\n" +
+ " public E2(long l) {}\n" +
+ "}\n" +
+ "class E3 {\n" +
+ " @p.NonNull\n" +
+ " private E3() {}\n" +
+ " public E3(long l) {}\n" +
+ "}\n" +
+ "class E4 {\n" +
+ " @Deprecated\n" +
+ " @p.Annot\n" +
+ " private E4() {}\n" +
+ " public E4(long l) {}\n" +
+ "}\n",
+ "p/NonNull.java",
+ "package p;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "import java.lang.annotation.*;\n" +
+ "@Target({TYPE, METHOD,PARAMETER,CONSTRUCTOR})\n" +
+ "public @interface NonNull {\n" +
+ "}",
+ "p/Annot.java",
+ "package p;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "import java.lang.annotation.*;\n" +
+ "@Target({TYPE, METHOD,PARAMETER,LOCAL_VARIABLE, CONSTRUCTOR})\n" +
+ "public @interface Annot {\n" +
+ "}"
+ },
+ null, customOptions,
+ "----------\n" +
+ "1. ERROR in Example.java (at line 10)\n" +
+ " private E1() {}\n" +
+ " ^^^^\n" +
+ "The constructor E1() is never used locally\n" +
+ "----------\n" +
+ "2. WARNING in Example.java (at line 14)\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " ^^^^^^\n" +
+ "Unnecessary @SuppressWarnings(\"null\")\n" +
+ "----------\n" +
+ "3. ERROR in Example.java (at line 15)\n" +
+ " private E2() {}\n" +
+ " ^^^^\n" +
+ "The constructor E2() is never used locally\n" +
+ "----------\n" +
+ "4. ERROR in Example.java (at line 20)\n" +
+ " private E3() {}\n" +
+ " ^^^^\n" +
+ "The constructor E3() is never used locally\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=365437
+// unused field
+public void testBug365437e() {
+ Map customOptions = getCompilerOptions();
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR);
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR);
+ customOptions.put(CompilerOptions.OPTION_AnnotationBasedNullAnalysis, CompilerOptions.ENABLED);
+ customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "p.NonNull");
+ this.runNegativeTest(
+ true,
+ new String[] {
+ "Example.java",
+ "class Example {\n" +
+ " @p.Annot\n" +
+ " private int Ex;\n" +
+ "}\n" +
+ "class E1 {\n" +
+ " @Deprecated\n" +
+ " private int E1;\n" +
+ "}\n" +
+ "class E2 {\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " private int E2;\n" +
+ "}\n" +
+ "class E3 {\n" +
+ " @p.NonNull\n" +
+ " private int E3;\n" +
+ "}\n" +
+ "class E4 {\n" +
+ " @Deprecated\n" +
+ " @p.Annot\n" +
+ " private int E4;\n" +
+ "}\n",
+ "p/NonNull.java",
+ "package p;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "import java.lang.annotation.*;\n" +
+ "@Target({TYPE, METHOD,PARAMETER,LOCAL_VARIABLE, FIELD})\n" +
+ "public @interface NonNull {\n" +
+ "}",
+ "p/Annot.java",
+ "package p;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "import java.lang.annotation.*;\n" +
+ "@Target({TYPE, METHOD,PARAMETER,LOCAL_VARIABLE, FIELD})\n" +
+ "public @interface Annot {\n" +
+ "}"
+ },
+ null, customOptions,
+ "----------\n" +
+ "1. ERROR in Example.java (at line 7)\n" +
+ " private int E1;\n" +
+ " ^^\n" +
+ "The value of the field E1.E1 is not used\n" +
+ "----------\n" +
+ "2. WARNING in Example.java (at line 10)\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " ^^^^^^\n" +
+ "Unnecessary @SuppressWarnings(\"null\")\n" +
+ "----------\n" +
+ "3. ERROR in Example.java (at line 11)\n" +
+ " private int E2;\n" +
+ " ^^\n" +
+ "The value of the field E2.E2 is not used\n" +
+ "----------\n" +
+ "4. ERROR in Example.java (at line 15)\n" +
+ " private int E3;\n" +
+ " ^^\n" +
+ "The value of the field E3.E3 is not used\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=365437
+// unused type
+public void testBug365437f() {
+ Map customOptions = getCompilerOptions();
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR);
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR);
+ customOptions.put(CompilerOptions.OPTION_AnnotationBasedNullAnalysis, CompilerOptions.ENABLED);
+ customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "p.NonNull");
+ this.runNegativeTest(
+ true,
+ new String[] {
+ "Example.java",
+ "class Example {\n" +
+ " @p.Annot\n" +
+ " private class Ex{}\n" +
+ "}\n" +
+ "class E1 {\n" +
+ " @Deprecated\n" +
+ " private class E11{}\n" +
+ "}\n" +
+ "class E2 {\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " private class E22{}\n" +
+ "}\n" +
+ "class E3 {\n" +
+ " @p.NonNull\n" +
+ " private class E33{}\n" +
+ "}\n" +
+ "class E4 {\n" +
+ " @Deprecated\n" +
+ " @p.Annot\n" +
+ " private class E44{}\n" +
+ "}\n",
+ "p/NonNull.java",
+ "package p;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "import java.lang.annotation.*;\n" +
+ "@Target({TYPE, METHOD,PARAMETER,LOCAL_VARIABLE})\n" +
+ "public @interface NonNull {\n" +
+ "}",
+ "p/Annot.java",
+ "package p;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "import java.lang.annotation.*;\n" +
+ "@Target({TYPE, METHOD,PARAMETER,LOCAL_VARIABLE, CONSTRUCTOR})\n" +
+ "public @interface Annot {\n" +
+ "}"
+ },
+ null, customOptions,
+ "----------\n" +
+ "1. ERROR in Example.java (at line 7)\n" +
+ " private class E11{}\n" +
+ " ^^^\n" +
+ "The type E1.E11 is never used locally\n" +
+ "----------\n" +
+ "2. WARNING in Example.java (at line 10)\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " ^^^^^^\n" +
+ "Unnecessary @SuppressWarnings(\"null\")\n" +
+ "----------\n" +
+ "3. ERROR in Example.java (at line 11)\n" +
+ " private class E22{}\n" +
+ " ^^^\n" +
+ "The type E2.E22 is never used locally\n" +
+ "----------\n" +
+ "4. ERROR in Example.java (at line 15)\n" +
+ " private class E33{}\n" +
+ " ^^^\n" +
+ "The type E3.E33 is never used locally\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
index b89df77bc..d63b9d0f2 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -16,6 +16,7 @@
* bug 349326 - [1.7] new warning for missing try-with-resources
* bug 359721 - [options] add command line option for new warning token "resource"
* bug 186342 - [compiler][null] Using annotations for null checking
+ * bug 365208 - [compiler][batch] command line options for annotation based null analysis
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -52,8 +53,33 @@ public class BatchCompilerTest extends AbstractRegressionTest {
static final String JRE_HOME_DIR = Util.getJREDirectory();
private static final Main MAIN = new Main(null/*outWriter*/, null/*errWriter*/, false/*systemExit*/, null/*options*/, null/*progress*/);
+ private static final String NONNULL_BY_DEFAULT_ANNOTATION_CONTENT = "package org.eclipse.jdt.annotation;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "import java.lang.annotation.*;\n" +
+ "@Documented\n" +
+ "@Retention(RetentionPolicy.CLASS)\n" +
+ "@Target({ PACKAGE, TYPE, METHOD, CONSTRUCTOR })\n" +
+ "public @interface NonNullByDefault{\n" +
+ "}";
+ private static final String NULLABLE_ANNOTATION_CONTENT = "package org.eclipse.jdt.annotation;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "import java.lang.annotation.*;\n" +
+ "@Documented\n" +
+ "@Retention(RetentionPolicy.CLASS)\n" +
+ "@Target({ METHOD, PARAMETER })\n" +
+ "public @interface Nullable{\n" +
+ "}\n";
+ private static final String NONNULL_ANNOTATION_CONTENT = "package org.eclipse.jdt.annotation;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "import java.lang.annotation.*;\n" +
+ "@Documented\n" +
+ "@Retention(RetentionPolicy.CLASS)\n" +
+ "@Target({ METHOD, PARAMETER })\n" +
+ "public @interface NonNull{\n" +
+ "}\n";
+
static {
-// TESTS_NAMES = new String[] { "test295_warn_options" };
+// TESTS_NAMES = new String[] { "test31" };
// TESTS_NUMBERS = new int[] { 306 };
// TESTS_RANGE = new int[] { 298, -1 };
}
@@ -1620,6 +1646,8 @@ public void test012(){
" -enableJavadoc consider references in javadoc\n" +
" -Xemacs used to enable emacs-style output in the console.\n" +
" It does not affect the xml log output\n" +
+ " -nonNullByDefault for annotation based null analysis assume nonnull\n" +
+ " as the global default\n" +
" \n" +
" -? -help print this help message\n" +
" -v -version print compiler version\n" +
@@ -1740,7 +1768,11 @@ public void test012b(){
" nls string literal lacking non-nls tag //$NON-NLS-<n>$\n" +
" noEffectAssign + assignment without effect\n" +
" null potential missing or redundant null check\n" +
- " nullDereference + missing null check\n" +
+ " nullAnnot(<annot. names separated by |>) + annotation based null analysis,\n" +
+ " nullable|nonnull|nonnullbydefault annotation types\n" +
+ " optionally specified using fully qualified names\n" +
+ " nullDereference + missing null check\n" +
+ " nullFields + null analysis for fields\n" +
" over-ann missing @Override annotation (superclass)\n" +
" paramAssign assignment to a parameter\n" +
" pkgDefaultMethod + attempt to override package-default method\n" +
@@ -1859,7 +1891,7 @@ public void test012b(){
" <option key=\"org.eclipse.jdt.core.compiler.debug.sourceFile\" value=\"generate\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.doc.comment.support\" value=\"disabled\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.generateClassFiles\" value=\"enabled\"/>\n" +
- " <option key=\"org.eclipse.jdt.core.compiler.maxProblemPerUnit\" value=\"100\"/>\n" +
+ " <option key=\"org.eclipse.jdt.core.compiler.maxProblemPerUnit\" value=\"100\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.annotationSuperInterface\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.assertIdentifier\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.autoboxing\" value=\"ignore\"/>\n" +
@@ -1880,6 +1912,7 @@ public void test012b(){
" <option key=\"org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.forbiddenReference\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock\" value=\"warning\"/>\n" +
+ " <option key=\"org.eclipse.jdt.core.compiler.problem.includeFieldsInNullAnalysis\" value=\"disabled\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts\" value=\"disabled\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch\" value=\"ignore\"/>\n" +
@@ -12372,4 +12405,395 @@ public void test0309_warn_options() {
"1 problem (1 warning)",
true);
}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=366829
+// -warn option - regression test to check option syncOverride
+// Warning when when a class overrides a synchronized method without synchronizing it
+public void test310_warn_options() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "class X { synchronized void foo() {} }\n" +
+ "class Y extends X { @Override void foo() { } }"
+ },
+ "\"" + OUTPUT_DIR + File.separator + "X.java\""
+ + " -sourcepath \"" + OUTPUT_DIR + "\""
+ + " -warn:syncOverride -1.5 -proc:none -d \"" + OUTPUT_DIR + "\"",
+ "",
+ "----------\n" +
+ "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 2)\n" +
+ " class Y extends X { @Override void foo() { } }\n" +
+ " ^^^^^\n" +
+ "The method Y.foo() is overriding a synchronized method without being synchronized\n" +
+ "----------\n" +
+ "1 problem (1 warning)",
+ true);
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=366829
+// -warn option - regression test to check option syncOverride
+// Warning when when a class overrides a synchronized method without synchronizing it
+public void test310b_warn_options() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " void bar() { new X() { @Override void foo() {} }; }\n"+
+ " synchronized void foo() { }\n"+
+ "}"
+ },
+ "\"" + OUTPUT_DIR + File.separator + "X.java\""
+ + " -sourcepath \"" + OUTPUT_DIR + "\""
+ + " -warn:syncOverride -1.5 -proc:none -d \"" + OUTPUT_DIR + "\"",
+ "",
+ "----------\n" +
+ "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 2)\n" +
+ " void bar() { new X() { @Override void foo() {} }; }\n"+
+ " ^^^^^\n" +
+ "The method new X(){}.foo() is overriding a synchronized method without being synchronized\n" +
+ "----------\n" +
+ "1 problem (1 warning)",
+ true);
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
+// -warn option - regression tests to check option nulLFields
+// Null warnings should be flagged on fields
+public void test311_warn_options() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " Object o;\n" +
+ " void foo() {\n" +
+ " if (o == null && o.toString() == \"\"){}\n" +
+ " else {}\n" +
+ " o.toString();\n" + // toString() call above defuses null info, so no warning here
+ " }\n" +
+ "}\n",
+ },
+ "\"" + OUTPUT_DIR + File.separator + "X.java\""
+ + " -sourcepath \"" + OUTPUT_DIR + "\""
+ + " -warn:null,nullFields -proc:none -d \"" + OUTPUT_DIR + "\"",
+ "",
+ "----------\n" +
+ "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 4)\n" +
+ " if (o == null && o.toString() == \"\"){}\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n" +
+ "1 problem (1 warning)",
+ true);
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
+// -warn option - regression tests to check option nullAnnot (with args)
+// Null warnings because of annotations - custom annotation types used - challenging various kinds of diagnostics
+public void test312_warn_options() {
+ this.runConformTest(
+ new String[] {
+ "p/X.java",
+ "package p;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "import java.lang.annotation.*;\n" +
+ "@SuppressWarnings(\"unused\")\n" +
+ "public class X {\n" +
+ " public void test() { Object o = null; o.toString();}\n" +
+ " @NonNull Object foo(@Nullable Object o, @NonNull Object o2) {\n" +
+ " if (o.toString() == \"\"){ return null;}\n" +
+ " if (o2 == null) {}\n" +
+ " goo(null).toString();\n" +
+ " Object local = null;\n" +
+ " o.toString();\n" +
+ " return null;\n" +
+ " }\n" +
+ " @Nullable Object goo(@NonNull Object o2) {\n" +
+ " return new Object();\n" +
+ " }\n" +
+ " @NonNullByDefault Object hoo(Object o2) {\n" +
+ " if (o2 == null){}\n" +
+ " if (o2 == null){\n" +
+ " return null;\n" +
+ " }\n" +
+ " return new Object();\n" +
+ " }\n" +
+ "}\n" +
+ "@Documented\n" +
+ "@Retention(RetentionPolicy.CLASS)\n" +
+ "@Target({ METHOD, PARAMETER })\n" +
+ "@interface NonNull{\n" +
+ "}\n" +
+ "@Documented\n" +
+ "@Retention(RetentionPolicy.CLASS)\n" +
+ "@Target({ METHOD, PARAMETER })\n" +
+ "@interface Nullable{\n" +
+ "}\n" +
+ "@Documented\n" +
+ "@Retention(RetentionPolicy.CLASS)\n" +
+ "@Target({ PACKAGE, TYPE, METHOD, CONSTRUCTOR })\n" +
+ "@interface NonNullByDefault{\n" +
+ "}"
+ },
+ "\"" + OUTPUT_DIR + File.separator + "p" + File.separator + "X.java\""
+// + " -sourcepath \"" + OUTPUT_DIR + "\""
+ + " -1.5"
+ + " -warn:+nullAnnot(p.Nullable|p.NonNull|p.NonNullByDefault) -warn:+null -proc:none -d \"" + OUTPUT_DIR + "\"",
+ "",
+ "----------\n" +
+ "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 6)\n" +
+ " public void test() { Object o = null; o.toString();}\n" +
+ " ^\n" +
+ "Null pointer access: The variable o can only be null at this location\n" +
+ "----------\n" +
+ "2. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 8)\n" +
+ " if (o.toString() == \"\"){ return null;}\n" +
+ " ^\n" +
+ "Potential null pointer access: The variable o may be null at this location\n" +
+ "----------\n" +
+ "3. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 8)\n" +
+ " if (o.toString() == \"\"){ return null;}\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n" +
+ "4. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " if (o2 == null) {}\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The variable o2 cannot be null at this location\n" +
+ "----------\n" +
+ "5. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 10)\n" +
+ " goo(null).toString();\n" +
+ " ^^^^^^^^^\n" +
+ "Potential null pointer access: The method goo(Object) may return null\n" +
+ "----------\n" +
+ "6. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 10)\n" +
+ " goo(null).toString();\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n" +
+ "7. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 13)\n" +
+ " return null;\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n" +
+ "8. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 19)\n" +
+ " if (o2 == null){}\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The variable o2 cannot be null at this location\n" +
+ "----------\n" +
+ "9. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 20)\n" +
+ " if (o2 == null){\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The variable o2 cannot be null at this location\n" +
+ "----------\n" +
+ "9 problems (9 warnings)",
+ true);
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
+// -warn option - regression tests to check option nullAnnot (no args)
+// Null warnings because of annotations, null spec violations
+public void test313_warn_options() {
+ this.runConformTest(
+ new String[] {
+ "p/X.java",
+ "package p;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull Object foo(@Nullable Object o, @NonNull Object o2) {\n" +
+ " return this;\n" +
+ " }\n" +
+ "}\n" +
+ "class Y extends X {\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ "}\n",
+ "org/eclipse/jdt/annotation/NonNull.java",
+ NONNULL_ANNOTATION_CONTENT,
+ "org/eclipse/jdt/annotation/Nullable.java",
+ NULLABLE_ANNOTATION_CONTENT,
+ "org/eclipse/jdt/annotation/NonNullByDefault.java",
+ NONNULL_BY_DEFAULT_ANNOTATION_CONTENT
+ },
+ "\"" + OUTPUT_DIR + File.separator + "p" + File.separator + "X.java\""
+ + " -sourcepath \"" + OUTPUT_DIR + "\""
+ + " -1.5"
+ + " -warn:+nullAnnot -warn:-null -proc:none -d \"" + OUTPUT_DIR + "\"",
+ "",
+ "----------\n" +
+ "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The return type is incompatible with the @NonNull return from X.foo(Object, Object)\n" +
+ "----------\n" +
+ "2. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ " ^^^^^^\n" +
+ "Missing nullable annotation: inherited method from X declares this parameter as @Nullable\n" +
+ "----------\n" +
+ "3. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ " ^^^^^^\n" +
+ "Missing non-null annotation: inherited method from X declares this parameter as @NonNull\n" +
+ "----------\n" +
+ "3 problems (3 warnings)",
+ true);
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
+// -err option - regression tests to check option nullAnnot
+// Null warnings because of annotations, null spec violations configured as errors
+public void test314_warn_options() {
+ this.runNegativeTest(
+ new String[] {
+ "p/X.java",
+ "package p;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull Object foo(@Nullable Object o, @NonNull Object o2) {\n" +
+ " return this;\n" +
+ " }\n" +
+ "}\n" +
+ "class Y extends X {\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ "}\n",
+ "org/eclipse/jdt/annotation/NonNull.java",
+ NONNULL_ANNOTATION_CONTENT,
+ "org/eclipse/jdt/annotation/Nullable.java",
+ NULLABLE_ANNOTATION_CONTENT,
+ "org/eclipse/jdt/annotation/NonNullByDefault.java",
+ NONNULL_BY_DEFAULT_ANNOTATION_CONTENT
+ },
+ "\"" + OUTPUT_DIR + File.separator + "p" + File.separator + "X.java\""
+ + " -sourcepath \"" + OUTPUT_DIR + "\""
+ + " -1.5"
+ + " -err:+nullAnnot -warn:-null -proc:none -d \"" + OUTPUT_DIR + "\"",
+ "",
+ "----------\n" +
+ "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The return type is incompatible with the @NonNull return from X.foo(Object, Object)\n" +
+ "----------\n" +
+ "2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ " ^^^^^^\n" +
+ "Missing nullable annotation: inherited method from X declares this parameter as @Nullable\n" +
+ "----------\n" +
+ "3. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ " ^^^^^^\n" +
+ "Missing non-null annotation: inherited method from X declares this parameter as @NonNull\n" +
+ "----------\n" +
+ "3 problems (3 errors)",
+ true);
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
+// -warn option - regression tests to check option nullAnnot
+// Null warnings because of annotations, global nonNullByDefault
+public void test315_warn_options() {
+ this.runConformTest(
+ new String[] {
+ "p/X.java",
+ "package p;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "@SuppressWarnings(\"unused\")\n" +
+ "public class X {\n" +
+ " Object foo(@Nullable Object o, Object o2) {\n" +
+ " if (o.toString() == \"\"){ return null;}\n" +
+ " if (o2 == null) {}\n" +
+ " goo(null).toString();\n" +
+ " return null;\n" +
+ " }\n" +
+ " @Nullable Object goo(Object o2) {\n" +
+ " return new Object();\n" +
+ " }\n" +
+ " @NonNullByDefault Object hoo(Object o2) {\n" + // redundant
+ " if (o2 == null)\n" +
+ " return null;\n" +
+ " return this;\n" +
+ " }\n" +
+ "}\n",
+ "org/eclipse/jdt/annotation/NonNull.java",
+ NONNULL_ANNOTATION_CONTENT,
+ "org/eclipse/jdt/annotation/Nullable.java",
+ NULLABLE_ANNOTATION_CONTENT,
+ "org/eclipse/jdt/annotation/NonNullByDefault.java",
+ NONNULL_BY_DEFAULT_ANNOTATION_CONTENT
+ },
+ "\"" + OUTPUT_DIR + File.separator + "p" + File.separator + "X.java\""
+ + " -sourcepath \"" + OUTPUT_DIR + "\""
+ + " -1.5"
+ + " -warn:+nullAnnot -warn:+null -nonNullByDefault -proc:none -d \"" + OUTPUT_DIR + "\"",
+ "",
+ "----------\n" +
+ "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 6)\n" +
+ " if (o.toString() == \"\"){ return null;}\n" +
+ " ^\n" +
+ "Potential null pointer access: The variable o may be null at this location\n" +
+ "----------\n" +
+ "2. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 6)\n" +
+ " if (o.toString() == \"\"){ return null;}\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n" +
+ "3. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 7)\n" +
+ " if (o2 == null) {}\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The variable o2 cannot be null at this location\n" +
+ "----------\n" +
+ "4. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 8)\n" +
+ " goo(null).toString();\n" +
+ " ^^^^^^^^^\n" +
+ "Potential null pointer access: The method goo(Object) may return null\n" +
+ "----------\n" +
+ "5. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 8)\n" +
+ " goo(null).toString();\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n" +
+ "6. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " return null;\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n" +
+ "7. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 14)\n" +
+ " @NonNullByDefault Object hoo(Object o2) {\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with the global default\n" +
+ "----------\n" +
+ "8. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 15)\n" +
+ " if (o2 == null)\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The variable o2 cannot be null at this location\n" +
+ "----------\n" +
+ "8 problems (8 warnings)",
+ true);
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
+// -warn option - regression tests to check option nullAnnot
+// option syntax error
+public void test316_warn_options() {
+ this.runNegativeTest(
+ new String[] {
+ "p/X.java",
+ "package p;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "@SuppressWarnings(\"unused\")\n" +
+ "public class X {}\n",
+ "org/eclipse/jdt/annotation/NonNull.java",
+ NONNULL_ANNOTATION_CONTENT,
+ "org/eclipse/jdt/annotation/Nullable.java",
+ NULLABLE_ANNOTATION_CONTENT,
+ "org/eclipse/jdt/annotation/NonNullByDefault.java",
+ NONNULL_BY_DEFAULT_ANNOTATION_CONTENT
+ },
+ "\"" + OUTPUT_DIR + File.separator + "p" + File.separator + "X.java\""
+ + " -sourcepath \"" + OUTPUT_DIR + "\""
+ + " -1.5"
+ + " -warn:+nullAnnot(foo|bar) -warn:+null -nonNullByDefault -proc:none -d \"" + OUTPUT_DIR + "\"",
+ "",
+ "Token nullAnnot(foo|bar) is not in the expected format \"nullAnnot(<non null annotation name> | <nullable annotation name> | <non-null by default annotation name>)\"\n",
+ true);
+}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
index 60f157d8c..bacc50be6 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2011 IBM Corporation and others.
+ * Copyright (c) 2006, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,6 +13,7 @@
* bug 236385: [compiler] Warn for potential programming problem if an object is created but not used
* bug 349326 - [1.7] new warning for missing try-with-resources
* bug 186342 - [compiler][null] Using annotations for null checking
+ * bug 365662 - [compiler][null] warn on contradictory and redundant null annotations
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -401,6 +402,7 @@ public void _test011_problem_categories() {
expectedProblemAttributes.put("CodeCannotBeReached", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("CodeSnippetMissingClass", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("CodeSnippetMissingMethod", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
+ expectedProblemAttributes.put("ContradictoryNullAnnotations", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("ComparingIdentical", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("ConflictingImport", new ProblemAttributes(CategorizedProblem.CAT_IMPORT));
expectedProblemAttributes.put("ConstructorVarargsArgumentNeedCast", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -728,6 +730,7 @@ public void _test011_problem_categories() {
expectedProblemAttributes.put("NonGenericConstructor", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("NonGenericMethod", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("NonGenericType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("NonNullFieldComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
@@ -740,6 +743,9 @@ public void _test011_problem_categories() {
expectedProblemAttributes.put("NotVisibleField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
expectedProblemAttributes.put("NotVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
expectedProblemAttributes.put("NotVisibleType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("NullFieldComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+ expectedProblemAttributes.put("NullFieldInstanceofYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+ expectedProblemAttributes.put("NullFieldReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -783,6 +789,7 @@ public void _test011_problem_categories() {
expectedProblemAttributes.put("PotentialHeapPollutionFromVararg", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+ expectedProblemAttributes.put("PotentialNullFieldReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("PotentialNullMessageSendReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
@@ -792,11 +799,18 @@ public void _test011_problem_categories() {
expectedProblemAttributes.put("RedefinedArgument", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("RedefinedLocal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
+ expectedProblemAttributes.put("RedundantFieldNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RedundantNullAnnotation", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
+ expectedProblemAttributes.put("RedundantNullCheckOnNonNullField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RedundantNullCheckOnNonNullMessageSend", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+ expectedProblemAttributes.put("RedundantNullCheckOnNullField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+ expectedProblemAttributes.put("RedundantNullDefaultAnnotation", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
+ expectedProblemAttributes.put("RedundantNullDefaultAnnotationPackage", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
+ expectedProblemAttributes.put("RedundantNullDefaultAnnotationType", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
+ expectedProblemAttributes.put("RedundantNullDefaultAnnotationMethod", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
expectedProblemAttributes.put("ReferenceToForwardField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
expectedProblemAttributes.put("RequiredNonNullButProvidedNull", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -1174,6 +1188,7 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("CodeSnippetMissingMethod", SKIP);
expectedProblemAttributes.put("ComparingIdentical", new ProblemAttributes(JavaCore.COMPILER_PB_COMPARING_IDENTICAL));
expectedProblemAttributes.put("ConflictingImport", SKIP);
+ expectedProblemAttributes.put("ContradictoryNullAnnotations", SKIP);
expectedProblemAttributes.put("ConstructorVarargsArgumentNeedCast", new ProblemAttributes(JavaCore.COMPILER_PB_VARARGS_ARGUMENT_NEED_CAST));
expectedProblemAttributes.put("CorruptedSignature", SKIP);
expectedProblemAttributes.put("DeadCode", new ProblemAttributes(JavaCore.COMPILER_PB_DEAD_CODE));
@@ -1499,6 +1514,7 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("NonGenericConstructor", SKIP);
expectedProblemAttributes.put("NonGenericMethod", SKIP);
expectedProblemAttributes.put("NonGenericType", SKIP);
+ expectedProblemAttributes.put("NonNullFieldComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
@@ -1511,6 +1527,9 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("NotVisibleField", SKIP);
expectedProblemAttributes.put("NotVisibleMethod", SKIP);
expectedProblemAttributes.put("NotVisibleType", SKIP);
+ expectedProblemAttributes.put("NullFieldComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
+ expectedProblemAttributes.put("NullFieldInstanceofYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
+ expectedProblemAttributes.put("NullFieldReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
@@ -1554,6 +1573,7 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("PotentialHeapPollutionFromVararg", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
+ expectedProblemAttributes.put("PotentialNullFieldReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
expectedProblemAttributes.put("PotentialNullMessageSendReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
@@ -1563,11 +1583,18 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("RedefinedArgument", SKIP);
expectedProblemAttributes.put("RedefinedLocal", SKIP);
expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_TYPE_ARGUMENTS));
+ expectedProblemAttributes.put("RedundantFieldNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("RedundantNullAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION));
+ expectedProblemAttributes.put("RedundantNullCheckOnNonNullField", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("RedundantNullCheckOnNonNullMessageSend", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
+ expectedProblemAttributes.put("RedundantNullCheckOnNullField", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
+ expectedProblemAttributes.put("RedundantNullDefaultAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION));
+ expectedProblemAttributes.put("RedundantNullDefaultAnnotationPackage", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION));
+ expectedProblemAttributes.put("RedundantNullDefaultAnnotationType", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION));
+ expectedProblemAttributes.put("RedundantNullDefaultAnnotationMethod", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION));
expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_SUPERINTERFACE));
expectedProblemAttributes.put("ReferenceToForwardField", SKIP);
expectedProblemAttributes.put("ReferenceToForwardTypeVariable", SKIP);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java
index aa4d4729e..5e591ccf1 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java
@@ -1,12 +1,13 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * IBM Corporation - initial API and implementation
+ * IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for Bug 365519 - editorial cleanup after bug 186342 and bug 365387
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -15,6 +16,7 @@ import java.util.Map;
import junit.framework.Test;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
@@ -6517,6 +6519,66 @@ public void test180() {
"",
null);
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=289892
+// in interaction with null annotations
+// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=365519#c4 item (6)
+public void test180a() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+ this.runConformTest(
+ new String[] {
+ "p/package-info.java",
+ "@p.Annot(state=p.MyEnum.BROKEN)\n" +
+ "package p;",
+ "p/Annot.java",
+ "package p;\n" +
+ "@Annot(state=MyEnum.KO)\n" +
+ "public @interface Annot {\n" +
+ " MyEnum state() default MyEnum.KO;\n" +
+ "}",
+ "p/MyEnum.java",
+ "package p;\n" +
+ "@Annot(state=MyEnum.KO)\n" +
+ "public enum MyEnum {\n" +
+ " WORKS, OK, KO, BROKEN, ;\n" +
+ "}",
+ "test180/package-info.java",
+ "@p.Annot(state=p.MyEnum.OK)\n" +
+ "package test180;",
+ "test180/Test.java",
+ "package test180;\n" +
+ "import p.MyEnum;\n" +
+ "import p.Annot;\n" +
+ "@Annot(state=MyEnum.OK)\n" +
+ "public class Test {}",
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null
+ );
+ options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_Process_Annotations, CompilerOptions.ENABLED);
+ this.runConformTest(
+ false,
+ new String[] {
+ "X.java",
+ "import test180.Test;\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " System.out.println(Test.class);\n" +
+ " }\n" +
+ "}"
+ },
+ null,
+ options,
+ "",
+ "class test180.Test",
+ "",
+ null);
+}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=300133
public void test181() {
this.runConformTest(
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java
index 4e758287b..669345c58 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -31,7 +31,7 @@ import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
public class FlowAnalysisTest extends AbstractRegressionTest {
static {
-// TESTS_NAMES = new String[] { "testLocalClassInInitializer1" };
+// TESTS_NAMES = new String[] { "testInnerClassesWithFields1" };
// TESTS_NUMBERS = new int[] { 69 };
}
public FlowAnalysisTest(String name) {
@@ -2496,6 +2496,119 @@ public void testLocalClassInInitializer2() {
"continue cannot be used outside of a loop\n" +
"----------\n");
}
+// final field in anonymous nested class
+// witness a regression during working on Bug 247564 - [compiler][null] Detecting null field reference
+public void testFinalFieldInNested1() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " void print4() {\n" +
+ " for (int i=0; i<4; i++)\n" +
+ " new Runnable() {\n" +
+ " final String s1local;\n" +
+ " public void run() {\n" +
+ " s1local.toString();\n" +
+ " }\n" +
+ " }.run();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " new Runnable() {\n" +
+ " ^^^^^^^^^^\n" +
+ "The blank final field s1local may not have been initialized\n" +
+ "----------\n");
+}
+// witness a regression during working on Bug 247564 - [compiler][null] Detecting null field reference
+// local variable in inner class triggered IAE in StackMapFrame.addStackItem
+public void testInnerClassesWithFields1() {
+ if (this.complianceLevel >= ClassFileConstants.JDK1_6) { // we're specifically interested in StackMap generation
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " int f1, f2, f3;\n" +
+ " class I1 {\n" +
+ " int f4;\n" +
+ " String m(boolean b) {\n" +
+ " String l1 = \"Hello\";\n" +
+ " if (b) {\n" +
+ " l1 += \" world!\";\n" +
+ " } else {\n" +
+ " l1 += \" test.\";\n" +
+ " }\n" +
+ " return l1;\n" +
+ " }\n" +
+ " }\n" +
+ " class I2 {\n" +
+ " int f5, f6, f7;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "");
+ }
+}
+// witness a regression during working on Bug 247564 - [compiler][null] Detecting null field reference
+// local variable in local class triggered IAE in StackMapFrame.addStackItem
+public void testInnerClassesWithFields1a() {
+ if (this.complianceLevel >= ClassFileConstants.JDK1_6) { // we're specifically interested in StackMap generation
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " int f1, f2, f3;\n" +
+ " void foo() {\n" +
+ " class I1 {\n" +
+ " int f4;\n" +
+ " String m(boolean b) {\n" +
+ " String l1 = \"Hello\";\n" +
+ " if (b) {\n" +
+ " l1 += \" world!\";\n" +
+ " } else {\n" +
+ " l1 += \" test.\";\n" +
+ " }\n" +
+ " return l1;\n" +
+ " }\n" +
+ " }\n" +
+ " }\n" +
+ " class I2 {\n" +
+ " int f5, f6, f7;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "");
+ }
+}
+// witness a regression during working on Bug 247564 - [compiler][null] Detecting null field reference
+// final fields in parameterized nested were reported as uninitialized
+public void testInnerClassesWithFields2() {
+ if (this.complianceLevel >= ClassFileConstants.JDK1_5) {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static final String f1 = \"f1\";\n" +
+ " static final String f2 = \"f2\";\n" +
+ " String f3;\n" +
+ " X() {\n" +
+ " f3 = \"f3\";\n" +
+ " }\n" +
+ " protected abstract class I<T> {\n" +
+ " final String f5, f6;\n" +
+ " T f7;\n" +
+ " I(T a) {\n" +
+ " f5 = \"f5\";\n" +
+ " f6 = \"f6\";\n" +
+ " f7 = a;\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "");
+ }
+}
public static Class testClass() {
return FlowAnalysisTest.class;
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
index 3c54f5f06..f2968e473 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -2465,4 +2465,88 @@ public void test348493a() {
"\'<>\' operator is not allowed for source level below 1.7\n" +
"----------\n");
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=366131
+public void test366131() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n" +
+ "class Range<T extends Comparable<? super T>> {\n" +
+ " public boolean containsNC(T value) {\n" +
+ " return false;\n" +
+ " }\n" +
+ "}\n" +
+ "class NumberRange<T extends Number & Comparable<? super T>> extends Range<T> {\n" +
+ " public boolean contains(Comparable<?> value) {\n" +
+ " return castTo((Class) null).containsNC((Comparable) null);\n" +
+ " }\n" +
+ " public <N extends Number & Comparable<? super N>> NumberRange<N>\n" +
+ "castTo(Class<N> type) {\n" +
+ " return null;\n" +
+ " }\n" +
+ "}\n",
+ },
+ "SUCCESS");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=366131
+public void test366131b() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public static void main(String [] args) {\n" +
+ " Zork z;\n" +
+ " }\n" +
+ "}\n" +
+ "class Range<T extends Comparable<? super T>> {\n" +
+ " public boolean containsNC(T value) {\n" +
+ " return false;\n" +
+ " }\n" +
+ "}\n" +
+ "class NumberRange<T extends Number & Comparable<? super T>> extends Range<T> {\n" +
+ " public boolean contains(Comparable<?> value) {\n" +
+ " return castTo((Class) null).containsNC((Comparable) null);\n" +
+ " }\n" +
+ " public <N extends Number & Comparable<? super N>> NumberRange<N>\n" +
+ "castTo(Class<N> type) {\n" +
+ " return null;\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " Zork z;\n" +
+ " ^^^^\n" +
+ "Zork cannot be resolved to a type\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 13)\n" +
+ " return castTo((Class) null).containsNC((Comparable) null);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^\n" +
+ "Type safety: Unchecked invocation castTo(Class) of the generic method castTo(Class<N>) of type NumberRange<T>\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 13)\n" +
+ " return castTo((Class) null).containsNC((Comparable) null);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Type safety: The method containsNC(Comparable) belongs to the raw type Range. References to generic type Range<T> should be parameterized\n" +
+ "----------\n" +
+ "4. WARNING in X.java (at line 13)\n" +
+ " return castTo((Class) null).containsNC((Comparable) null);\n" +
+ " ^^^^^^^^^^^^\n" +
+ "Type safety: The expression of type Class needs unchecked conversion to conform to Class<Number&Comparable<? super Number&Comparable<? super N>>>\n" +
+ "----------\n" +
+ "5. WARNING in X.java (at line 13)\n" +
+ " return castTo((Class) null).containsNC((Comparable) null);\n" +
+ " ^^^^^\n" +
+ "Class is a raw type. References to generic type Class<T> should be parameterized\n" +
+ "----------\n" +
+ "6. WARNING in X.java (at line 13)\n" +
+ " return castTo((Class) null).containsNC((Comparable) null);\n" +
+ " ^^^^^^^^^^\n" +
+ "Comparable is a raw type. References to generic type Comparable<T> should be parameterized\n" +
+ "----------\n");
+}
} \ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InitializationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InitializationTests.java
index 23d941007..0309b5f19 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InitializationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InitializationTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -464,6 +464,44 @@ public void testBug324178d() {
"The local variable b2 may not have been initialized\n" +
"----------\n");
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=247564
+// Change in the way field id's are calculated should not affect initializations
+public void testBug247564j() {
+ this.runNegativeTest(
+ new String[] {
+ "Z.java",
+ "public class Z {\n" +
+ " final int field1 = 0;\n" +
+ " {\n" +
+ " class ZInner {\n" +
+ " final int fieldz1;\n" +
+ " final int fieldz2 = 0;\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. WARNING in Z.java (at line 4)\n" +
+ " class ZInner {\n" +
+ " ^^^^^^\n" +
+ "The type ZInner is never used locally\n" +
+ "----------\n" +
+ "2. ERROR in Z.java (at line 4)\n" +
+ " class ZInner {\n" +
+ " ^^^^^^\n" +
+ "The blank final field fieldz1 may not have been initialized\n" +
+ "----------\n" +
+ "3. WARNING in Z.java (at line 5)\n" +
+ " final int fieldz1;\n" +
+ " ^^^^^^^\n" +
+ "The value of the field ZInner.fieldz1 is not used\n" +
+ "----------\n" +
+ "4. WARNING in Z.java (at line 6)\n" +
+ " final int fieldz2 = 0;\n" +
+ " ^^^^^^^\n" +
+ "The value of the field ZInner.fieldz2 is not used\n" +
+ "----------\n"
+ );
+}
public static Class testClass() {
return InitializationTests.class;
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java
index 35de47568..53f8c5b88 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -2330,18 +2330,36 @@ public class MethodVerifyTest extends AbstractComparableTest {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=83162
public void test036d() { // 2 interface cases
// in these cases, bridge methods are needed once abstract/concrete methods are defiined (either in the abstract class or a concrete subclass)
- this.runConformTest(
- new String[] {
- "Y.java",
- "abstract class Y implements Equivalent<String>, EqualityComparable<Integer> {\n" +
- " public abstract boolean equalTo(Number other);\n" +
- "}\n" +
- "interface Equivalent<T> { boolean equalTo(T other); }\n" +
- "interface EqualityComparable<T> { boolean equalTo(T other); }\n"
- },
- ""
- // no bridge methods are created here since Y does not define an equalTo(?) method which equals an inherited equalTo method
- );
+ if (this.complianceLevel < ClassFileConstants.JDK1_7) {
+ this.runConformTest(
+ new String[] {
+ "Y.java",
+ "abstract class Y implements Equivalent<String>, EqualityComparable<Integer> {\n" +
+ " public abstract boolean equalTo(Number other);\n" +
+ "}\n" +
+ "interface Equivalent<T> { boolean equalTo(T other); }\n" +
+ "interface EqualityComparable<T> { boolean equalTo(T other); }\n"
+ },
+ ""
+ // no bridge methods are created here since Y does not define an equalTo(?) method which equals an inherited equalTo method
+ );
+ } else {
+ this.runNegativeTest(
+ new String[] {
+ "Y.java",
+ "abstract class Y implements Equivalent<String>, EqualityComparable<Integer> {\n" +
+ " public abstract boolean equalTo(Number other);\n" +
+ "}\n" +
+ "interface Equivalent<T> { boolean equalTo(T other); }\n" +
+ "interface EqualityComparable<T> { boolean equalTo(T other); }\n"
+ },
+ "----------\n" +
+ "1. ERROR in Y.java (at line 1)\n" +
+ " abstract class Y implements Equivalent<String>, EqualityComparable<Integer> {\n" +
+ " ^\n" +
+ "Name clash: The method equalTo(T) of type Equivalent<T> has the same erasure as equalTo(T) of type EqualityComparable<T> but does not override it\n" +
+ "----------\n");
+ }
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=83162
public void test036e() { // 2 interface cases
@@ -2354,6 +2372,7 @@ public class MethodVerifyTest extends AbstractComparableTest {
"interface Equivalent<T> { boolean equalTo(T other); }\n" +
"interface EqualityComparable<T> { boolean equalTo(T other); }\n"
},
+ this.complianceLevel < ClassFileConstants.JDK1_7 ?
"----------\n" +
"1. ERROR in Y.java (at line 2)\n" +
" public abstract boolean equalTo(Object other);\n" +
@@ -2364,8 +2383,24 @@ public class MethodVerifyTest extends AbstractComparableTest {
" public abstract boolean equalTo(Object other);\n" +
" ^^^^^^^^^^^^^^^^^^^^^\n" +
"Name clash: The method equalTo(Object) of type Y has the same erasure as equalTo(T) of type EqualityComparable<T> but does not override it\n" +
- "----------\n"
+ "----------\n" :
// name clash: equalTo(java.lang.Object) in Y and equalTo(T) in Equivalent<java.lang.String> have the same erasure, yet neither overrides the other
+ "----------\n" +
+ "1. ERROR in Y.java (at line 1)\n" +
+ " abstract class Y implements Equivalent<String>, EqualityComparable<Integer> {\n" +
+ " ^\n" +
+ "Name clash: The method equalTo(T) of type Equivalent<T> has the same erasure as equalTo(T) of type EqualityComparable<T> but does not override it\n" +
+ "----------\n" +
+ "2. ERROR in Y.java (at line 2)\n" +
+ " public abstract boolean equalTo(Object other);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Name clash: The method equalTo(Object) of type Y has the same erasure as equalTo(T) of type Equivalent<T> but does not override it\n" +
+ "----------\n" +
+ "3. ERROR in Y.java (at line 2)\n" +
+ " public abstract boolean equalTo(Object other);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Name clash: The method equalTo(Object) of type Y has the same erasure as equalTo(T) of type EqualityComparable<T> but does not override it\n" +
+ "----------\n"
);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=83162
@@ -2428,6 +2463,7 @@ public class MethodVerifyTest extends AbstractComparableTest {
"interface K extends I { void foo(A<String> a); }\n" +
"class A<T> {}"
},
+ this.complianceLevel < ClassFileConstants.JDK1_7 ?
"----------\n" +
"1. WARNING in X.java (at line 4)\n" +
" class YYY implements J, I { public void foo(A a) {} }\n" +
@@ -2453,7 +2489,38 @@ public class MethodVerifyTest extends AbstractComparableTest {
" interface K extends I { void foo(A<String> a); }\n" +
" ^^^^^^^^^^^^^^^^\n" +
"Name clash: The method foo(A<String>) of type K has the same erasure as foo(A) of type I but does not override it\n" +
- "----------\n");
+ "----------\n" :
+ "----------\n" +
+ "1. ERROR in X.java (at line 2)\n" +
+ " abstract class Y implements J, I { }\n" +
+ " ^\n" +
+ "Name clash: The method foo(A<String>) of type J has the same erasure as foo(A) of type I but does not override it\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 4)\n" +
+ " class YYY implements J, I { public void foo(A a) {} }\n" +
+ " ^\n" +
+ "A is a raw type. References to generic type A<T> should be parameterized\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 5)\n" +
+ " class XXX implements I, J { public void foo(A a) {} }\n" +
+ " ^\n" +
+ "A is a raw type. References to generic type A<T> should be parameterized\n" +
+ "----------\n" +
+ "4. WARNING in X.java (at line 6)\n" +
+ " class ZZZ implements K { public void foo(A a) {} }\n" +
+ " ^\n" +
+ "A is a raw type. References to generic type A<T> should be parameterized\n" +
+ "----------\n" +
+ "5. WARNING in X.java (at line 7)\n" +
+ " interface I { void foo(A a); }\n" +
+ " ^\n" +
+ "A is a raw type. References to generic type A<T> should be parameterized\n" +
+ "----------\n" +
+ "6. ERROR in X.java (at line 9)\n" +
+ " interface K extends I { void foo(A<String> a); }\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Name clash: The method foo(A<String>) of type K has the same erasure as foo(A) of type I but does not override it\n" +
+ "----------\n");
}
public void test037a() { // test inheritance scenarios
this.runNegativeTest(
@@ -11470,9 +11537,9 @@ public void test207() {
},
"class java.lang.Object");
}
-// https://bugs.eclipse.org/bugs/show_bug.cgi?id=343060, make sure a bridge method
-// is NOT generated when a public method is inherited from a non-public class into a
-// public class if the non public class happens to be in the default package.
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=288658, make sure a bridge method
+// is generated when a public method is inherited from a non-public class into a
+// public class.
public void test208() {
this.runConformTest(
new String[] {
@@ -11505,11 +11572,11 @@ public void test208() {
"\n"+
"}\n"
},
- "Annotation was found");
+ this.complianceLevel <= ClassFileConstants.JDK1_5 ? "Annotation was found" : "Annotation was not found");
}
-// https://bugs.eclipse.org/bugs/show_bug.cgi?id=343060, make sure a bridge method
-// is NOT generated when a public method is inherited from a non-public class into a
-// public class if the non public class happens to be in the default package.
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=288658, make sure a bridge method
+// is generated when a public method is inherited from a non-public class into a
+// public class.
public void test208a() {
this.runConformTest(
new String[] {
@@ -11543,7 +11610,7 @@ public void test208a() {
"\n"+
"}\n"
},
- "Annotation was found");
+ this.complianceLevel <= ClassFileConstants.JDK1_5 ? "Annotation was found" : "Annotation was not found");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=322001
public void test209() {
@@ -13617,4 +13684,130 @@ public void test288658a() {
},
this.complianceLevel <= ClassFileConstants.JDK1_5 ? "Annotation was found" : "Annotation was not found");
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=354229
+public void test354229() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.util.*;\n" +
+ "interface A {\n" +
+ "int get(List<String> l);\n" +
+ "}\n" +
+ "interface B {\n" +
+ "int get(List<Integer> l);\n" +
+ "}\n" +
+ "interface C extends A, B { \n" +
+ "//int get(List l); // name clash error here\n" +
+ " Zork z;\n" +
+ "}\n"
+ },
+ this.complianceLevel <= ClassFileConstants.JDK1_6 ?
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " Zork z;\n" +
+ " ^^^^\n" +
+ "Zork cannot be resolved to a type\n" +
+ "----------\n" :
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " interface C extends A, B { \n" +
+ " ^\n" +
+ "Name clash: The method get(List<String>) of type A has the same erasure as get(List<Integer>) of type B but does not override it\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 10)\n" +
+ " Zork z;\n" +
+ " ^^^^\n" +
+ "Zork cannot be resolved to a type\n" +
+ "----------\n");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=354229
+public void test354229b() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.util.*;\n" +
+ "interface A {\n" +
+ "int get(List<String> l);\n" +
+ "}\n" +
+ "interface B {\n" +
+ "int get(List<Integer> l);\n" +
+ "}\n" +
+ "interface C extends A, B { \n" +
+ " int get(List l); // name clash error here\n" +
+ " Zork z;\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. WARNING in X.java (at line 9)\n" +
+ " int get(List l); // name clash error here\n" +
+ " ^^^^\n" +
+ "List is a raw type. References to generic type List<E> should be parameterized\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 10)\n" +
+ " Zork z;\n" +
+ " ^^^^\n" +
+ "Zork cannot be resolved to a type\n" +
+ "----------\n");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=354229
+public void test354229c() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "interface X {\n" +
+ " <T> T e(Action<T> p);\n" +
+ "}\n" +
+ "interface Y {\n" +
+ " <S, T> S e(Action<S> t);\n" +
+ "}\n" +
+ "interface E extends X, Y {\n" +
+ "}\n" +
+ "class Action<T> {\n" +
+ " Zork z;\n" +
+ "}\n"
+
+ },
+ this.complianceLevel < ClassFileConstants.JDK1_7 ?
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " Zork z;\n" +
+ " ^^^^\n" +
+ "Zork cannot be resolved to a type\n" +
+ "----------\n" :
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " interface E extends X, Y {\n" +
+ " ^\n" +
+ "Name clash: The method e(Action<T>) of type X has the same erasure as e(Action<S>) of type Y but does not override it\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 10)\n" +
+ " Zork z;\n" +
+ " ^^^^\n" +
+ "Zork cannot be resolved to a type\n" +
+ "----------\n");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=354229
+public void test354229d() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "interface X {\n" +
+ " <T> T e(Action<T> p);\n" +
+ " <S, T> S e(Action<S> t);\n" +
+ "}\n" +
+ "class Action<T> {\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 2)\n" +
+ " <T> T e(Action<T> p);\n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Method e(Action<T>) has the same erasure e(Action<T>) as another method in type X\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 3)\n" +
+ " <S, T> S e(Action<S> t);\n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Method e(Action<S>) has the same erasure e(Action<T>) as another method in type X\n" +
+ "----------\n");
+}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java
index 1d283670a..2db03cf6c 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,6 +12,7 @@ package org.eclipse.jdt.core.tests.compiler.regression;
import java.util.Map;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import junit.framework.Test;
@@ -24,7 +25,7 @@ public class NonFatalErrorTest extends AbstractRegressionTest {
// All specified tests which does not belong to the class are skipped...
static {
// TESTS_NAMES = new String[] { "test127" };
-// TESTS_NUMBERS = new int[] { 5 };
+// TESTS_NUMBERS = new int[] { 7 };
// TESTS_RANGE = new int[] { 169, 180 };
}
@@ -258,4 +259,41 @@ public class NonFatalErrorTest extends AbstractRegressionTest {
// javac options
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError /* javac test options */);
}
+ public void test007() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) {
+ return;
+ }
+ Map customOptions = getCompilerOptions();
+ customOptions.put(CompilerOptions.OPTION_FatalOptionalError,
+ CompilerOptions.ENABLED);
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal,
+ CompilerOptions.ERROR);
+ customOptions.put(CompilerOptions.OPTION_SuppressWarnings,
+ CompilerOptions.ENABLED);
+ customOptions.put(CompilerOptions.OPTION_SuppressOptionalErrors,
+ CompilerOptions.ENABLED);
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedWarningToken,
+ CompilerOptions.ERROR);
+ runConformTest(
+ new String[] { /* test files */
+ "X.java",
+ "public class X {\n" +
+ " @SuppressWarnings(\"unused\")\n" +
+ " static void foo() {\n" +
+ " String s = null;\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ " public static void main(String argv[]) {\n" +
+ " foo();\n" +
+ " }\n" +
+ "}"
+ },
+ "SUCCESS" /* expected output string */,
+ null /* no class libraries */,
+ true,
+ null,
+ customOptions /* custom options */,
+ // compiler results
+ null /* do not check error string */);
+ }
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
index 53d8a6fb7..1b1d69ca0 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
@@ -19,6 +19,7 @@ import junit.framework.Test;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
// see bug 186342 - [compiler][null] Using annotations for null checking
public class NullAnnotationTest extends AbstractComparableTest {
@@ -52,7 +53,7 @@ public NullAnnotationTest(String name) {
// Static initializer to specify tests subset using TESTS_* static variables
// All specified tests which do not belong to the class are skipped...
static {
-// TESTS_NAMES = new String[] { "test_assignment_expression_1" };
+// TESTS_NAMES = new String[] { "test_redundant_annotation_" };
// TESTS_NUMBERS = new int[] { 561 };
// TESTS_RANGE = new int[] { 1, 2049 };
}
@@ -550,6 +551,183 @@ public void test_nonnull_parameter_013() {
"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
"----------\n");
}
+// non-null varargs (message send)
+public void test_nonnull_parameter_015() {
+ if (this.complianceLevel > ClassFileConstants.JDK1_7) {
+ fail("Reminder: should check if JSR 308 mandates a change in handling vararg elements (see bug 365983).");
+ return;
+ }
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " void foo(@NonNull Object ... o) {\n" +
+ " if (o != null)\n" +
+ " System.out.print(o.toString());\n" +
+ " }\n" +
+ " void foo2(int i, @NonNull Object ... o) {\n" +
+ " if (o.length > 0 && o[0] != null)\n" +
+ " System.out.print(o[0].toString());\n" +
+ " }\n" +
+ " void bar() {\n" +
+ " foo((Object)null);\n" + // unchecked: single plain argument
+ " Object[] objs = null;\n" +
+ " foo(objs);\n" + // error
+ " foo(this, null);\n" + // unchecked: multiple plain arguments
+ " foo2(2, (Object)null);\n" + // unchecked: single plain argument
+ " foo2(2, null, this);\n" + // unchecked: multiple plain arguments
+ " foo2(2, null);\n" + // error
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " if (o != null)\n" +
+ " ^\n" +
+ "Redundant null check: The variable o cannot be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 14)\n" +
+ " foo(objs);\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object[]\' but the provided value is null\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 18)\n" +
+ " foo2(2, null);\n" +
+ " ^^^^^^^^^^^^^\n" +
+ "The argument of type null should explicitly be cast to Object[] for the invocation of the varargs method foo2(int, Object...) from type X. It could alternatively be cast to Object for a varargs invocation\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 18)\n" +
+ " foo2(2, null);\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object[]\' but the provided value is null\n" +
+ "----------\n",
+ this.LIBS,
+ true /* shouldFlush*/);
+}
+// non-null varargs (allocation and explicit constructor calls)
+public void test_nonnull_parameter_016() {
+ if (this.complianceLevel > ClassFileConstants.JDK1_7) {
+ fail("Reminder: should check if JSR 308 mandates a change in handling vararg elements (see bug 365983).");
+ return;
+ }
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " X(@NonNull Object ... o) {\n" +
+ " if (o != null)\n" +
+ " System.out.print(o.toString());\n" +
+ " }\n" +
+ " class Y extends X {\n" +
+ " Y(int i, @NonNull Object ... o) {\n" +
+ " super(i, (Object)null);\n" +
+ " }\n" +
+ " Y(char c, @NonNull Object ... o) {\n" +
+ " this(1, new Object(), null);\n" +
+ " }\n" +
+ " }\n" +
+ " void bar() {\n" +
+ " new X((Object[])null);\n" +
+ " new X(this, null);\n" +
+ " X x = new X(null, this);\n" +
+ " x.new Y(2, (Object)null);\n" +
+ " this.new Y(2, null, this);\n" +
+ " this.new Y(2, (Object[])null);\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " if (o != null)\n" +
+ " ^\n" +
+ "Redundant null check: The variable o cannot be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 16)\n" +
+ " new X((Object[])null);\n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Type mismatch: required \'@NonNull Object[]\' but the provided value is null\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 21)\n" +
+ " this.new Y(2, (Object[])null);\n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Type mismatch: required \'@NonNull Object[]\' but the provided value is null\n" +
+ "----------\n",
+ this.LIBS,
+ true /* shouldFlush*/);
+}
+// Bug 367203 - [compiler][null] detect assigning null to nonnull argument
+public void test_nonnull_argument_001() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "ShowNPE2.java",
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "@NonNullByDefault\n" +
+ "public class ShowNPE2 {\n" +
+ " public Object foo(Object o1, final boolean b) {\n" +
+ " o1 = null; // expect NPE error\n" +
+ " System.out.println(o1.toString()); \n" +
+ " return null; // expect NPE error\n" +
+ " }\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in ShowNPE2.java (at line 5)\n" +
+ " o1 = null; // expect NPE error\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n" +
+ "2. ERROR in ShowNPE2.java (at line 7)\n" +
+ " return null; // expect NPE error\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n");
+}
+// Bug 367203 - [compiler][null] detect assigning null to nonnull argument
+public void test_nonnull_argument_002() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "ShowNPE2.java",
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "@NonNullByDefault\n" +
+ "public class ShowNPE2 {\n" +
+ " public Object foo(Object o1, final boolean b) {\n" +
+ " bar(o1); // expecting no problem\n" +
+ " return null; // expect NPE error\n" +
+ " }\n" +
+ " void bar(Object o2) {}\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in ShowNPE2.java (at line 6)\n" +
+ " return null; // expect NPE error\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n");
+}
+// a method of a local class has a non-null parameter, client passes potential null (msg send)
+public void test_nonnull_parameter_014() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "B.java",
+ "class B {\n" +
+ " void bar () {\n" +
+ " class Local {\n" +
+ " void callMe(@org.eclipse.jdt.annotation.NonNull Object o){\n" +
+ " }\n" +
+ " }\n" +
+ " Local l = new Local();\n" +
+ " l.callMe(getNull());\n" +
+ " }\n" +
+ " @org.eclipse.jdt.annotation.Nullable Object getNull() { return null; }" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in B.java (at line 8)\n" +
+ " l.callMe(getNull());\n" +
+ " ^^^^^^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" +
+ "----------\n");
+}
// assigning potential null to a nonnull local variable
public void test_nonnull_local_001() {
runNegativeTest(
@@ -1513,6 +1691,39 @@ public void test_nonnull_return_013() {
customOptions,
"");
}
+// bug 365835: [compiler][null] inconsistent error reporting.
+public void test_nonnull_return_014() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "\n" +
+ "public class X {\n" +
+ " @NonNull\n" +
+ " public Object foo(Object x, int y) {\n" +
+ " @NonNull Object local;\n" +
+ " while (true) {\n" +
+ " if (y == 4) {\n" +
+ " local = x; // error\n" +
+ " return x; // only a warning.\n" +
+ " }\n" +
+ " x = null;\n" +
+ " }\n" +
+ " }\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " local = x; // error\n" +
+ " ^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 10)\n" +
+ " return x; // only a warning.\n" +
+ " ^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" +
+ "----------\n");
+}
//suppress an error regarding null-spec violation
public void test_suppress_001() {
Map customOptions = getCompilerOptions();
@@ -2326,8 +2537,421 @@ public void test_default_nullness_011() {
" new C(null);\n" +
" ^^^^\n" +
"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n" +
+ "----------\n" +
+ "1. WARNING in p1\\C.java (at line 2)\n" +
+ " @org.eclipse.jdt.annotation.NonNullByDefault\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing package p1\n" +
+ "----------\n");
+}
+// Bug 365836 - [compiler][null] Incomplete propagation of null defaults.
+public void test_default_nullness_012() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "\n" +
+ "public class X {\n" +
+ " @NonNullByDefault \n" +
+ " public void foo(@Nullable String [] args) {\n" +
+ " class local {\n" +
+ " void zoo(Object o) {\n" +
+ " }\n" +
+ " };\n" +
+ " new local().zoo(null); // defaults applying from foo\n" +
+ " }\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 11)\n" +
+ " new local().zoo(null); // defaults applying from foo\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n");
+}
+// Bug 365836 - [compiler][null] Incomplete propagation of null defaults.
+public void test_default_nullness_013() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "\n" +
+ "@SuppressWarnings(\"unused\")\n" +
+ "public class X {\n" +
+ " @NonNullByDefault \n" +
+ " public void foo(@Nullable String [] args) {\n" +
+ " class local {\n" +
+ " class Deeply {\n" +
+ " Object zoo() {\n" +
+ " return null; // defaults applying from foo\n" +
+ " }\n" +
+ " }\n" +
+ " };\n" +
+ " }\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 11)\n" +
+ " return null; // defaults applying from foo\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n");
+}
+// bug 367154 - [compiler][null] Problem in propagating null defaults.
+public void test_default_nullness_014() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "\n" +
+ "@SuppressWarnings(\"unused\")\n" +
+ "public class X {\n" +
+ "\n" +
+ " public void foo(@Nullable String [] args) {\n" +
+ " @NonNullByDefault\n" +
+ " class local {\n" +
+ " class Deeply {\n" +
+ " Object zoo() {\n" +
+ " return null; // expect error here\n" +
+ " }\n" +
+ " }\n" +
+ " };\n" +
+ " }\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 12)\n" +
+ " return null; // expect error here\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n");
+}
+// bug 367154 - [compiler][null] Problem in propagating null defaults.
+// initializer involved
+public void test_default_nullness_015() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "\n" +
+ "@SuppressWarnings(\"unused\")\n" +
+ "@NonNullByDefault\n" +
+ "public class X {\n" +
+ " {\n" +
+ " class local {\n" +
+ " class Deeply {\n" +
+ " Object zoo() {\n" +
+ " return null; // expect error here\n" +
+ " }\n" +
+ " }\n" +
+ " };\n" +
+ " }\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 11)\n" +
+ " return null; // expect error here\n" +
+ " ^^^^\n" +
+ "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
"----------\n");
}
+
+// redundant default annotations - class vs. inner class
+public void test_redundant_annotation_01() {
+ Map customOptions = getCompilerOptions();
+// customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
+ runConformTestWithLibs(
+ new String[] {
+ "p2/Y.java",
+ "package p2;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "@NonNullByDefault\n" +
+ "public class Y {\n" +
+ " @NonNullByDefault class Inner {\n" +
+ " @NonNullByDefault class DeepInner {}\n" +
+ " }\n" +
+ " class Inner2 {\n" +
+ " @NonNullByDefault class DeepInner2 {\n" +
+ " }\n" +
+ " void foo() {\n" +
+ " @SuppressWarnings(\"unused\") @NonNullByDefault class Local {}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "@NonNullByDefault class V {}\n",
+ "p3/package-info.java",
+ "@org.eclipse.jdt.annotation.NonNullByDefault package p3;\n",
+ "p3/Z.java",
+ "package p3;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "@NonNullByDefault\n" +
+ "public class Z {\n" +
+ "}\n" +
+ "class X {\n" +
+ " @NonNullByDefault class Inner {}\n" +
+ " class Inner2 {\n" +
+ " @NonNullByDefault class DeepInner {}\n" +
+ " }\n" +
+ "}\n"
+ },
+ customOptions,
+ "----------\n" +
+ "1. WARNING in p2\\Y.java (at line 5)\n" +
+ " @NonNullByDefault class Inner {\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing type Y\n" +
+ "----------\n" +
+ "2. WARNING in p2\\Y.java (at line 6)\n" +
+ " @NonNullByDefault class DeepInner {}\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing type Y.Inner\n" +
+ "----------\n" +
+ "3. WARNING in p2\\Y.java (at line 9)\n" +
+ " @NonNullByDefault class DeepInner2 {\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing type Y\n" +
+ "----------\n" +
+ "4. WARNING in p2\\Y.java (at line 12)\n" +
+ " @SuppressWarnings(\"unused\") @NonNullByDefault class Local {}\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing type Y\n" +
+ "----------\n" +
+ "----------\n" +
+ "1. WARNING in p3\\Z.java (at line 3)\n" +
+ " @NonNullByDefault\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing package p3\n" +
+ "----------\n" +
+ "2. WARNING in p3\\Z.java (at line 7)\n" +
+ " @NonNullByDefault class Inner {}\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing package p3\n" +
+ "----------\n" +
+ "3. WARNING in p3\\Z.java (at line 9)\n" +
+ " @NonNullByDefault class DeepInner {}\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing package p3\n" +
+ "----------\n");
+}
+
+// redundant default annotations - class vs. method
+public void test_redundant_annotation_02() {
+ Map customOptions = getCompilerOptions();
+ runConformTestWithLibs(
+ new String[] {
+ "p2/Y.java",
+ "package p2;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "@NonNullByDefault\n" +
+ "public class Y {\n" +
+ " @NonNullByDefault void foo() {}\n" +
+ "}\n" +
+ "class Z {\n" +
+ " @NonNullByDefault void bar() {\n" +
+ " @NonNullByDefault @SuppressWarnings(\"unused\") class Zork {\n" +
+ " @NonNullByDefault void fubar() {}\n" +
+ " }\n" +
+ " }\n" +
+ " @NonNullByDefault void zink() {\n" +
+ " @SuppressWarnings(\"unused\") class Bork {\n" +
+ " @NonNullByDefault void jubar() {}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ customOptions,
+ "----------\n" +
+ "1. WARNING in p2\\Y.java (at line 5)\n" +
+ " @NonNullByDefault void foo() {}\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing type Y\n" +
+ "----------\n" +
+ "2. WARNING in p2\\Y.java (at line 9)\n" +
+ " @NonNullByDefault @SuppressWarnings(\"unused\") class Zork {\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing method bar()\n" +
+ "----------\n" +
+ "3. WARNING in p2\\Y.java (at line 10)\n" +
+ " @NonNullByDefault void fubar() {}\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing type Zork\n" +
+ "----------\n" +
+ "4. WARNING in p2\\Y.java (at line 15)\n" +
+ " @NonNullByDefault void jubar() {}\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing method zink()\n" +
+ "----------\n");
+}
+
+//redundant default annotations - class vs. method - generics
+public void test_redundant_annotation_02g() {
+ Map customOptions = getCompilerOptions();
+ runConformTestWithLibs(
+ new String[] {
+ "p2/Y.java",
+ "package p2;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "@NonNullByDefault\n" +
+ "public class Y<TY> {\n" +
+ " @NonNullByDefault <TF> void foo(TF arg) {}\n" +
+ "}\n" +
+ "class Z {\n" +
+ " @NonNullByDefault <TB> void bar() {\n" +
+ " @NonNullByDefault @SuppressWarnings(\"unused\") class Zork {\n" +
+ " @NonNullByDefault void fubar(TB arg) {}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ customOptions,
+ "----------\n" +
+ "1. WARNING in p2\\Y.java (at line 5)\n" +
+ " @NonNullByDefault <TF> void foo(TF arg) {}\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing type Y<TY>\n" +
+ "----------\n" +
+ "2. WARNING in p2\\Y.java (at line 9)\n" +
+ " @NonNullByDefault @SuppressWarnings(\"unused\") class Zork {\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing method bar()\n" +
+ "----------\n" +
+ "3. WARNING in p2\\Y.java (at line 10)\n" +
+ " @NonNullByDefault void fubar(TB arg) {}\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing type Zork\n" +
+ "----------\n");
+}
+
+// redundant default annotations - package / class / method vs global default
+public void test_redundant_annotation_03() {
+ Map customOptions = getCompilerOptions();
+ customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
+ runConformTestWithLibs(
+ new String[] {
+ "p2/Y.java",
+ "package p2;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "@NonNullByDefault\n" +
+ "public class Y {\n" +
+ " @NonNullByDefault void foo() {}\n" +
+ "}\n" +
+ "class Z {\n" +
+ " @NonNullByDefault void bar() {}\n" +
+ "}\n",
+ "p3/package-info.java",
+ "@org.eclipse.jdt.annotation.NonNullByDefault package p3;\n"
+ },
+ customOptions,
+ "----------\n" +
+ "1. WARNING in p2\\Y.java (at line 3)\n" +
+ " @NonNullByDefault\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with the global default\n" +
+ "----------\n" +
+ "2. WARNING in p2\\Y.java (at line 5)\n" +
+ " @NonNullByDefault void foo() {}\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with a default specified for the enclosing type Y\n" +
+ "----------\n" +
+ "3. WARNING in p2\\Y.java (at line 8)\n" +
+ " @NonNullByDefault void bar() {}\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with the global default\n" +
+ "----------\n" +
+ "----------\n" +
+ "1. WARNING in p3\\package-info.java (at line 1)\n" +
+ " @org.eclipse.jdt.annotation.NonNullByDefault package p3;\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Nullness default is redundant with the global default\n" +
+ "----------\n");
+}
+
+// redundant default annotations - class vs. inner class
+// ensure that disabling null annotations also disables this diagnostic
+public void test_redundant_annotation_04() {
+ Map customOptions = getCompilerOptions();
+ customOptions.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.DISABLED);
+ runConformTestWithLibs(
+ new String[] {
+ "p2/Y.java",
+ "package p2;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "@NonNullByDefault\n" +
+ "public class Y {\n" +
+ " @NonNullByDefault class Inner {\n" +
+ " @NonNullByDefault class DeepInner {}\n" +
+ " }\n" +
+ " class Inner2 {\n" +
+ " @NonNullByDefault class DeepInner2 {\n" +
+ " }\n" +
+ " @NonNullByDefault void foo(@Nullable @NonNull Object arg) {\n" +
+ " @NonNullByDefault class Local {}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "@NonNullByDefault class V {}\n",
+ "p3/package-info.java",
+ "@org.eclipse.jdt.annotation.NonNullByDefault package p3;\n",
+ "p3/Z.java",
+ "package p3;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "@NonNullByDefault\n" +
+ "public class Z {\n" +
+ "}\n" +
+ "class X {\n" +
+ " @NonNullByDefault class Inner {}\n" +
+ " class Inner2 {\n" +
+ " @NonNullByDefault class DeepInner {}\n" +
+ " }\n" +
+ "}\n"
+ },
+ customOptions,
+ "");
+}
+
+// contradictory null annotations
+public void test_contradictory_annotations_01() {
+ Map customOptions = getCompilerOptions();
+ runNegativeTestWithLibs(
+ new String[] {
+ "p2/Y.java",
+ "package p2;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class Y {\n" +
+ " void foo(@NonNull @Nullable Object o) {}\n" +
+ " @Nullable @NonNull Object bar() {\n" +
+ " @NonNull @Nullable Object o = null;\n" +
+ " return o;\n" +
+ " }\n" +
+ "}\n" +
+ "class Z {\n" +
+ " @NonNullByDefault void bar() {}\n" +
+ "}\n"
+ },
+ customOptions,
+ "----------\n" +
+ "1. ERROR in p2\\Y.java (at line 4)\n" +
+ " void foo(@NonNull @Nullable Object o) {}\n" +
+ " ^^^^^^^^^\n" +
+ "Contradictory null specification; only one of @NonNull and @Nullable can be specified at any location\n" +
+ "----------\n" +
+ "2. ERROR in p2\\Y.java (at line 5)\n" +
+ " @Nullable @NonNull Object bar() {\n" +
+ " ^^^^^^^^\n" +
+ "Contradictory null specification; only one of @NonNull and @Nullable can be specified at any location\n" +
+ "----------\n" +
+ "3. ERROR in p2\\Y.java (at line 6)\n" +
+ " @NonNull @Nullable Object o = null;\n" +
+ " ^^^^^^^^^\n" +
+ "Contradictory null specification; only one of @NonNull and @Nullable can be specified at any location\n" +
+ "----------\n");
+}
+
// a nonnull variable is dereferenced in a loop
public void test_nonnull_var_in_constrol_structure_1() {
Map customOptions = getCompilerOptions();
@@ -2589,7 +3213,7 @@ public void test_assignment_expression_1() {
customOptions,
"");
}
-// a nonnull variable is dereferenced method of a nested type
+// a nonnull variable is dereferenced in a method of a nested type
public void test_nesting_1() {
Map customOptions = getCompilerOptions();
// customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
@@ -2598,7 +3222,6 @@ public void test_nesting_1() {
new String[] {
"X.java",
"import org.eclipse.jdt.annotation.*;\n" +
- "@NonNullByDefault\n" +
"public class X {\n" +
" void print4(final String s1) {\n" +
" for (int i=0; i<3; i++)\n" +
@@ -2633,12 +3256,12 @@ public void test_nesting_1() {
},
customOptions,
"----------\n" +
- "1. ERROR in X.java (at line 16)\n" +
+ "1. ERROR in X.java (at line 15)\n" +
" print(s2);\n" +
" ^^\n" +
"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
"----------\n" +
- "2. ERROR in X.java (at line 25)\n" +
+ "2. ERROR in X.java (at line 24)\n" +
" @NonNull String s3R = s3;\n" +
" ^^\n" +
"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java
index 95af131fd..2bb4c6175 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * Copyright (c) 2005, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -37,6 +37,7 @@ import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
/**
* A tests series especially meant to validate the internals of our null
@@ -1083,18 +1084,21 @@ public FlowInfo copy() {
return copy;
}
-public void markAsDefinitelyNonNull(LocalVariableBinding local) {
- grow(local.id + this.maxFieldCount);
+public void markAsDefinitelyNonNull(VariableBinding local) {
+ int position = local.getAnalysisId(this.maxFieldCount);
+ grow(position);
super.markAsDefinitelyNonNull(local);
}
-public void markAsDefinitelyNull(LocalVariableBinding local) {
- grow(local.id + this.maxFieldCount);
+public void markAsDefinitelyNull(VariableBinding local) {
+ int position = local.getAnalysisId(this.maxFieldCount);
+ grow(position);
super.markAsDefinitelyNull(local);
}
-public void markAsDefinitelyUnknown(LocalVariableBinding local) {
- grow(local.id + this.maxFieldCount);
+public void markAsDefinitelyUnknown(VariableBinding local) {
+ int position = local.getAnalysisId(this.maxFieldCount);
+ grow(position);
super.markAsDefinitelyUnknown(local);
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
index 0b017455a..6e8dfa6cc 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -21,6 +21,7 @@
* bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis
* bug 349326 - [1.7] new warning for missing try-with-resources
* bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
+ * bug 367879 - Incorrect "Potential null pointer access" warning on statement after try-with-resources within try-finally
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -48,7 +49,7 @@ public NullReferenceTest(String name) {
// Only the highest compliance level is run; add the VM argument
// -Dcompliance=1.4 (for example) to lower it if needed
static {
-// TESTS_NAMES = new String[] { "testBug360328" };
+// TESTS_NAMES = new String[] { "testBug247564n_3" };
// TESTS_NUMBERS = new int[] { 561 };
// TESTS_RANGE = new int[] { 1, 2049 };
}
@@ -71,6 +72,7 @@ protected Map getCompilerOptions() {
defaultOptions.put(CompilerOptions.OPTION_ReportRedundantNullCheck, CompilerOptions.ERROR);
defaultOptions.put(CompilerOptions.OPTION_ReportRawTypeReference, CompilerOptions.IGNORE);
defaultOptions.put(CompilerOptions.OPTION_IncludeNullInfoFromAsserts, CompilerOptions.ENABLED);
+ defaultOptions.put(CompilerOptions.OPTION_IncludeFieldsInNullAnalysis, CompilerOptions.ENABLED);
}
return defaultOptions;
}
@@ -108,13 +110,12 @@ public void test0002_simple_field() {
" o.toString();\n" +
" }\n" +
"}\n"},
- ""
-// "----------\n" +
-// "1. ERROR in X.java (at line 5)\n" +
-// " o.toString();\n" +
-// " ^\n" +
-// "The field o is likely null; it was either set to null or checked for null when last used\n" +
-// "----------\n"
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n"
);
}
@@ -345,13 +346,12 @@ public void test0014_field_with_explicit_this_access() {
" this.o.toString();\n" +
" }\n" +
"}\n"},
- ""
-// "----------\n" +
-// "1. ERROR in X.java (at line 5)\n" +
-// " this.o.toString();\n" +
-// " ^^^^^^\n" +
-// "The field o is likely null; it was either set to null or checked for null when last used\n" +
-// "----------\n"
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " this.o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n"
);
}
@@ -367,13 +367,12 @@ public void test0015_field_with_explicit_this_access() {
" o.toString();\n" +
" }\n" +
"}\n"},
- ""
-// "----------\n" +
-// "1. ERROR in X.java (at line 5)\n" +
-// " o.toString();\n" +
-// " ^\n" +
-// "The field o is likely null; it was either set to null or checked for null when last used\n" +
-// "----------\n"
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n"
);
}
@@ -423,13 +422,12 @@ public void test0018_field_of_enclosing_object() {
" }\n" +
" }\n" +
"}\n"},
- ""
-// "----------\n" +
-// "1. ERROR in X.java (at line 6)\n" +
-// " X.this.o.toString();\n" +
-// " ^^^^^^^^\n" +
-// "The field o is likely null; it was either set to null or checked for null when last used\n" +
-// "----------\n"
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " X.this.o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n"
);
}
@@ -448,13 +446,12 @@ public void test0019_field_synchronized() {
" }\n" +
" void bar() {/* */}\n" +
"}\n"},
- ""
-// "----------\n" +
-// "1. ERROR in X.java (at line 5)\n" +
-// " o.toString();\n" +
-// " ^\n" +
-// "The field o is likely null; it was either set to null or checked for null when last used\n" +
-// "----------\n"
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n"
);
}
@@ -3098,7 +3095,7 @@ public void test0412_while_if_nested() {
// null analysis -- while
public void test0413_while_unknown_field() {
- this.runConformTest(
+ this.runNegativeTest(
new String[] {
"X.java",
"public class X {\n" +
@@ -3110,7 +3107,12 @@ public void test0413_while_unknown_field() {
" o.toString();\n" +
" }\n" +
"}\n"},
- "");
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n");
}
// null analysis -- while
@@ -6021,6 +6023,7 @@ public void test0561_try_catch_unchecked_exception() {
public void test0562_try_catch_unchecked_exception() {
Map options = getCompilerOptions();
options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.WARNING);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
this.runNegativeTest(
true,
new String[] {
@@ -6043,7 +6046,7 @@ public void test0562_try_catch_unchecked_exception() {
"1. WARNING in X.java (at line 6)\n" +
" o = new LineNumberReader(new FileReader(\"dummy\"));\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Resource leak: 'o' is never closed\n" +
+ "Potential resource leak: \'o\' may not be closed\n" +
"----------\n" +
"2. ERROR in X.java (at line 8)\n" +
" o.toString();\n" +
@@ -15010,6 +15013,32 @@ public void test358827() {
"----------\n");
}
}
+// Bug 367879 - Incorrect "Potential null pointer access" warning on statement after try-with-resources within try-finally
+public void test367879() {
+ if (this.complianceLevel >= ClassFileConstants.JDK1_7) {
+ this.runConformTest(
+ new String[] {
+ "Bug367879.java",
+ "import java.io.IOException;\n" +
+ "import java.io.InputStream;\n" +
+ "import java.net.HttpURLConnection;\n" +
+ "import java.net.URL;\n" +
+ "public class Bug367879 {\n" +
+ " public void test() throws IOException {\n" +
+ " HttpURLConnection http = null;\n" +
+ " try {\n" +
+ " http = (HttpURLConnection) new URL(\"http://example.com/\").openConnection();\n" +
+ " try (InputStream in = http.getInputStream()) { /* get input */ }\n" +
+ " http.getURL();\n" + // shouldn't *not* flag as Potential null pointer access
+ " } finally {\n" +
+ " if (http != null) { http.disconnect(); }\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "");
+ }
+}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=256796
public void testBug256796() {
Map compilerOptions = getCompilerOptions();
@@ -15427,4 +15456,2709 @@ public void testBug360328d() {
"",/* expected error */
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
}
-} \ No newline at end of file
+
+// null analysis -- simple case for field
+public void testBug247564a() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " Object o;\n" +
+ " void foo() {\n" +
+ " if (o == null && o.toString() == \"\"){}\n" +
+ " else {}\n" +
+ " o.toString();\n" + // toString() call above defuses null info, so no warning here
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " if (o == null && o.toString() == \"\"){}\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- simple case for field
+// no redundant null check warnings should be obtained since value of field
+// may be changed in another thread.
+public void testBug247564a_1() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " Object o;\n" +
+ " void foo() {\n" +
+ " o = null;" +
+ " if (o == null){}\n" +
+ " if (o != null){}\n" +
+ " o.toString();\n" + // warn here
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- simple case for field
+public void testBug247564a_2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " Object o;\n" +
+ " void foo() {\n" +
+ " if (o == null){\n" + // o is null inside the if block
+ " o.toString();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- simple case for field
+// null info from one method should not be present in the other (for instance fields)
+public void testBug247564a_3() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " Object o;\n" +
+ " void foo() {\n" +
+ " o = null;\n" +
+ " }\n" +
+ " void foo1() {\n" +
+ " o.toString();\n" +
+ " }\n" +
+ "}\n"},
+ ""
+ );
+}
+
+//null analysis -- simple case for field
+public void testBug247564a_4() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " Object o;\n" +
+ " int foo() {\n" +
+ " if (o != null && o.toString() == \"\") {\n" +
+ " } else {\n" +
+ " }\n" +
+ " return o.hashCode();\n" + // the above check has shed doubts so give a warning here
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " return o.hashCode();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- field accessed inside control structure
+// from https://bugs.eclipse.org/bugs/show_bug.cgi?id=247564#c121
+public void testBug247564a_5() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " private Object field;\n" +
+ " void goo(Object var) throws Exception{\n" +
+ " if (field != null) field.hashCode();\n" +
+ " int i = 20;\n" +
+ " while (i<10) {\n" +
+ " if (field == null) { \n" +
+ " field = new Object();\n" +
+ " }\n" +
+ " field.toString(); // Wrong outcome was: Pot. NPE\n" +
+ " i--;\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"},
+ ""
+ );
+}
+
+// null analysis -- simple case for static final field
+// once dereferenced, treat as non null. Consistent with local variables.
+public void testBug247564b() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static final Object o = null;\n" +
+ " static final Object o1 = new Object();\n" +
+ " void foo() {\n" +
+ " if (o.toString() == \"\") {}\n" +
+ " if (o == null) {}\n" +
+ " if (o != null) {}\n" +
+ " if (o1 == null) {}\n" +
+ " if (o1 != null) {}\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " if (o.toString() == \"\") {}\n" +
+ " ^\n" +
+ "Null pointer access: The field o can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 6)\n" +
+ " if (o == null) {}\n" +
+ " ^\n" +
+ "Null comparison always yields false: The field o cannot be null at this location\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 6)\n" +
+ " if (o == null) {}\n" +
+ " ^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 7)\n" +
+ " if (o != null) {}\n" +
+ " ^\n" +
+ "Redundant null check: The field o cannot be null at this location\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 8)\n" +
+ " if (o1 == null) {}\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o1 cannot be null at this location\n" +
+ "----------\n" +
+ "6. WARNING in X.java (at line 8)\n" +
+ " if (o1 == null) {}\n" +
+ " ^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "7. ERROR in X.java (at line 9)\n" +
+ " if (o1 != null) {}\n" +
+ " ^^\n" +
+ "Redundant null check: The field o1 cannot be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- simple case for static final field
+public void testBug247564b_1() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static final Object o;\n" +
+ " static final Object o1;\n" +
+ " static {\n" +
+ " o = null;\n" +
+ " o1 = new Object();\n" +
+ " }\n" +
+ " void foo() {\n" +
+ " if (o.toString() == \"\") {}\n" +
+ " if (o == null) {}\n" +
+ " if (o != null) {}\n" +
+ " if (o1 == null) {}\n" +
+ " if (o1 != null) {}\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " if (o.toString() == \"\") {}\n" +
+ " ^\n" +
+ "Null pointer access: The field o can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 10)\n" +
+ " if (o == null) {}\n" +
+ " ^\n" +
+ "Null comparison always yields false: The field o cannot be null at this location\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 10)\n" +
+ " if (o == null) {}\n" +
+ " ^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 11)\n" +
+ " if (o != null) {}\n" +
+ " ^\n" +
+ "Redundant null check: The field o cannot be null at this location\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 12)\n" +
+ " if (o1 == null) {}\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o1 cannot be null at this location\n" +
+ "----------\n" +
+ "6. WARNING in X.java (at line 12)\n" +
+ " if (o1 == null) {}\n" +
+ " ^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "7. ERROR in X.java (at line 13)\n" +
+ " if (o1 != null) {}\n" +
+ " ^^\n" +
+ "Redundant null check: The field o1 cannot be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- simple case for static final field
+public void testBug247564b_1_2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "Object field0, \n" +
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61, field62, field63, field64, \n" +
+ "field65, field66, field67, field68, \n" +
+ "field69, field70, field71, field72, \n" +
+ "field73, field74, field75, field76, \n" +
+ "field77, field78, field79, field80, \n" +
+ "field81, field82, field83, field84, \n" +
+ "field85, field86, field87, field88, \n" +
+ "field89, field90, field91, field92, \n" +
+ "field93, field94, field95, field96, \n" +
+ "field97, field98, field99;\n" +
+ " static final Object o;\n" +
+ " static final Object o1;\n" +
+ " static {\n" +
+ " o = null;\n" +
+ " o1 = new Object();\n" +
+ " }\n" +
+ " void foo() {\n" +
+ " if (o.toString() == \"\") {}\n" +
+ " if (o == null) {}\n" +
+ " if (o != null) {}\n" +
+ " if (o1 == null) {}\n" +
+ " if (o1 != null) {}\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 35)\n" +
+ " if (o.toString() == \"\") {}\n" +
+ " ^\n" +
+ "Null pointer access: The field o can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 36)\n" +
+ " if (o == null) {}\n" +
+ " ^\n" +
+ "Null comparison always yields false: The field o cannot be null at this location\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 36)\n" +
+ " if (o == null) {}\n" +
+ " ^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 37)\n" +
+ " if (o != null) {}\n" +
+ " ^\n" +
+ "Redundant null check: The field o cannot be null at this location\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 38)\n" +
+ " if (o1 == null) {}\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o1 cannot be null at this location\n" +
+ "----------\n" +
+ "6. WARNING in X.java (at line 38)\n" +
+ " if (o1 == null) {}\n" +
+ " ^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "7. ERROR in X.java (at line 39)\n" +
+ " if (o1 != null) {}\n" +
+ " ^^\n" +
+ "Redundant null check: The field o1 cannot be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// checked before use
+public void testBug247564b_2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static final Object o;\n" +
+ " static final Object o1 = new Object();\n" +
+ " static {\n" +
+ " if (o1.hashCode() == 2){\n" +
+ " o = new Object();\n" +
+ " } else {\n" +
+ " o = null;\n" +
+ " }\n" +
+ " }\n" +
+ " void foo1() {\n" +
+ " if (o == null) \n" +
+ " return;\n" +
+ " o.toString();\n" + // cant be null for sure, dont complain
+ " }\n" +
+ "}\n"},
+ ""
+ );
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// checked before use
+public void testBug247564b_2_2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "Object field0, \n" +
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61, field62, field63, field64, \n" +
+ "field65, field66, field67, field68, \n" +
+ "field69, field70, field71, field72, \n" +
+ "field73, field74, field75, field76, \n" +
+ "field77, field78, field79, field80, \n" +
+ "field81, field82, field83, field84, \n" +
+ "field85, field86, field87, field88, \n" +
+ "field89, field90, field91, field92, \n" +
+ "field93, field94, field95, field96, \n" +
+ "field97, field98, field99;\n" +
+ " static final Object o;\n" +
+ " static final Object o1 = new Object();\n" +
+ " static {\n" +
+ " if (o1.hashCode() == 2){\n" +
+ " o = new Object();\n" +
+ " } else {\n" +
+ " o = null;\n" +
+ " }\n" +
+ " }\n" +
+ " void foo1() {\n" +
+ " if (o == null) \n" +
+ " return;\n" +
+ " o.toString();\n" + // cant be null for sure, dont complain
+ " }\n" +
+ "}\n"},
+ ""
+ );
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// Check pot. NPE case for constant fields
+// Once dereferenced, treat as non null. Just like locals.
+public void testBug247564b_3() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static final Object o;\n" +
+ " static final Object o1 = new Object();\n" +
+ " static {\n" +
+ " if (o1.hashCode() == 2){\n" +
+ " o = new Object();\n" +
+ " } else {\n" +
+ " o = null;\n" +
+ " }\n" +
+ " }\n" +
+ " void foo() {\n" +
+ " if (o.toString() == \"\") {}\n" +
+ " if (o == null) {}\n" +
+ " if (o != null) {}\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 12)\n" +
+ " if (o.toString() == \"\") {}\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 13)\n" +
+ " if (o == null) {}\n" +
+ " ^\n" +
+ "Null comparison always yields false: The field o cannot be null at this location\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 13)\n" +
+ " if (o == null) {}\n" +
+ " ^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 14)\n" +
+ " if (o != null) {}\n" +
+ " ^\n" +
+ "Redundant null check: The field o cannot be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// Check pot. NPE case for constant fields
+// Once dereferenced, treat as non null. Just like locals.
+public void testBug247564b_3_2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "Object field0, \n" +
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61, field62, field63, field64, \n" +
+ "field65, field66, field67, field68, \n" +
+ "field69, field70, field71, field72, \n" +
+ "field73, field74, field75, field76, \n" +
+ "field77, field78, field79, field80, \n" +
+ "field81, field82, field83, field84, \n" +
+ "field85, field86, field87, field88, \n" +
+ "field89, field90, field91, field92, \n" +
+ "field93, field94, field95, field96, \n" +
+ "field97, field98, field99;\n" +
+ " static final Object o;\n" +
+ " static final Object o1 = new Object();\n" +
+ " static {\n" +
+ " if (o1.hashCode() == 2){\n" +
+ " o = new Object();\n" +
+ " } else {\n" +
+ " o = null;\n" +
+ " }\n" +
+ " }\n" +
+ " void foo() {\n" +
+ " if (o.toString() == \"\") {}\n" +
+ " if (o == null) {}\n" +
+ " if (o != null) {}\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 38)\n" +
+ " if (o.toString() == \"\") {}\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 39)\n" +
+ " if (o == null) {}\n" +
+ " ^\n" +
+ "Null comparison always yields false: The field o cannot be null at this location\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 39)\n" +
+ " if (o == null) {}\n" +
+ " ^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 40)\n" +
+ " if (o != null) {}\n" +
+ " ^\n" +
+ "Redundant null check: The field o cannot be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// checked before use
+public void testBug247564b_4() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static final Object o;\n" +
+ " static final Object o1 = new Object();\n" +
+ " static {\n" +
+ " if (o1.hashCode() == 2){\n" +
+ " o = new Object();\n" +
+ " } else {\n" +
+ " o = null;\n" +
+ " }\n" +
+ " }\n" +
+ " void foo1() {\n" +
+ " if (o == null) {\n" +
+ " o.toString(); // danger\n" +
+ " return;\n" +
+ " }\n" +
+ " o.toString(); // safe\n" +
+ " }\n" +
+ " void foo2() {\n" +
+ " if (o != null) {\n" +
+ " o.toString(); // safe (2)\n" +
+ " }\n" +
+ " o.toString(); // uncertain\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 13)\n" +
+ " o.toString(); // danger\n" +
+ " ^\n" +
+ "Null pointer access: The field o can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 22)\n" +
+ " o.toString(); // uncertain\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// checked before use
+public void testBug247564b_4_2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "Object field0, \n" +
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61, field62, field63, field64, \n" +
+ "field65, field66, field67, field68, \n" +
+ "field69, field70, field71, field72, \n" +
+ "field73, field74, field75, field76, \n" +
+ "field77, field78, field79, field80, \n" +
+ "field81, field82, field83, field84, \n" +
+ "field85, field86, field87, field88, \n" +
+ "field89, field90, field91, field92, \n" +
+ "field93, field94, field95, field96, \n" +
+ "field97, field98, field99;\n" +
+ " static final Object o;\n" +
+ " static final Object o1 = new Object();\n" +
+ " static {\n" +
+ " if (o1.hashCode() == 2){\n" +
+ " o = new Object();\n" +
+ " } else {\n" +
+ " o = null;\n" +
+ " }\n" +
+ " }\n" +
+ " void foo1() {\n" +
+ " if (o == null) {\n" +
+ " o.toString(); // danger\n" +
+ " return;\n" +
+ " }\n" +
+ " o.toString(); // safe\n" +
+ " }\n" +
+ " void foo2() {\n" +
+ " if (o != null) {\n" +
+ " o.toString(); // safe (2)\n" +
+ " }\n" +
+ " o.toString(); // uncertain\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 39)\n" +
+ " o.toString(); // danger\n" +
+ " ^\n" +
+ "Null pointer access: The field o can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 48)\n" +
+ " o.toString(); // uncertain\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// check if the resetting works properly i.e. null status for constant fields should not be
+// reset on method calls.
+public void testBug247564b_5() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static final Object o;\n" +
+ " static final Object o1 = new Object();\n" +
+ " static final Object o2 = new Object();\n" +
+ " static {\n" +
+ " if (o1.hashCode() == 2){\n" +
+ " o = new Object();\n" +
+ " } else {\n" +
+ " o = null;\n" +
+ " }\n" +
+ " }\n" +
+ " void foo1() {\n" +
+ " final Object local = null;\n" +
+ " if (local == null) {\n" +
+ " local.toString();\n" +
+ " }\n" +
+ " local.toString();\n" +
+ " if (o == null) {\n" + // don't know o's nullness, so silent
+ " o.toString();\n" + // report NPE
+ " }\n" +
+ " local.toString();\n" + // try to diffuse status for o / o2
+ " o.toString();\n" + // already reported NPE above. So silent. Same behaviour as 'local'
+ " if (o2 == null) {\n" + // report always false null check
+ " o2.toString();\n" + // dead code
+ " }\n" +
+ " o2.toString();" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 14)\n" +
+ " if (local == null) {\n" +
+ " ^^^^^\n" +
+ "Redundant null check: The variable local can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 15)\n" +
+ " local.toString();\n" +
+ " ^^^^^\n" +
+ "Null pointer access: The variable local can only be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 19)\n" +
+ " o.toString();\n" +
+ " ^\n" +
+ "Null pointer access: The field o can only be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 23)\n" +
+ " if (o2 == null) {\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o2 cannot be null at this location\n" +
+ "----------\n" +
+ "5. WARNING in X.java (at line 23)\n" +
+ " if (o2 == null) {\n" +
+ " o2.toString();\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// check if the resetting works properly i.e. null status for constant fields should not be
+// reset on method calls. This test is for constructors
+public void testBug247564b_6() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static final Object o;\n" +
+ " static final Object o1 = new Object();\n" +
+ " static final Object o2 = new Object();\n" +
+ " static {\n" +
+ " if (o1.hashCode() == 2){\n" +
+ " o = new Object();\n" +
+ " } else {\n" +
+ " o = null;\n" +
+ " }\n" +
+ " }\n" +
+ " public X() {\n" +
+ " final Object local = null;\n" +
+ " if (local == null) {\n" +
+ " local.toString();\n" +
+ " }\n" +
+ " local.toString();\n" +
+ " if (o == null) {\n" + // don't know o's nullness, so silent
+ " o.toString();\n" + // report NPE
+ " }\n" +
+ " local.toString();\n" + // try to diffuse status for o / o2
+ " o.toString();\n" + // already reported NPE above. So silent. Same behaviour as 'local'
+ " if (o2 == null) {\n" + // report always false null check
+ " o2.toString();\n" + // dead code
+ " }\n" +
+ " o2.toString();" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 14)\n" +
+ " if (local == null) {\n" +
+ " ^^^^^\n" +
+ "Redundant null check: The variable local can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 15)\n" +
+ " local.toString();\n" +
+ " ^^^^^\n" +
+ "Null pointer access: The variable local can only be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 19)\n" +
+ " o.toString();\n" +
+ " ^\n" +
+ "Null pointer access: The field o can only be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 23)\n" +
+ " if (o2 == null) {\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o2 cannot be null at this location\n" +
+ "----------\n" +
+ "5. WARNING in X.java (at line 23)\n" +
+ " if (o2 == null) {\n" +
+ " o2.toString();\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// check if the resetting works properly i.e. null status for constant fields should not be
+// reset on method calls. This test is for constructors
+public void testBug247564b_6_2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "Object field0, \n" +
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61, field62, field63, field64, \n" +
+ "field65, field66, field67, field68, \n" +
+ "field69, field70, field71, field72, \n" +
+ "field73, field74, field75, field76, \n" +
+ "field77, field78, field79, field80, \n" +
+ "field81, field82, field83, field84, \n" +
+ "field85, field86, field87, field88, \n" +
+ "field89, field90, field91, field92, \n" +
+ "field93, field94, field95, field96, \n" +
+ "field97, field98, field99;\n" +
+ " static final Object o;\n" +
+ " static final Object o1 = new Object();\n" +
+ " static final Object o2 = new Object();\n" +
+ " static {\n" +
+ " if (o1.hashCode() == 2){\n" +
+ " o = new Object();\n" +
+ " } else {\n" +
+ " o = null;\n" +
+ " }\n" +
+ " }\n" +
+ " public X() {\n" +
+ " final Object local = null;\n" +
+ " if (local == null) {\n" +
+ " local.toString();\n" +
+ " }\n" +
+ " local.toString();\n" +
+ " if (o == null) {\n" + // don't know o's nullness, so silent
+ " o.toString();\n" + // report NPE
+ " }\n" +
+ " local.toString();\n" + // try to diffuse status for o / o2
+ " o.toString();\n" + // already reported NPE above. So silent. Same behaviour as 'local'
+ " if (o2 == null) {\n" + // report always false null check
+ " o2.toString();\n" + // dead code
+ " }\n" +
+ " o2.toString();" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 40)\n" +
+ " if (local == null) {\n" +
+ " ^^^^^\n" +
+ "Redundant null check: The variable local can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 41)\n" +
+ " local.toString();\n" +
+ " ^^^^^\n" +
+ "Null pointer access: The variable local can only be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 45)\n" +
+ " o.toString();\n" +
+ " ^\n" +
+ "Null pointer access: The field o can only be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 49)\n" +
+ " if (o2 == null) {\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o2 cannot be null at this location\n" +
+ "----------\n" +
+ "5. WARNING in X.java (at line 49)\n" +
+ " if (o2 == null) {\n" +
+ " o2.toString();\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// check if the resetting works properly i.e. null status for constant fields should not be
+// reset on method calls. Also, null info of constant field from static block is available in methods
+public void testBug247564b_7() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static final Object o;\n" +
+ " static final Object o1 = null;\n" +
+ " static final Object o2 = new Object();\n" +
+ " static {\n" +
+ " if (o1.hashCode() == 2){\n" + // report NPE. But dereferenced here, so later it should be treated as non null
+ " o = new Object();\n" +
+ " } else {\n" +
+ " o = null;\n" +
+ " }\n" +
+ " }\n" +
+ " void foo1() {\n" +
+ " final Object local = null;\n" +
+ " if (local == null) {\n" +
+ " local.toString();\n" +
+ " }\n" +
+ " local.toString();\n" +
+ " if (o1 == null) {\n" + // can't be null, was dereferenced in static initializer
+ " o1.toString();\n" + // dead
+ " }\n" +
+ " local.toString();\n" + // try to diffuse status for o1 / o2
+ " o1.toString();\n" + // safe
+ " if (o2 == null) {\n" + // report always false null check
+ " o2.toString();\n" + // dead code
+ " }\n" +
+ " o2.toString();" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " if (o1.hashCode() == 2){\n" +
+ " ^^\n" +
+ "Null pointer access: The field o1 can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 14)\n" +
+ " if (local == null) {\n" +
+ " ^^^^^\n" +
+ "Redundant null check: The variable local can only be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 15)\n" +
+ " local.toString();\n" +
+ " ^^^^^\n" +
+ "Null pointer access: The variable local can only be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 18)\n" +
+ " if (o1 == null) {\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o1 cannot be null at this location\n" +
+ "----------\n" +
+ "5. WARNING in X.java (at line 18)\n" +
+ " if (o1 == null) {\n" +
+ " o1.toString();\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "6. ERROR in X.java (at line 23)\n" +
+ " if (o2 == null) {\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o2 cannot be null at this location\n" +
+ "----------\n" +
+ "7. WARNING in X.java (at line 23)\n" +
+ " if (o2 == null) {\n" +
+ " o2.toString();\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// check if the resetting works properly i.e. null status for constant fields should not be
+// reset on method calls. This test is for more than 64 fields to check for extra bits.
+public void testBug247564b_8() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ false,
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "Object field0, \n" +
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61, field62, field63, field64, \n" +
+ "field65, field66, field67, field68, \n" +
+ "field69, field70, field71, field72, \n" +
+ "field73, field74, field75, field76, \n" +
+ "field77, field78, field79, field80, \n" +
+ "field81, field82, field83, field84, \n" +
+ "field85, field86, field87, field88, \n" +
+ "field89, field90, field91, field92, \n" +
+ "field93, field94, field95, field96, \n" +
+ "field97, field98, field99;\n" +
+ "static final Object o1 = null;\n" +
+ "static final Object o2 = new Object();\n" +
+ " void foo1() {\n" +
+ " final Object local = null;\n" +
+ " if (local == null) {\n" +
+ " local.toString();\n" +
+ " }\n" +
+ " local.toString();\n" +
+ " if (o1 == null) {\n" + // report redundant null check
+ " o1.toString();\n" + // report NPE
+ " }\n" +
+ " local.toString();\n" + // try to diffuse status for o1 / o2
+ " o1.toString();\n" + // already reported NPE above. So silent. Same behaviour as 'local'
+ " if (o2 == null) {\n" + // report always false null check
+ " o2.toString();\n" + // dead code
+ " }\n" +
+ " o2.toString();" +
+ " }\n" +
+ "}\n"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 32)\n" +
+ " if (local == null) {\n" +
+ " ^^^^^\n" +
+ "Redundant null check: The variable local can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 33)\n" +
+ " local.toString();\n" +
+ " ^^^^^\n" +
+ "Null pointer access: The variable local can only be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 36)\n" +
+ " if (o1 == null) {\n" +
+ " ^^\n" +
+ "Redundant null check: The field o1 can only be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 37)\n" +
+ " o1.toString();\n" +
+ " ^^\n" +
+ "Null pointer access: The field o1 can only be null at this location\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 41)\n" +
+ " if (o2 == null) {\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o2 cannot be null at this location\n" +
+ "----------\n" +
+ "6. WARNING in X.java (at line 41)\n" +
+ " if (o2 == null) {\n" +
+ " o2.toString();\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+
+// null analysis -- case for static final field initialized inside static block where some locals are also present
+// check if the resetting works properly
+public void testBug247564b_9() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ false,
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static final Object o1;\n" +
+ " static final Object o2 = new Object();\n" +
+ " static {\n" +
+ " int i = 10;\n" +
+ " o1 = null;\n" +
+ " }\n" +
+ " void foo1() {\n" +
+ " final Object local = null;\n" +
+ " if (local == null) {\n" +
+ " local.toString();\n" +
+ " }\n" +
+ " local.toString();\n" +
+ " if (o1 == null) {\n" + // report redundant null check
+ " o1.toString();\n" + // report NPE
+ " }\n" +
+ " local.toString();\n" + // try to diffuse status for o1 / o2
+ " o1.toString();\n" + // already reported NPE above. So silent. Same behaviour as 'local'
+ " if (o2 == null) {\n" + // report always false null check
+ " o2.toString();\n" + // dead code
+ " }\n" +
+ " o2.toString();" +
+ " }\n" +
+ "}\n"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " if (local == null) {\n" +
+ " ^^^^^\n" +
+ "Redundant null check: The variable local can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 11)\n" +
+ " local.toString();\n" +
+ " ^^^^^\n" +
+ "Null pointer access: The variable local can only be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 14)\n" +
+ " if (o1 == null) {\n" +
+ " ^^\n" +
+ "Redundant null check: The field o1 can only be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 15)\n" +
+ " o1.toString();\n" +
+ " ^^\n" +
+ "Null pointer access: The field o1 can only be null at this location\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 19)\n" +
+ " if (o2 == null) {\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o2 cannot be null at this location\n" +
+ "----------\n" +
+ "6. WARNING in X.java (at line 19)\n" +
+ " if (o2 == null) {\n" +
+ " o2.toString();\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// check if the resetting works properly i.e. null status for constant fields should not be
+// reset on method calls.
+// Boundary condition: field <boundary> constant local
+public void testBug247564b_10() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ false,
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "Object field0, \n" +
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61, field62, field63;\n" +
+ "static final Object static64 = null;\n" +
+ " void foo1(Object local65) {\n" +
+ " if (field63 == null) {\n" +
+ " field63.toString(); // report NPE\n" +
+ " }\n" +
+ " if (static64 == null) { // redundant\n" +
+ " static64.toString(); // report NPE\n" +
+ " }\n" +
+ " if (local65 == null) {\n" +
+ " local65.toString(); // report NPE\n" +
+ " }\n" +
+ " if (field63 == null) {\n" +
+ " this.toString();\n" +
+ " field63.toString();\n" + // wiped by method call
+ " }\n" +
+ " if (static64 == null) { // always false\n" + // because we're past static64.toString()
+ " this.toString(); // dead\n" +
+ " static64.toString();\n" +
+ " }\n" +
+ " if (local65 == null) { // alwayws false\n" + // because we're past local65.toString()
+ " this.toString(); // dead\n" +
+ " local65.toString();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 22)\n" +
+ " field63.toString(); // report NPE\n" +
+ " ^^^^^^^\n" +
+ "Potential null pointer access: The field field63 may be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 24)\n" +
+ " if (static64 == null) { // redundant\n" +
+ " ^^^^^^^^\n" +
+ "Redundant null check: The field static64 can only be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 25)\n" +
+ " static64.toString(); // report NPE\n" +
+ " ^^^^^^^^\n" +
+ "Null pointer access: The field static64 can only be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 28)\n" +
+ " local65.toString(); // report NPE\n" +
+ " ^^^^^^^\n" +
+ "Null pointer access: The variable local65 can only be null at this location\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 34)\n" +
+ " if (static64 == null) { // always false\n" +
+ " ^^^^^^^^\n" +
+ "Null comparison always yields false: The field static64 cannot be null at this location\n" +
+ "----------\n" +
+ "6. WARNING in X.java (at line 34)\n" +
+ " if (static64 == null) { // always false\n" +
+ " this.toString(); // dead\n" +
+ " static64.toString();\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "7. ERROR in X.java (at line 38)\n" +
+ " if (local65 == null) { // alwayws false\n" +
+ " ^^^^^^^\n" +
+ "Null comparison always yields false: The variable local65 cannot be null at this location\n" +
+ "----------\n" +
+ "8. WARNING in X.java (at line 38)\n" +
+ " if (local65 == null) { // alwayws false\n" +
+ " this.toString(); // dead\n" +
+ " local65.toString();\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// check if the resetting works properly i.e. null status for constant fields should not be
+// reset on method calls.
+// Boundary condition: constant field <boundary> local
+public void testBug247564b_11() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ false,
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "Object field0, \n" +
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61;\n" +
+ "static final Object static62 = null;\n" +
+ "Object field63;" +
+ " void foo1(Object local64) {\n" +
+ " if (static62 == null) { // redundant\n" +
+ " static62.toString(); // report NPE\n" +
+ " }\n" +
+ " if (field63 == null) {\n" +
+ " field63.toString(); // report NPE\n" +
+ " }\n" +
+ " if (local64 == null) {\n" +
+ " local64.toString(); // report NPE\n" +
+ " }\n" +
+ " if (static62 == null) { // always false\n" + // because we're past static64.toString()
+ " this.toString(); // dead\n" +
+ " static62.toString();\n" +
+ " }\n" +
+ " if (field63 == null) {\n" +
+ " this.toString(); //\n" +
+ " field63.toString();\n" + // wiped by method call
+ " }\n" +
+ " if (local64 == null) { // alwayws false\n" + // because we're past local64.toString()
+ " this.toString(); // dead\n" +
+ " local64.toString();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 21)\n" +
+ " if (static62 == null) { // redundant\n" +
+ " ^^^^^^^^\n" +
+ "Redundant null check: The field static62 can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 22)\n" +
+ " static62.toString(); // report NPE\n" +
+ " ^^^^^^^^\n" +
+ "Null pointer access: The field static62 can only be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 25)\n" +
+ " field63.toString(); // report NPE\n" +
+ " ^^^^^^^\n" +
+ "Potential null pointer access: The field field63 may be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 28)\n" +
+ " local64.toString(); // report NPE\n" +
+ " ^^^^^^^\n" +
+ "Null pointer access: The variable local64 can only be null at this location\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 30)\n" +
+ " if (static62 == null) { // always false\n" +
+ " ^^^^^^^^\n" +
+ "Null comparison always yields false: The field static62 cannot be null at this location\n" +
+ "----------\n" +
+ "6. WARNING in X.java (at line 30)\n" +
+ " if (static62 == null) { // always false\n" +
+ " this.toString(); // dead\n" +
+ " static62.toString();\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "7. ERROR in X.java (at line 38)\n" +
+ " if (local64 == null) { // alwayws false\n" +
+ " ^^^^^^^\n" +
+ "Null comparison always yields false: The variable local64 cannot be null at this location\n" +
+ "----------\n" +
+ "8. WARNING in X.java (at line 38)\n" +
+ " if (local64 == null) { // alwayws false\n" +
+ " this.toString(); // dead\n" +
+ " local64.toString();\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+
+// null analysis -- fields in synchronized methods
+// check that null analysis for fields in synchronized methods
+// behave as it does in ordinary methods.
+public void testBug247564c() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " Object o;\n" +
+ " Object o1;\n" +
+ " static final Object o2 = null;\n" +
+ " static final Object o3 = new Object();\n" +
+ " synchronized void foo() {\n" +
+ " o = null;\n" +
+ " if (o == null) {\n" +
+ " o.toString();\n" +
+ " }\n" +
+ " o1 = new Object();\n" +
+ " if (o1 == null) {\n" +
+ " o1.toString();\n" +
+ " }\n" +
+ " if (o2 != null) {\n" +
+ " }\n" +
+ " else {\n" +
+ " o2.toString();\n" +
+ " }\n" +
+ " if (o3 == null) {\n" +
+ " }\n" +
+ " else {\n" +
+ " o3.toString();\n" +
+ " }\n" +
+ " }\n" +
+ " void foo1() {\n" +
+ " o.toString();\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 13)\n" +
+ " o1.toString();\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o1 may be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 15)\n" +
+ " if (o2 != null) {\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o2 can only be null at this location\n" +
+ "----------\n" +
+ "4. WARNING in X.java (at line 15)\n" +
+ " if (o2 != null) {\n" +
+ " }\n" +
+ " ^^^^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 18)\n" +
+ " o2.toString();\n" +
+ " ^^\n" +
+ "Null pointer access: The field o2 can only be null at this location\n" +
+ "----------\n" +
+ "6. ERROR in X.java (at line 20)\n" +
+ " if (o3 == null) {\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o3 cannot be null at this location\n" +
+ "----------\n" +
+ "7. WARNING in X.java (at line 20)\n" +
+ " if (o3 == null) {\n" +
+ " }\n" +
+ " ^^^^^\n" +
+ "Dead code\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- fields in synchronized methods
+// check that null analysis for fields in synchronized methods
+// behave as it does in ordinary methods. Higher no. of fields
+public void testBug247564c_2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " Object o;\n" +
+ " Object o1;\n" +
+ "Object field0, \n" +
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61, field62, field63, field64, \n" +
+ "field65, field66, field67, field68, \n" +
+ "field69, field70, field71, field72, \n" +
+ "field73, field74, field75, field76, \n" +
+ "field77, field78, field79, field80, \n" +
+ "field81, field82, field83, field84, \n" +
+ "field85, field86, field87, field88, \n" +
+ "field89, field90, field91, field92, \n" +
+ "field93, field94, field95, field96, \n" +
+ "field97, field98, field99;\n" +
+ " static final Object o2 = null;\n" +
+ " static final Object o3 = new Object();\n" +
+ " synchronized void foo() {\n" +
+ " o = null;\n" +
+ " if (o == null) {\n" +
+ " o.toString();\n" +
+ " }\n" +
+ " o1 = new Object();\n" +
+ " if (o1 == null) {\n" +
+ " o1.toString();\n" +
+ " }\n" +
+ " if (o2 != null) {\n" +
+ " }\n" +
+ " else {\n" +
+ " o2.toString();\n" +
+ " }\n" +
+ " if (o3 == null) {\n" +
+ " }\n" +
+ " else {\n" +
+ " o3.toString();\n" +
+ " }\n" +
+ " }\n" +
+ " void foo1() {\n" +
+ " o.toString();\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 35)\n" +
+ " o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 39)\n" +
+ " o1.toString();\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o1 may be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 41)\n" +
+ " if (o2 != null) {\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o2 can only be null at this location\n" +
+ "----------\n" +
+ "4. WARNING in X.java (at line 41)\n" +
+ " if (o2 != null) {\n" +
+ " }\n" +
+ " ^^^^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 44)\n" +
+ " o2.toString();\n" +
+ " ^^\n" +
+ "Null pointer access: The field o2 can only be null at this location\n" +
+ "----------\n" +
+ "6. ERROR in X.java (at line 46)\n" +
+ " if (o3 == null) {\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The field o3 cannot be null at this location\n" +
+ "----------\n" +
+ "7. WARNING in X.java (at line 46)\n" +
+ " if (o3 == null) {\n" +
+ " }\n" +
+ " ^^^^^\n" +
+ "Dead code\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- test redundant instanceof warning for static final field
+public void testBug247564d() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static final Object o = null;\n" +
+ " static final Object o1 = new Object();\n" +
+ " void foo() {\n" +
+ " if (o instanceof String) {}\n" +
+ " if (o1 instanceof String) {}\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " if (o instanceof String) {}\n" +
+ " ^\n" +
+ "instanceof always yields false: The field o can only be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- test redundant instanceof warning for static final field. More fields
+public void testBug247564d_1() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "Object field0, \n" +
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61, field62, field63, field64, \n" +
+ "field65, field66, field67, field68, \n" +
+ "field69, field70, field71, field72, \n" +
+ "field73, field74, field75, field76, \n" +
+ "field77, field78, field79, field80, \n" +
+ "field81, field82, field83, field84, \n" +
+ "field85, field86, field87, field88, \n" +
+ "field89, field90, field91, field92, \n" +
+ "field93, field94, field95, field96, \n" +
+ "field97, field98, field99;\n" +
+ " static final Object o = null;\n" +
+ " static final Object o1 = new Object();\n" +
+ " void foo() {\n" +
+ " if (o instanceof String) {}\n" +
+ " if (o1 instanceof String) {}\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 31)\n" +
+ " if (o instanceof String) {}\n" +
+ " ^\n" +
+ "instanceof always yields false: The field o can only be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- test potential null ptr access warning because of static field access through object returned by method call
+public void testBug247564f() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ false,
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static Object o;\n" +
+ " static Object o1;\n" +
+ " Object o2;\n" +
+ " X getX() { return new X();\n}\n" +
+ " void foo() {\n" +
+ " if (getX().o == null && this.o.hashCode() == 0) return;\n" +
+ " if (getX().o2 == null && this.o2.hashCode() == 0) return;\n" +
+ " }\n" +
+ "}"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " if (getX().o == null && this.o.hashCode() == 0) return;\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+
+// null analysis -- test potential null ptr access warning because of static field access through object returned by method call
+public void testBug247564f_1() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ false,
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static Object o;\n" +
+ " X getX() { return new X();\n}\n" +
+ " Y getY() { return new Y();\n}\n" +
+ " void foo() {\n" +
+ " if (getY().o == null && this.o.hashCode() == 0) return;\n" +
+ " if (getX().o == null && this.o.hashCode() == 0) return;\n" +
+ " }\n" +
+ "}\n" +
+ "class Y{\n" +
+ " static Object o;\n" +
+ "}\n"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " if (getX().o == null && this.o.hashCode() == 0) return;\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o may be null at this location\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+
+// null analysis -- test field analysis in case of more than 64 fields
+public void testBug247564g() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ false,
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "Object field0, \n" +
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61, field62, field63, field64, \n" +
+ "field65, field66, field67, field68, \n" +
+ "field69, field70, field71, field72, \n" +
+ "field73, field74, field75, field76, \n" +
+ "field77, field78, field79, field80, \n" +
+ "field81, field82, field83, field84, \n" +
+ "field85, field86, field87, field88, \n" +
+ "field89, field90, field91, field92, \n" +
+ "field93, field94, field95, field96, \n" +
+ "field97, field98, field99;\n" +
+ "static final Object field100 = null;\n" +
+ " void foo() {\n" +
+ " int i = 0;" +
+ " while (i<10){\n" +
+ " i++;\n" +
+ " if (this.field99 == null && this.field99.hashCode() == 0){}\n" +
+ " this.field98 = null;\n" +
+ " }\n" +
+ " if (this.field98.hashCode() == 0) {}\n" +
+ " this.field97 = null;\n" +
+ " if (this.field97.hashCode() == 0) {}\n" +
+ " if (this.field100.hashCode() == 0) {}\n" +
+ " }\n" +
+ "}"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 32)\n" +
+ " if (this.field99 == null && this.field99.hashCode() == 0){}\n" +
+ " ^^^^^^^\n" +
+ "Potential null pointer access: The field field99 may be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 35)\n" +
+ " if (this.field98.hashCode() == 0) {}\n" +
+ " ^^^^^^^\n" +
+ "Potential null pointer access: The field field98 may be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 37)\n" +
+ " if (this.field97.hashCode() == 0) {}\n" +
+ " ^^^^^^^\n" +
+ "Potential null pointer access: The field field97 may be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 38)\n" +
+ " if (this.field100.hashCode() == 0) {}\n" +
+ " ^^^^^^^^\n" +
+ "Null pointer access: The field field100 can only be null at this location\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+
+// null analysis -- simple case for field for inner class
+// to make sure field id's of inner and outer classes are not same for flow analysis
+public void testBug247564h() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " Object o;\n" +
+ " class X1 {\n" +
+ " Object x;" +
+ " Object x1;" +
+ " Object x2;" +
+ " void goo() {\n" +
+ " if (o == null && x.toString() == \"\"){}\n" +
+ " if (o2 == null && o2.toString() == \"\"){}\n" +
+ " if (o2 == null && x2.toString() == \"\"){}\n" +
+ " }\n" +
+
+ " }\n" +
+ " Object o1;\n" +
+ " static Object o2;\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " if (o2 == null && o2.toString() == \"\"){}\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o2 may be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- simple case for field for inner class
+// to make sure that id's of local variables in inner classes don't conflict with those of fields.
+public void testBug247564h_1() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " Object field0;\n" +
+ " Object field1;\n" +
+ " class X1 {\n" +
+ " Object field2;" +
+ " Object field3;" +
+ " void goo(Object var) {\n" +
+ " if (var == null && field2.toString() == \"\"){}\n" +
+ " if (var == null && field3.toString() == \"\"){}\n" +
+ " if (field2 == null && field2.toString() == \"\"){}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " if (field2 == null && field2.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field2 may be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- simple case for field for inner class
+// to make sure that id's of local variables in inner classes don't conflict with those of fields.
+public void testBug247564h_2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " Object field0;\n" +
+ " Object field1;\n" +
+ " class X1 {\n" +
+ " Object field2;\n" +
+ " Object field3;\n" +
+ " class X2 {\n" +
+ " Object field4;\n" +
+ " Object field5;\n" +
+ " void goo(Object var) {\n" +
+ " if (var == null && field4.toString() == \"\"){}\n" +
+ " if (var == null && field5.toString() == \"\"){}\n" +
+ " if (field3 == null && field3.toString() == \"\"){}\n" +
+ " if (field3 == null && field1.toString() == \"\"){}\n" +
+ " }\n" +
+ " }\n" +
+ " Object field22;\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 13)\n" +
+ " if (field3 == null && field3.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field3 may be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- simple case for static fields
+// to make sure that static field only of the current type is assigned potentially null when compared against null
+// Static fields belonging to any other class should be ignored
+// Qualified access to static fields should also work
+public void testBug247564i_1() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ true,
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static Object field0;\n" +
+ " static Object field1;\n" +
+ " Y getY(){ return new Y();}\n" +
+ " X getX() { return new X();}\n" +
+ " void goo(Object var) {\n" +
+ " if (Y.yField1 == null && field0.toString() == \"\"){}\n" + // no warn
+ " if (Y.yField1 == null && this.field0.toString() == \"\"){}\n" + // no warn
+ " if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" + // warn, qualified access
+ " if (Y.yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (Y.xiny.field1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (X.field0 == null && X.field0.toString() == \"\"){}\n" + // warn
+ " if (this.field0 == null && X.field0.toString() == \"\"){}\n" + // warn
+ " if (X.field0 == null && this.field0.toString() == \"\"){}\n" + // warn
+ " if (X.field0 == null && getX().field0.toString() == \"\"){}\n" + // no warn (diffused by getX() call)
+ " }\n" +
+ "}\n" +
+ "class Y{\n" +
+ " Y getY(){ return new Y();}\n" +
+ " X getX(){ return new X();}\n" +
+ " static Object yField1;" +
+ " static X xiny;\n" +
+ "}"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 12)\n" +
+ " if (X.field0 == null && X.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 13)\n" +
+ " if (this.field0 == null && X.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 14)\n" +
+ " if (X.field0 == null && this.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+ );
+}
+
+// null analysis -- static fields accessed via MessageSend
+// to make sure that static field only of the current type is assigned potentially null when compared against null
+// Static fields belonging to any other class should be ignored
+// Qualified access to static fields should also work
+public void testBug247564i_2() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ true,
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static Object field0;\n" +
+ " static Object field1;\n" +
+ " Y getY(){ return new Y();}\n" +
+ " X getX() { return new X();}\n" +
+ " void goo(Object var) {\n" +
+ " if (new Y().getY().yField1 == null && field0.toString() == \"\"){}\n" + // no warn
+ " if (getY().yField1 == null && field0.toString() == \"\"){}\n" + // no warn
+ " if (getY().yField1 == null && this.field0.toString() == \"\"){}\n" + // no warn
+ " if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && field0.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && this.field0.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && getX().field0.toString() == \"\"){}\n" + // no warn, getX() wipes out null info
+ " if (getX().field0 == null && X.field0.toString() == \"\"){}\n" + // warn, qualified access
+ // fields from other types, don't warn
+ " if (new Y().getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (getX().field0 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " }\n" +
+ "}\n" +
+ "class Y{\n" +
+ " Y getY(){ return new Y();}\n" +
+ " X getX(){ return new X();}\n" +
+ " static Object yField1;\n" +
+ "}"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 11)\n" +
+ " if (getX().field0 == null && field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 12)\n" +
+ " if (getX().field0 == null && this.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 14)\n" +
+ " if (getX().field0 == null && X.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+ );
+}
+
+// null analysis -- static fields accessed from Member type
+// Qualified access to static fields should also work
+public void testBug247564i_3() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ true,
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static Object field0;\n" +
+ " static Object field1;\n" +
+ " static Y getY(){ return new Y();}\n" +
+ " static X getX() { return new X();}\n" +
+ " static class XInner{\n" +
+ " static Object xinnerfield;\n" +
+ " XInner getXInner() { return new XInner();\n}" +
+ " void goo(Object var) {\n" +
+ " if (new Y().getY().yField1 == null && field0.toString() == \"\"){}\n" + // no warn
+ " if (getY().yField1 == null && field0.toString() == \"\"){}\n" + // no warn
+ " if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && field0.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && getX().field0.toString() == \"\"){}\n" + // no warn, getX() wipes out null info
+ " if (getX().field0 == null && X.field0.toString() == \"\"){}\n" + // warn, qualified access
+ " if (getXInner().xinnerfield == null && xinnerfield.toString() == \"\"){}\n" + // warn
+ " if (getXInner().xinnerfield == null && this.xinnerfield.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && this.xinnerfield.toString() == \"\"){}\n" + // no warn
+ " if (getXInner().xinnerfield == null && field0.toString() == \"\"){}\n" + // no warn
+ // fields from other types, don't warn
+ " if (new Y().getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (getX().field0 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ // qualified accesses
+ " if (Y.yField1 == null && field0.toString() == \"\"){}\n" + // no warn
+ " if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" + // warn, qualified access
+ " if (Y.yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (Y.xiny.field1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (X.field0 == null && X.field0.toString() == \"\"){}\n" + // warn
+ " if (X.field0 == null && getX().field0.toString() == \"\"){}\n" + // no warn
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "class Y{\n" +
+ " Y getY(){ return new Y();}\n" +
+ " X getX(){ return new X();}\n" +
+ " static Object yField1;\n" +
+ " static X xiny;\n" +
+ "}"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 12)\n" +
+ " if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 13)\n" +
+ " if (getX().field0 == null && field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 15)\n" +
+ " if (getX().field0 == null && X.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 16)\n" +
+ " if (getXInner().xinnerfield == null && xinnerfield.toString() == \"\"){}\n" +
+ " ^^^^^^^^^^^\n" +
+ "Potential null pointer access: The field xinnerfield may be null at this location\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 17)\n" +
+ " if (getXInner().xinnerfield == null && this.xinnerfield.toString() == \"\"){}\n" +
+ " ^^^^^^^^^^^\n" +
+ "Potential null pointer access: The field xinnerfield may be null at this location\n" +
+ "----------\n" +
+ "6. ERROR in X.java (at line 24)\n" +
+ " if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "7. ERROR in X.java (at line 27)\n" +
+ " if (X.field0 == null && X.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+ );
+}
+
+// null analysis -- static fields accessed from a local type
+// Qualified access to static fields should also work
+public void testBug247564i_4() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ true,
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " static Object field0;\n" +
+ " static Object field1;\n" +
+ " Y getY(){ return new Y();}\n" +
+ " X getX() { return new X();}\n" +
+ " void goo(Object var) {\n" +
+ " class Local{\n" +
+ " void localfoo(){\n " +
+ " if (new Y().getY().yField1 == null && field0.toString() == \"\"){}\n" + // no warn
+ " if (getY().yField1 == null && field0.toString() == \"\"){}\n" + // no warn
+ " if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && field0.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && getX().field0.toString() == \"\"){}\n" + // no warn, getX() wipes out null info
+ " if (getX().field0 == null && X.field0.toString() == \"\"){}\n" + // warn, qualified access
+ // fields from other types, don't warn
+ " if (new Y().getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (getX().field0 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ // qualified accesses
+ " if (Y.yField1 == null && field0.toString() == \"\"){}\n" + // no warn
+ " if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" + // warn, qualified access
+ " if (Y.yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (Y.xiny.field1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (X.field0 == null && X.field0.toString() == \"\"){}\n" + // warn
+ " if (X.field0 == null && getX().field0.toString() == \"\"){}\n" + // no warn
+ " }\n" +
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "class Y{\n" +
+ " Y getY(){ return new Y();}\n" +
+ " X getX(){ return new X();}\n" +
+ " static Object yField1;\n" +
+ " static X xiny;\n" +
+ "}"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. WARNING in X.java (at line 7)\n" +
+ " class Local{\n" +
+ " ^^^^^\n" +
+ "The type Local is never used locally\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 8)\n" +
+ " void localfoo(){\n" +
+ " ^^^^^^^^^^\n" +
+ "The method localfoo() from the type Local is never used locally\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 11)\n" +
+ " if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 12)\n" +
+ " if (getX().field0 == null && field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 14)\n" +
+ " if (getX().field0 == null && X.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "6. ERROR in X.java (at line 19)\n" +
+ " if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "7. ERROR in X.java (at line 22)\n" +
+ " if (X.field0 == null && X.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+ );
+}
+
+// null analysis -- static fields from an anonymous type
+// Qualified access to static fields should also work
+public void testBug247564i_5() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ true,
+ new String[] {
+ "X.java",
+ "interface Anon{}\n" +
+ "public class X {\n" +
+ " static Object field0;\n" +
+ " static Object field1;\n" +
+ " Y getY(){ return new Y();}\n" +
+ " X getX() { return new X();}\n" +
+ " void goo(Object var) {\n" +
+ " new Anon(){\n" +
+ " void localfoo(){\n " +
+ " if (new Y().getY().yField1 == null && field0.toString() == \"\"){}\n" + // no warn
+ " if (getY().yField1 == null && field0.toString() == \"\"){}\n" + // no warn
+ " if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && field0.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && getX().field0.toString() == \"\"){}\n" + // no warn, getX() wipes out null info
+ " if (getX().field0 == null && X.field0.toString() == \"\"){}\n" + // warn, qualified access
+ // fields from other types, don't warn
+ " if (new Y().getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (getX().field0 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ // qualified accesses
+ " if (Y.yField1 == null && field0.toString() == \"\"){}\n" + // no warn
+ " if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" + // warn, qualified access
+ " if (Y.yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (Y.xiny.field1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (X.field0 == null && X.field0.toString() == \"\"){}\n" + // warn
+ " if (X.field0 == null && getX().field0.toString() == \"\"){}\n" + // no warn
+ " }\n" +
+ " };\n" +
+ " }\n" +
+ "}\n" +
+ "class Y{\n" +
+ " Y getY(){ return new Y();}\n" +
+ " X getX(){ return new X();}\n" +
+ " static Object yField1;\n" +
+ " static X xiny;\n" +
+ "}"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. WARNING in X.java (at line 9)\n" +
+ " void localfoo(){\n" +
+ " ^^^^^^^^^^\n" +
+ "The method localfoo() from the type new Anon(){} is never used locally\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 12)\n" +
+ " if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 13)\n" +
+ " if (getX().field0 == null && field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 15)\n" +
+ " if (getX().field0 == null && X.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 20)\n" +
+ " if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "6. ERROR in X.java (at line 23)\n" +
+ " if (X.field0 == null && X.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+ );
+}
+// null analysis -- static fields
+// to check static field access from fieldReference and QualifiedReference when the type is parameterized
+public void testBug247564i_6() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return;
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ true,
+ new String[] {
+ "X.java",
+ "public class X<T> {\n" +
+ " static Object field0;\n" +
+ " static Object field1;\n" +
+ " Y getY(){ return new Y();}\n" +
+ " X getX() { return new X();}\n" +
+ " void goo(Object var) {\n" +
+ " if (new Y().getY().yField1 == null && X.field0.toString() == \"\"){}\n" + // no warn
+ " if (getY().yField1 == null && X.field0.toString() == \"\"){}\n" + // no warn
+ " if (getY().yField1 == null && this.field0.toString() == \"\"){}\n" + // no warn
+ " if (new Y().getX().field0 == null && X.field0.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && X.field0.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && this.field0.toString() == \"\"){}\n" + // warn
+ " if (getX().field0 == null && getX().field0.toString() == \"\"){}\n" + // no warn, getX() wipes out null info
+ // fields from other types, don't warn
+ " if (new Y().getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " if (getX().field0 == null && Y.yField1.toString() == \"\"){}\n" + // no warn
+ " }\n" +
+ "}\n" +
+ "class Y<K>{\n" +
+ " Y getY(){ return new Y();}\n" +
+ " X getX(){ return new X();}\n" +
+ " static Object yField1;\n" +
+ "}"},
+ null,
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " if (new Y().getX().field0 == null && X.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 11)\n" +
+ " if (getX().field0 == null && X.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 12)\n" +
+ " if (getX().field0 == null && this.field0.toString() == \"\"){}\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: The field field0 may be null at this location\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+ );
+}
+//null analysis -- simple case for field of parent type
+public void testBug247564j() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X extends Y {\n" +
+ " private Object fieldx;\n" +
+ " void goo(Object var) {\n" +
+ " if (fieldx == null && fieldy.toString() == \"\"){}\n" + // don't flag fieldy, nothing known
+ " }\n" +
+ "}\n" +
+ "class Y{\n" +
+ " protected Object fieldy = null;\n" +
+ "}\n" +
+ ""},
+ ""
+ );
+}
+
+// null analysis -- simple case for field in try-finally
+public void testBug247564k() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " private Object f;\n" +
+ " void goo(Object var) {\n" +
+ " try {\n" +
+ " int i = 10;\n" +
+ " while (i<20){\n" +
+ " if (i == 15) {\n" +
+ " f = null;\n" +
+ " break;\n" +
+ " }\n" +
+ " i++;\n" +
+ " }\n" +
+ " return;\n" +
+ " } finally {\n" +
+ " if (f != null && f.hashCode() == 0){}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"},
+ ""
+ );
+}
+
+// null analysis -- simple case for field in try-finally
+// presence or absence of throw should not affect the behaviour
+public void testBug247564k_1() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " private Object f;\n" +
+ " void goo(Object var) throws Exception{\n" +
+ " try {\n" +
+ " int i = 10;\n" +
+ " } catch(Exception e) {\n" +
+ " f = null;\n" +
+ " throw e;\n" +
+ " } finally {\n" +
+ " if (f != null && f.hashCode() == 0){}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"},
+ ""
+ );
+}
+
+// null analysis -- simple case for field in try-finally
+// presence or absence of method call in finally should not affect the behaviour
+public void testBug247564k_2() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " private Object f;\n" +
+ " void gooCalls(){}\n" +
+ " void goo(Object var) throws Exception{\n" +
+ " try {\n" +
+ " if (f != null) {}\n" +
+ " } finally {\n" +
+ " if (f != null ) {\n" +
+ " gooCalls();\n" +
+ " f.toString();\n" +
+ " }\n" + // silent
+ " }\n" +
+ " }\n" +
+ "}\n"},
+ ""
+ );
+}
+
+// null analysis -- simple case for constant field in try-catch-finally
+// presence or absence of method call in finally should not affect the behaviour
+public void testBug247564k_3() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " private static final Object f = null;\n" +
+ " void gooCalls() throws NumberFormatException{}\n" +
+ " void goo(Object var) throws Exception{\n" +
+ " try {\n" +
+ " gooCalls();\n" +
+ " } catch(NumberFormatException e) {\n" +
+ " if (f.hashCode() == 0){}\n" +
+ " } finally {\n" +
+ " gooCalls();\n" +
+ " if (f.hashCode() == 0){}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " if (f.hashCode() == 0){}\n" +
+ " ^\n" +
+ "Null pointer access: The field f can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 11)\n" +
+ " if (f.hashCode() == 0){}\n" +
+ " ^\n" +
+ "Null pointer access: The field f can only be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- potentially redundant checks against the same field
+public void testBug247564l_1() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " private Object f;\n" +
+ " int foo() throws Exception{\n" +
+ " if (f == null && f != null)\n" +
+ " return 13;\n" +
+ " return -13;\n" +
+ " }\n" +
+ " int goo() throws Exception{\n" +
+ " if (f == null && f == null)\n" +
+ " return 14;\n" +
+ " return -14;\n" +
+ " }\n" +
+ " boolean hoo() throws Exception{\n" +
+ " if (f == null)\n" +
+ " return f != null;\n" +
+ " return f == null;\n" +
+ " }\n" +
+ "}\n"},
+ ""
+ );
+}
+
+// null analysis -- fields assigned a def. non null value in a loop
+// comment 121
+public void testBug247564l_2() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " private Object field;\n" +
+ " void foo() throws Exception{\n" +
+ " if (field != null) field.hashCode();\n" +
+ " int i = 10;\n" +
+ " while (i<20) {\n" +
+ " if (field == null) field = new Object();\n" +
+ " field.toString();\n" + // should not warn
+ " i++;\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"},
+ ""
+ );
+}
+
+// null analysis -- checked and unchecked exceptions
+public void testBug247564m() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "class MyException extends Exception{}\n" +
+ "public class X {\n" +
+ " private Object f;\n" +
+ " void gooCalls() throws MyException{}\n" +
+ " void goo(){\n" +
+ " try {\n" +
+ " if (f == null) return;\n" +
+ " gooCalls();\n" +
+ " } catch(MyException e) {\n" + // checked Exception
+ " f.toString();\n" + // silent - at gooCalls() in 'try', f is not going to be null
+ " } catch(NumberFormatException e) {\n" + // unchecked Exception
+ " f.toString();\n" + // could have come from anywhere, f can be null as doubted in 'try'
+ " }\n" +
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. WARNING in X.java (at line 1)\n" +
+ " class MyException extends Exception{}\n" +
+ " ^^^^^^^^^^^\n" +
+ "The serializable class MyException does not declare a static final serialVersionUID field of type long\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 12)\n" +
+ " f.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field f may be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis -- check resetting of large no. of fields
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=247564#c161
+public void testBug247564n() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "Object field0, \n" +
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61, field62, field63, field64; \n" +
+ " static final Object o2 = new Object();\n" +
+ " public X() {\n" +
+ " field23 = null;\n" +
+ " o2.toString();\n" +
+ " if (field23.hashCode() == 0){}\n" + // don't warn
+ " }\n" +
+ "}\n"},
+ ""
+ );
+}
+// null analysis -- check resetting of large no. of fields
+// see also https://bugs.eclipse.org/bugs/show_bug.cgi?id=369381
+public void testBug247564n_2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "Object field0, \n" + // more than 64 fields
+ "field1, field2, field3, field4, \n" +
+ "field5, field6, field7, field8, \n" +
+ "field9, field10, field11, field12, \n" +
+ "field13, field14, field15, field16, \n" +
+ "field17, field18, field19, field20, \n" +
+ "field21, field22, field23, field24, \n" +
+ "field25, field26, field27, field28, \n" +
+ "field29, field30, field31, field32, \n" +
+ "field33, field34, field35, field36, \n" +
+ "field37, field38, field39, field40, \n" +
+ "field41, field42, field43, field44, \n" +
+ "field45, field46, field47, field48, \n" +
+ "field49, field50, field51, field52, \n" +
+ "field53, field54, field55, field56, \n" +
+ "field57, field58, field59, field60, \n" +
+ "field61, field62, field63, field64; \n" +
+ " static final Object o2 = new Object();\n" +
+ " public X() {\n" +
+ " Object l0, l1, l2, l3, l4, l5, l6, l7, l8, l9,\n" + // more than 64 locals
+ " l10, l11, l12, l13, l14, l15, l16, l17, l18, l19,\n" +
+ " l20, l21, l22, l23, l24, l25, l26, l27, l28, l29,\n" +
+ " l30, l31, l32, l33, l34, l35, l36, l37, l38, l39,\n" +
+ " l40, l41, l42, l43, l44, l45, l46, l47, l48, l49,\n" +
+ " l50, l51, l52, l53, l54, l55, l56, l57, l58, l59,\n" +
+ " l60, l61, l62, l63, l64, l65, l66, l67, l68, l69;\n" +
+ " l69 = null;\n" + // l69 has bits in extra[x][1]
+ " o2.toString();\n" + // resetNullInfoForFields() must not reset any bits in extra[x][1]
+ " l69.toString();\n" + // warn!
+ " }\n" +
+ "}\n"},
+ "----------\n" +
+ "1. ERROR in X.java (at line 30)\n" +
+ " l69.toString();\n" +
+ " ^^^\n" +
+ "Null pointer access: The variable l69 can only be null at this location\n" +
+ "----------\n"
+ );
+}
+
+// null analysis - should not throw NPE
+// see also https://bugs.eclipse.org/bugs/show_bug.cgi?id=369381
+public void testBug369381() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X extends XParent{\n" +
+ " public void foo(X x, int i) {\n" +
+ " if (this.field0.length == i){}\n" + // declaring class of 'length' is null. Dont throw NPE
+ " }\n" +
+ "}\n" +
+ "class XParent {\n" +
+ " protected Object[] field0 = {new Object()}; \n" +
+ "}\n"
+ },
+ ""
+ );
+}
+
+// null analysis -- with large no. of fields, no AIOOBE should be thrown
+// no. of static final fields less than no. of final-only fields
+public void _testBug369381a() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "static final Object field0 = null;\n " +
+ "static final Object field1 = null;\n " +
+ "static final Object field2 = null;\n " +
+ "static final Object field3 = null;\n " +
+ "static final Object field4 = null;\n " +
+ "static final Object field5 = null;\n " +
+ "static final Object field6 = null;\n " +
+ "static final Object field7 = null;\n " +
+ "static final Object field8 = null;\n " +
+ "static final Object field9 = null;\n " +
+ "static final Object field10 = null;\n" +
+ "static final Object field11 = null;\n" +
+ "static final Object field12 = null;\n" +
+ "static final Object field13 = null;\n" +
+ "static final Object field14 = null;\n" +
+ "static final Object field15 = null;\n" +
+ "static final Object field16 = null;\n" +
+ "static final Object field17 = null;\n" +
+ "static final Object field18 = null;\n" +
+ "static final Object field19 = null;\n" +
+ "static final Object field20 = null;\n" +
+ "static final Object field21 = null;\n" +
+ "static final Object field22 = null;\n" +
+ "static final Object field23 = null;\n" +
+ "static final Object field24 = null;\n" +
+ "static final Object field25 = null;\n" +
+ "static final Object field26 = null;\n" +
+ "static final Object field27 = null;\n" +
+ "static final Object field28 = null;\n" +
+ "static final Object field29 = null;\n" +
+ "static final Object field30 = null;\n" +
+ "static final Object field31 = null;\n" +
+ "static final Object field32 = null;\n" +
+ "static final Object field33 = null;\n" +
+ "static final Object field34 = null;\n" +
+ "static final Object field35 = null;\n" +
+ "static final Object field36 = null;\n" +
+ "static final Object field37 = null;\n" +
+ "static final Object field38 = null;\n" +
+ "static final Object field39 = null;\n" +
+ "static final Object field40 = null;\n" +
+ "static final Object field41 = null;\n" +
+ "static final Object field42 = null;\n" +
+ "static final Object field43 = null;\n" +
+ "static final Object field44 = null;\n" +
+ "static final Object field45 = null;\n" +
+ "static final Object field46 = null;\n" +
+ "static final Object field47 = null;\n" +
+ "static final Object field48 = null;\n" +
+ "static final Object field49 = null;\n" +
+ "static final Object field50 = null;\n" +
+ "static final Object field51 = null;\n" +
+ "static final Object field52 = null;\n" +
+ "static final Object field53 = null;\n" +
+ "static final Object field54 = null;\n" +
+ "static final Object field55 = null;\n" +
+ "static final Object field56 = null;\n" +
+ "static final Object field57 = null;\n" +
+ "static final Object field58 = null;\n" +
+ "static final Object field59 = null;\n" +
+ "static final Object field60 = null;\n" +
+ "static final Object field61 = null;\n" +
+ "static final Object field62 = null;\n" +
+ "static final Object field63 = null;\n" +
+ "static final Object field64 = null;\n" +
+ "static final Object field65 = null;\n" +
+ "static final Object field66 = null;\n" +
+ "static final Object field67 = null;\n" +
+ "static final Object field68 = null;\n" +
+ "static final Object field69 = null;\n" +
+ "final Object field00 = null; \n" +
+ "final Object field01 = null; \n" +
+ "final Object field02 = null; \n" +
+ "final Object field03 = null; \n" +
+ "final Object field04 = null; \n" +
+ "final Object field05 = null; \n" +
+ "final Object field06 = null; \n" +
+ "final Object field07 = null; \n" +
+ "final Object field08 = null; \n" +
+ "final Object field09 = null; \n" +
+ "final Object field010 = null;\n" +
+ "final Object field011 = null;\n" +
+ "final Object field012 = null;\n" +
+ "final Object field013 = null;\n" +
+ "final Object field014 = null;\n" +
+ "final Object field015 = null;\n" +
+ "final Object field016 = null;\n" +
+ "final Object field017 = null;\n" +
+ "final Object field018 = null;\n" +
+ "final Object field019 = null;\n" +
+ "final Object field020 = null;\n" +
+ "final Object field021 = null;\n" +
+ "final Object field022 = null;\n" +
+ "final Object field023 = null;\n" +
+ "final Object field024 = null;\n" +
+ "final Object field025 = null;\n" +
+ "final Object field026 = null;\n" +
+ "final Object field027 = null;\n" +
+ "final Object field028 = null;\n" +
+ "final Object field029 = null;\n" +
+ "final Object field030 = null;\n" +
+ "final Object field031 = null;\n" +
+ "final Object field032 = null;\n" +
+ "final Object field033 = null;\n" +
+ "final Object field034 = null;\n" +
+ "final Object field035 = null;\n" +
+ "final Object field036 = null;\n" +
+ "final Object field037 = null;\n" +
+ "final Object field038 = null;\n" +
+ "final Object field039 = null;\n" +
+ "final Object field040 = null;\n" +
+ "final Object field041 = null;\n" +
+ "final Object field042 = null;\n" +
+ "final Object field043 = null;\n" +
+ "final Object field044 = null;\n" +
+ "final Object field045 = null;\n" +
+ "final Object field046 = null;\n" +
+ "final Object field047 = null;\n" +
+ "final Object field048 = null;\n" +
+ "final Object field049 = null;\n" +
+ "final Object field050 = null;\n" +
+ "final Object field051 = null;\n" +
+ "final Object field052 = null;\n" +
+ "final Object field053 = null;\n" +
+ "final Object field054 = null;\n" +
+ "final Object field055 = null;\n" +
+ "final Object field056 = null;\n" +
+ "final Object field057 = null;\n" +
+ "final Object field058 = null;\n" +
+ "final Object field059 = null;\n" +
+ "final Object field060 = null;\n" +
+ "final Object field061 = null;\n" +
+ "final Object field062 = null;\n" +
+ "final Object field063 = null;\n" +
+ "final Object field064 = null;\n" +
+ "final Object field065 = null;\n" +
+ "final Object field066 = null;\n" +
+ "final Object field067 = null;\n" +
+ "final Object field068 = null;\n" +
+ "final Object field069 = null;\n" +
+ " public X() {\n" +
+ " }\n" +
+ "}\n"},
+ ""
+ );
+}
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
new file mode 100644
index 000000000..c587eaf6c
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
@@ -0,0 +1,3192 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 GK Software AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Map;
+
+import junit.framework.Test;
+
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+
+public class ResourceLeakTests extends AbstractRegressionTest {
+
+static {
+// TESTS_NAMES = new String[] { "testBug368709"};
+// TESTS_NUMBERS = new int[] { 50 };
+// TESTS_RANGE = new int[] { 11, -1 };
+}
+public ResourceLeakTests(String name) {
+ super(name);
+}
+public static Test suite() {
+ return buildAllCompliancesTestSuite(ResourceLeakTests.class);
+}
+
+void runTestsExpectingErrorsOnlyIn17(String[] testFiles, String errorsIn17, Map options) {
+ if (this.complianceLevel >= ClassFileConstants.JDK1_7)
+ runNegativeTest(testFiles, errorsIn17, null, true, options);
+ else
+ runConformTest(testFiles, "", null, true, null, options, null);
+}
+
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// a method uses an AutoCloseable without ever closing it.
+public void test056() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+// not invoking any methods on FileReader, try to avoid necessary call to superclass() in the compiler
+// " char[] in = new char[50];\n" +
+// " fileReader.read(in);\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " ^^^^^^^^^^\n" +
+ "Resource leak: 'fileReader' is never closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// a method uses an AutoCloseable and closes it but not protected by t-w-r nor regular try-finally
+public void test056a() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
+ runTestsExpectingErrorsOnlyIn17(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " fileReader.close();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " ^^^^^^^^^^\n" +
+ "Resource 'fileReader' should be managed by try-with-resource\n" +
+ "----------\n",
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// a method uses an AutoCloseable and closes it properly in a finally block
+public void test056b() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " try {\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " } finally {\n" +
+ " fileReader.close();\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String[] args) {\n" +
+ " try {\n" +
+ " new X().foo();\n" +
+ " } catch (IOException ioex) {\n" +
+ " System.out.println(\"caught\");\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "caught", /*output*/
+ null/*classLibs*/,
+ true/*shouldFlush*/,
+ null/*vmargs*/,
+ options,
+ null/*requestor*/);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// a method uses an AutoCloseable properly within try-with-resources.
+public void test056c() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // t-w-r used
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " try (FileReader fileReader = new FileReader(file)) {\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String[] args) {\n" +
+ " try {\n" +
+ " new X().foo();\n" +
+ " } catch (IOException ioex) {\n" +
+ " System.out.println(\"caught\");\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "caught", /*output*/
+ null/*classLibs*/,
+ true/*shouldFlush*/,
+ null/*vmargs*/,
+ options,
+ null/*requestor*/);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// a method uses two AutoCloseables (testing independent analysis)
+//- one closeable may be unclosed at a conditional return
+//- the other is only conditionally closed
+public void test056d() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo(boolean flag1, boolean flag2) throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " char[] in = new char[50];\n" +
+ " FileReader fileReader1 = new FileReader(file);\n" +
+ " fileReader1.read(in);\n" +
+ " FileReader fileReader2 = new FileReader(file);\n" +
+ " fileReader2.read(in);\n" +
+ " if (flag1) {\n" +
+ " fileReader2.close();\n" +
+ " return;\n" +
+ " } else if (flag2) {\n" +
+ " fileReader2.close();\n" +
+ " }\n" +
+ " fileReader1.close();\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo(false, true);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. WARNING in X.java (at line 10)\n" +
+ " FileReader fileReader2 = new FileReader(file);\n" +
+ " ^^^^^^^^^^^\n" +
+ "Potential resource leak: 'fileReader2' may not be closed\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 14)\n" +
+ " return;\n" +
+ " ^^^^^^^\n" +
+ "Resource leak: 'fileReader1' is not closed at this location\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// a method uses two AutoCloseables (testing independent analysis)
+//- one closeable may be unclosed at a conditional return
+//- the other is only conditionally closed
+public void test056d_suppress() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // annotations used
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
+ options.put(CompilerOptions.OPTION_SuppressOptionalErrors, CompilerOptions.ENABLED);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo(boolean flag1, boolean flag2) throws IOException {\n" +
+ " @SuppressWarnings(\"resource\") File file = new File(\"somefile\"); // unnecessary suppress\n" +
+ " char[] in = new char[50];\n" +
+ " FileReader fileReader1 = new FileReader(file);\n" +
+ " fileReader1.read(in);\n" +
+ " @SuppressWarnings(\"resource\") FileReader fileReader2 = new FileReader(file); // useful suppress\n" +
+ " fileReader2.read(in);\n" +
+ " if (flag1) {\n" +
+ " fileReader2.close();\n" +
+ " return; // not suppressed\n" +
+ " } else if (flag2) {\n" +
+ " fileReader2.close();\n" +
+ " }\n" +
+ " fileReader1.close();\n" +
+ " }\n" +
+ " @SuppressWarnings(\"resource\") // useful suppress\n" +
+ " void bar() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo(false, true);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. WARNING in X.java (at line 6)\n" +
+ " @SuppressWarnings(\"resource\") File file = new File(\"somefile\"); // unnecessary suppress\n" +
+ " ^^^^^^^^^^\n" +
+ "Unnecessary @SuppressWarnings(\"resource\")\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 14)\n" +
+ " return; // not suppressed\n" +
+ " ^^^^^^^\n" +
+ "Resource leak: 'fileReader1' is not closed at this location\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// Bug 362332 - Only report potential leak when closeable not created in the local scope
+// one method returns an AutoCleasble, a second method uses this object without ever closing it.
+public void test056e() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " FileReader getReader(String filename) throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " return fileReader;\n" + // don't complain here, pass responsibility to caller
+ " }\n" +
+ " void foo() throws IOException {\n" +
+ " FileReader reader = getReader(\"somefile\");\n" +
+ " char[] in = new char[50];\n" +
+ " reader.read(in);\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 11)\n" +
+ " FileReader reader = getReader(\"somefile\");\n" +
+ " ^^^^^^\n" +
+ "Potential resource leak: \'reader\' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// a method explicitly closes its AutoCloseable rather than using t-w-r
+public void test056f() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
+ options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
+ runTestsExpectingErrorsOnlyIn17(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader fileReader = null;\n" +
+ " try {\n" +
+ " fileReader = new FileReader(file);\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " } finally {\n" +
+ " fileReader.close();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " FileReader fileReader = null;\n" +
+ " ^^^^^^^^^^\n" +
+ "Resource 'fileReader' should be managed by try-with-resource\n" +
+ "----------\n",
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// an AutoCloseable local is re-assigned
+public void test056g() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " fileReader = new FileReader(file);\n" +
+ " fileReader.read(in);\n" +
+ " fileReader.close();\n" +
+ " fileReader = null;\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " fileReader = new FileReader(file);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: 'fileReader' is not closed at this location\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// an AutoCloseable local is re-assigned after null-assigned
+public void test056g2() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " fileReader = null;\n" +
+ " fileReader = new FileReader(file);\n" + // don't complain again, fileReader is null, so nothing can leak here
+ " fileReader.read(in);\n" +
+ " fileReader.close();\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " fileReader = null;\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: 'fileReader' is not closed at this location\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// two AutoCloseables at different nesting levels (anonymous local type)
+public void test056h() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " final File file = new File(\"somefile\");\n" +
+ " final FileReader fileReader = new FileReader(file);\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " new Runnable() {\n public void run() {\n" +
+ " try {\n" +
+ " fileReader.close();\n" +
+ " FileReader localReader = new FileReader(file);\n" +
+ " } catch (IOException ex) { /* nop */ }\n" +
+ " }}.run();\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. WARNING in X.java (at line 7)\n" +
+ " final FileReader fileReader = new FileReader(file);\n" +
+ " ^^^^^^^^^^\n" +
+ "Potential resource leak: 'fileReader' may not be closed\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 14)\n" +
+ " FileReader localReader = new FileReader(file);\n" +
+ " ^^^^^^^^^^^\n" +
+ "Resource leak: 'localReader' is never closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// three AutoCloseables in different blocks of the same method
+public void test056i() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo(boolean f1, boolean f2) throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " if (f1) {\n" +
+ " FileReader fileReader = new FileReader(file); // err: not closed\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " while (true) {\n" +
+ " FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" +
+ " loopReader.close();" +
+ " break;\n" +
+ " }\n" +
+ " } else {\n" +
+ " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
+ " if (f2)\n" +
+ " fileReader.close();\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo(true, true);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " FileReader fileReader = new FileReader(file); // err: not closed\n" +
+ " ^^^^^^^^^^\n" +
+ "Resource leak: 'fileReader' is never closed\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 16)\n" +
+ " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
+ " ^^^^^^^^^^\n" +
+ "Potential resource leak: 'fileReader' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// three AutoCloseables in different blocks of the same method - problems ignored
+public void test056i_ignore() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.IGNORE);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.IGNORE);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo(boolean f1, boolean f2) throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " if (f1) {\n" +
+ " FileReader fileReader = new FileReader(file); // err: not closed\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " while (true) {\n" +
+ " FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" +
+ " loopReader.close();" +
+ " break;\n" +
+ " }\n" +
+ " } else {\n" +
+ " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
+ " if (f2)\n" +
+ " fileReader.close();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// three AutoCloseables in different blocks of the same method
+public void test056i2() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo(boolean f1, boolean f2) throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " if (f1) {\n" +
+ " FileReader fileReader = new FileReader(file); // properly closed\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " while (true) {\n" +
+ " fileReader.close();\n" +
+ " FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" +
+ " loopReader.close();\n" +
+ " break;\n" +
+ " }\n" +
+ " } else {\n" +
+ " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
+ " if (f2)\n" +
+ " fileReader.close();\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo(true, true);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 18)\n" +
+ " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
+ " ^^^^^^^^^^\n" +
+ "Potential resource leak: 'fileReader' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// a method uses an AutoCloseable without closing it locally but passing as arg to another method
+public void test056j() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " read(fileReader);\n" +
+ " }\n" +
+ " void read(FileReader reader) { }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " ^^^^^^^^^^\n" +
+ "Potential resource leak: 'fileReader' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// a method uses an AutoCloseable without closing it locally but passing as arg to another method
+public void test056jconditional() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo(boolean b) throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " synchronized (b ? this : new X()) {\n" +
+ " new ReadDelegator(fileReader);\n" +
+ " }\n" +
+ " }\n" +
+ " class ReadDelegator { ReadDelegator(FileReader reader) { } }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo(true);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " ^^^^^^^^^^\n" +
+ "Potential resource leak: 'fileReader' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// many locals, some are AutoCloseable.
+// Unfortunately analysis cannot respect how exception exits may affect ra3 and rb3,
+// doing so would create false positives.
+public void test056k() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
+ options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
+ String expectedProblems = this.complianceLevel < ClassFileConstants.JDK1_7 ?
+ "----------\n" +
+ "1. ERROR in X.java (at line 15)\n" +
+ " ra2 = new FileReader(file);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'ra2\' is never closed\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 28)\n" +
+ " rb2 = new FileReader(file);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'rb2\' is never closed\n" +
+ "----------\n"
+ :
+ "----------\n" +
+ "1. ERROR in X.java (at line 12)\n" +
+ " FileReader ra1 = null, ra2 = null;\n" +
+ " ^^^\n" +
+ "Resource 'ra1' should be managed by try-with-resource\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 15)\n" +
+ " ra2 = new FileReader(file);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: 'ra2' is never closed\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 16)\n" +
+ " FileReader ra3 = new FileReader(file);\n" +
+ " ^^^\n" +
+ "Resource 'ra3' should be managed by try-with-resource\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 25)\n" +
+ " FileReader rb1 = null, rb2 = null;\n" +
+ " ^^^\n" +
+ "Resource 'rb1' should be managed by try-with-resource\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 28)\n" +
+ " rb2 = new FileReader(file);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: 'rb2' is never closed\n" +
+ "----------\n" +
+ "6. ERROR in X.java (at line 29)\n" +
+ " FileReader rb3 = new FileReader(file);\n" +
+ " ^^^\n" +
+ "Resource 'rb3' should be managed by try-with-resource\n" +
+ "----------\n";
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " int i01, i02, i03, i04, i05, i06, i07, i08, i09,\n" +
+ " i11, i12, i13, i14, i15, i16, i17, i18, i19,\n" +
+ " i21, i22, i23, i24, i25, i26, i27, i28, i29,\n" +
+ " i31, i32, i33, i34, i35, i36, i37, i38, i39,\n" +
+ " i41, i42, i43, i44, i45, i46, i47, i48, i49;\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader ra1 = null, ra2 = null;\n" +
+ " try {\n" +
+ " ra1 = new FileReader(file);\n" +
+ " ra2 = new FileReader(file);\n" +
+ " FileReader ra3 = new FileReader(file);\n" +
+ " char[] in = new char[50];\n" +
+ " ra1.read(in);\n" +
+ " ra2.read(in);\n" +
+ " ra3.close();\n" +
+ " } finally {\n" +
+ " ra1.close();\n" +
+ " }\n" +
+ " int i51, i52, i53, i54, i55, i56, i57, i58, i59, i60;\n" + // beyond this point locals are analyzed using extraBits
+ " FileReader rb1 = null, rb2 = null;\n" +
+ " try {\n" +
+ " rb1 = new FileReader(file);\n" +
+ " rb2 = new FileReader(file);\n" +
+ " FileReader rb3 = new FileReader(file);\n" +
+ " char[] in = new char[50];\n" +
+ " rb1.read(in);\n" +
+ " rb2.read(in);\n" +
+ " rb3.close();\n" +
+ " } finally {\n" +
+ " rb1.close();\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ expectedProblems,
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// various non-problems
+public void test056l() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
+ String expectedProblems = this.complianceLevel >= ClassFileConstants.JDK1_7 ?
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " FileReader fileReader = getReader();\n" +
+ " ^^^^^^^^^^\n" +
+ "Resource 'fileReader' should be managed by try-with-resource\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 11)\n" +
+ " FileReader r3 = getReader();\n" +
+ " ^^\n" +
+ "Resource 'r3' should be managed by try-with-resource\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 24)\n" +
+ " FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" +
+ " ^^\n" +
+ "Potential resource leak: 'r2' may not be closed\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 25)\n" +
+ " new X(r2).foo(new FileReader(new File(\"notthere\"))); // potential problem: foo may/may not close the new FileReader\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value>\' may not be closed\n" +
+ "----------\n"
+ :
+ "----------\n" +
+ "1. ERROR in X.java (at line 24)\n" +
+ " FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" +
+ " ^^\n" +
+ "Potential resource leak: 'r2' may not be closed\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 25)\n" +
+ " new X(r2).foo(new FileReader(new File(\"notthere\"))); // potential problem: foo may/may not close the new FileReader\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value>\' may not be closed\n" +
+ "----------\n";
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " X(FileReader r0) {}\n" + // don't complain against argument
+ " FileReader getReader() { return null; }\n" +
+ " void foo(FileReader r1) throws IOException {\n" +
+ " FileReader fileReader = getReader();\n" +
+ " if (fileReader == null)\n" +
+ " return;\n" + // don't complain, resource is actually null
+ " FileReader r3 = getReader();\n" +
+ " if (r3 == null)\n" +
+ " r3 = new FileReader(new File(\"absent\"));\n" + // don't complain, previous resource is actually null
+ " try {\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " r1.read(in);\n" +
+ " } finally {\n" +
+ " fileReader.close();\n" +
+ " r3.close();\n" + // the effect of this close() call might be spoiled by exception in fileReader.close() above, but we ignore exception exits in the analysis
+ " }\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" +
+ " new X(r2).foo(new FileReader(new File(\"notthere\"))); // potential problem: foo may/may not close the new FileReader\n" +
+ " }\n" +
+ "}\n"
+ },
+ expectedProblems,
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// nested try with early exit
+public void test056m() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() {\n" +
+ " File file = new File(\"somefile\");" +
+ " try {\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " try {\n" +
+ " char[] in = new char[50];\n" +
+ " if (fileReader.read(in)==0)\n" +
+ " return;\n" +
+ " } finally {\n" +
+ " fileReader.close();\n" +
+ " }\n" +
+ " } catch (IOException e) {\n" +
+ " System.out.println(\"caught\");\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String[] args) {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "caught", /*output*/
+ null/*classLibs*/,
+ true/*shouldFlush*/,
+ null/*vmargs*/,
+ options,
+ null/*requestor*/);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// nested try should not interfere with earlier analysis.
+public void test056n() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "import java.io.FileNotFoundException;\n" +
+ "public class X {\n" +
+ " void foo(File someFile, char[] buf) throws IOException {\n" +
+ " FileReader fr1 = new FileReader(someFile);\n" +
+ " try {\n" +
+ " fr1.read(buf);\n" +
+ " } finally {\n" +
+ " fr1.close();\n" +
+ " }\n" +
+ " try {\n" +
+ " FileReader fr3 = new FileReader(someFile);\n" +
+ " try {\n" +
+ " } finally {\n" +
+ " fr3.close();\n" +
+ " }\n" +
+ " } catch (IOException e) {\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " try {\n" +
+ " new X().foo(new File(\"missing\"), new char[100]);\n" +
+ " } catch (FileNotFoundException e) {\n" +
+ " System.out.println(\"caught\");\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "caught", /*output*/
+ null/*classLibs*/,
+ true/*shouldFlush*/,
+ null/*vmargs*/,
+ options,
+ null/*requestor*/);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// if close is guarded by null check this should still be recognized as definitely closed
+public void test056o() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "import java.io.FileNotFoundException;\n" +
+ "public class X {\n" +
+ " void foo(File someFile, char[] buf) throws IOException {\n" +
+ " FileReader fr1 = null;\n" +
+ " try {\n" +
+ " fr1 = new FileReader(someFile);" +
+ " fr1.read(buf);\n" +
+ " } finally {\n" +
+ " if (fr1 != null)\n" +
+ " try {\n" +
+ " fr1.close();\n" +
+ " } catch (IOException e) { /*do nothing*/ }\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " try {\n" +
+ " new X().foo(new File(\"missing\"), new char[100]);\n" +
+ " } catch (FileNotFoundException e) {\n" +
+ " System.out.println(\"caught\");\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "caught", /*output*/
+ null/*classLibs*/,
+ true/*shouldFlush*/,
+ null/*vmargs*/,
+ options,
+ null/*requestor*/);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// Bug 362332 - Only report potential leak when closeable not created in the local scope
+// a method uses an AutoCloseable without ever closing it, type from a type variable
+public void test056p() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // generics used
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.Reader;\n" +
+ "import java.io.IOException;\n" +
+ "public abstract class X <T extends Reader> {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " T fileReader = newReader(file);\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " }\n" +
+ " abstract T newReader(File file) throws IOException;\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X<FileReader>() {\n" +
+ " FileReader newReader(File f) throws IOException { return new FileReader(f); }\n" +
+ " }.foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " T fileReader = newReader(file);\n" +
+ " ^^^^^^^^^^\n" +
+ "Potential resource leak: \'fileReader\' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// closed in dead code
+public void test056q() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " if (2*2 == 4)\n" +
+ " return;\n" +
+ " fileReader.close();\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " FileReader fileReader = new FileReader(file);\n" +
+ " ^^^^^^^^^^\n" +
+ "Resource leak: 'fileReader' is never closed\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 10)\n" +
+ " if (2*2 == 4)\n" +
+ " ^^^^^^^^\n" +
+ "Comparing identical expressions\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 12)\n" +
+ " fileReader.close();\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// properly closed, dead code in between
+public void test056r() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileReader fr = new FileReader(file);\n" +
+ " Object b = null;\n" +
+ " fr.close();\n" +
+ " if (b != null) {\n" +
+ " fr = new FileReader(file);\n" +
+ " return;\n" +
+ " } else {\n" +
+ " System.out.print(42);\n" +
+ " }\n" +
+ " return; // Should not complain about fr\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " if (b != null) {\n" +
+ " fr = new FileReader(file);\n" +
+ " return;\n" +
+ " } else {\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 13)\n" +
+ " } else {\n" +
+ " System.out.print(42);\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Statement unnecessarily nested within else clause. The corresponding then clause does not complete normally\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// resource inside t-w-r is re-assigned, shouldn't even record an errorLocation
+public void test056s() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // t-w-r used
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " try (FileReader fileReader = new FileReader(file);) {\n" +
+ " char[] in = new char[50];\n" +
+ " fileReader.read(in);\n" +
+ " fileReader = new FileReader(file); // debug here\n" +
+ " fileReader.read(in);\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " fileReader = new FileReader(file); // debug here\n" +
+ " ^^^^^^^^^^\n" +
+ "The resource fileReader of a try-with-resources statement cannot be assigned\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// resource is closed, dead code follows
+public void test056t() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo31() throws IOException {\n" +
+ " FileReader reader = new FileReader(\"file\"); //warning\n" +
+ " if (reader != null) {\n" +
+ " reader.close();\n" +
+ " } else {\n" +
+ " // nop\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo31();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " } else {\n" +
+ " // nop\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// resource is reassigned within t-w-r with different resource
+// was initially broken due to https://bugs.eclipse.org/358827
+public void test056u() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // t-w-r used
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " void foo() throws Exception {\n" +
+ " FileReader reader1 = new FileReader(\"file1\");\n" +
+ " FileReader reader2 = new FileReader(\"file2\");\n" +
+ " reader2 = reader1;// this disconnects reader 2\n" +
+ " try (FileReader reader3 = new FileReader(\"file3\")) {\n" +
+ " int ch;\n" +
+ " while ((ch = reader2.read()) != -1) {\n" +
+ " System.out.println(ch);\n" +
+ " reader1.read();\n" +
+ " }\n" +
+ " reader2 = reader1; // warning 1 regarding original reader1\n" + // this warning was missing
+ " reader2 = reader1; // warning 2 regarding original reader1\n" +
+ " } finally {\n" +
+ " if (reader2 != null) {\n" +
+ " reader2.close();\n" +
+ " } else {\n" +
+ " System.out.println();\n" +
+ " }\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " FileReader reader2 = new FileReader(\"file2\");\n" +
+ " ^^^^^^^\n" +
+ "Resource leak: 'reader2' is never closed\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 13)\n" +
+ " reader2 = reader1; // warning 1 regarding original reader1\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: 'reader1' is not closed at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 14)\n" +
+ " reader2 = reader1; // warning 2 regarding original reader1\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: 'reader1' is not closed at this location\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// scope-related pbs reported in https://bugs.eclipse.org/349326#c70 and https://bugs.eclipse.org/349326#c82
+public void test056v() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ String expectedProblems = this.complianceLevel >= ClassFileConstants.JDK1_7 ?
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " FileReader reader = new FileReader(\"file\");\n" +
+ " ^^^^^^\n" +
+ "Resource leak: 'reader' is never closed\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 19)\n" +
+ " FileReader reader111 = new FileReader(\"file2\");\n" +
+ " ^^^^^^^^^\n" +
+ "Resource 'reader111' should be managed by try-with-resource\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 42)\n" +
+ " return;\n" +
+ " ^^^^^^^\n" +
+ "Resource leak: 'reader2' is not closed at this location\n" +
+ "----------\n"
+ :
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " FileReader reader = new FileReader(\"file\");\n" +
+ " ^^^^^^\n" +
+ "Resource leak: 'reader' is never closed\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 42)\n" +
+ " return;\n" +
+ " ^^^^^^^\n" +
+ "Resource leak: 'reader2' is not closed at this location\n" +
+ "----------\n";
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " boolean foo1() throws Exception {\n" +
+ " FileReader reader = new FileReader(\"file\");\n" +
+ " try {\n" +
+ " int ch;\n" +
+ " while ((ch = reader.read()) != -1) {\n" +
+ " System.out.println(ch);\n" +
+ " reader.read();\n" +
+ " }\n" +
+ " if (ch > 10) {\n" +
+ " return true;\n" +
+ " }\n" +
+ " return false;\n" + // return while resource from enclosing scope remains unclosed
+ " } finally {\n" +
+ " }\n" +
+ " }\n" +
+ " void foo111() throws Exception {\n" +
+ " FileReader reader111 = new FileReader(\"file2\");\n" +
+ " try {\n" +
+ " int ch;\n" +
+ " while ((ch = reader111.read()) != -1) {\n" +
+ " System.out.println(ch);\n" +
+ " reader111.read();\n" +
+ " }\n" +
+ " return;\n" + // this shouldn't spoil the warning "should be managed with t-w-r"
+ " } finally {\n" +
+ " if (reader111 != null) {\n" +
+ " reader111.close();\n" +
+ " }\n" +
+ " }\n" +
+ " }\n" +
+ " void foo2() throws Exception {\n" +
+ " FileReader reader2 = new FileReader(\"file\");\n" +
+ " try {\n" +
+ " int ch;\n" +
+ " while ((ch = reader2.read()) != -1) {\n" +
+ " System.out.println(ch);\n" +
+ " reader2.read();\n" +
+ " }\n" +
+ " if (ch > 10) {\n" +
+ " return;\n" + // potential leak
+ " }\n" +
+ " } finally {\n" +
+ " }\n" +
+ " reader2.close();\n" + // due to this close we don't say "never closed"
+ " }\n" +
+ "}\n"
+ },
+ expectedProblems,
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// end of method is dead end, but before we have both a close() and an early return
+public void test056w() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " boolean foo1() throws Exception {\n" +
+ " FileReader reader = new FileReader(\"file\");\n" +
+ " try {\n" +
+ " int ch;\n" +
+ " while ((ch = reader.read()) != -1) {\n" +
+ " System.out.println(ch);\n" +
+ " reader.read();\n" +
+ " }\n" +
+ " if (ch > 10) {\n" +
+ " reader.close();\n" +
+ " return true;\n" +
+ " }\n" +
+ " return false;\n" +
+ " } finally {\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 15)\n" +
+ " return false;\n" +
+ " ^^^^^^^^^^^^^\n" +
+ "Resource leak: 'reader' is not closed at this location\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// different early exits, if no close seen report as definitely unclosed
+public void test056x() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " void foo31(boolean b) throws Exception {\n" +
+ " FileReader reader = new FileReader(\"file\");\n" +
+ " if (b) {\n" +
+ " reader.close();\n" +
+ " } else {\n" +
+ " return; // warning\n" +
+ " }\n" +
+ " }\n" +
+ " void foo32(boolean b) throws Exception {\n" +
+ " FileReader reader = new FileReader(\"file\"); // warn here\n" +
+ " return;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " return; // warning\n" +
+ " ^^^^^^^\n" +
+ "Resource leak: 'reader' is not closed at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 12)\n" +
+ " FileReader reader = new FileReader(\"file\"); // warn here\n" +
+ " ^^^^^^\n" +
+ "Resource leak: 'reader' is never closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// nested method passes the resource to outside code
+public void test056y() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " void foo31(boolean b) throws Exception {\n" +
+ " final FileReader reader31 = new FileReader(\"file\");\n" +
+ " new Runnable() {\n" +
+ " public void run() {\n" +
+ " foo18(reader31);\n" +
+ " }\n" +
+ " }.run();\n" +
+ " }\n" +
+ " void foo18(FileReader r18) {\n" +
+ " // could theoretically close r18;\n" +
+ " }\n" +
+ " abstract class ResourceProvider {\n" +
+ " abstract FileReader provide();" +
+ " }\n" +
+ " ResourceProvider provider;" +
+ " void foo23() throws Exception {\n" +
+ " final FileReader reader23 = new FileReader(\"file\");\n" +
+ " provider = new ResourceProvider() {\n" +
+ " public FileReader provide() {\n" +
+ " return reader23;\n" +
+ " }\n" +
+ " };\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. WARNING in X.java (at line 4)\n" +
+ " final FileReader reader31 = new FileReader(\"file\");\n" +
+ " ^^^^^^^^\n" +
+ "Potential resource leak: 'reader31' may not be closed\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 17)\n" +
+ " final FileReader reader23 = new FileReader(\"file\");\n" +
+ " ^^^^^^^^\n" +
+ "Potential resource leak: 'reader23' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// resource assigned to second local and is (potentially) closed on the latter
+public void test056z() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " void foo17() throws Exception {\n" +
+ " FileReader reader17 = new FileReader(\"file\");\n" +
+ " final FileReader readerCopy = reader17;\n" +
+ " readerCopy.close();\n" +
+ " }\n" +
+ " void foo17a() throws Exception {\n" +
+ " FileReader reader17a = new FileReader(\"file\");\n" +
+ " FileReader readerCopya;" +
+ " readerCopya = reader17a;\n" +
+ " bar(readerCopya);\n" + // potentially closes
+ " }\n" +
+ " void bar(FileReader r) {}\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " FileReader reader17a = new FileReader(\"file\");\n" +
+ " ^^^^^^^^^\n" +
+ "Potential resource leak: 'reader17a' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// multiple early exists from nested scopes (always closed)
+public void test056zz() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ runTestsExpectingErrorsOnlyIn17(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " void foo16() throws Exception {\n" +
+ " FileReader reader16 = new FileReader(\"file\");\n" +
+ " try {\n" +
+ " reader16.close();\n " +
+ " return;\n" +
+ " } catch (RuntimeException re) {\n" +
+ " return;\n" +
+ " } catch (Error e) {\n" +
+ " return;\n" +
+ " } finally {\n" +
+ " reader16.close();\n " +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " FileReader reader16 = new FileReader(\"file\");\n" +
+ " ^^^^^^^^\n" +
+ "Resource 'reader16' should be managed by try-with-resource\n" +
+ "----------\n",
+ options);
+}
+// Bug 349326 - [1.7] new warning for missing try-with-resources
+// multiple early exists from nested scopes (never closed)
+public void test056zzz() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " void foo16() throws Exception {\n" +
+ " FileReader reader16 = new FileReader(\"file\");\n" +
+ " try {\n" +
+ " return;\n" +
+ " } catch (RuntimeException re) {\n" +
+ " return;\n" +
+ " } catch (Error e) {\n" +
+ " return;\n" +
+ " } finally {\n" +
+ " System.out.println();\n " +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " FileReader reader16 = new FileReader(\"file\");\n" +
+ " ^^^^^^^^\n" +
+ "Resource leak: 'reader16' is never closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
+// explicit throw is a true method exit here
+public void test056throw1() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " void foo2(boolean a, boolean b, boolean c) throws Exception {\n" +
+ " FileReader reader = new FileReader(\"file\");\n" +
+ " if(a)\n" +
+ " throw new Exception(); //warning 1\n" +
+ " else if (b)\n" +
+ " reader.close();\n" +
+ " else if(c)\n" +
+ " throw new Exception(); //warning 2\n" +
+ " reader.close();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " throw new Exception(); //warning 1\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: 'reader' is not closed at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 10)\n" +
+ " throw new Exception(); //warning 2\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: 'reader' is not closed at this location\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
+// close() within finally provides protection for throw
+public void test056throw2() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ runTestsExpectingErrorsOnlyIn17(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " void foo1() throws Exception {\n" +
+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
+ " try {\n" +
+ " reader.read();\n" +
+ " return;\n" +
+ " } catch (Exception e) {\n" +
+ " throw new Exception();\n" +
+ " } finally {\n" +
+ " reader.close();\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " void foo2() throws Exception {\n" +
+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
+ " try {\n" +
+ " reader.read();\n" +
+ " throw new Exception(); // should not warn here\n" +
+ " } catch (Exception e) {\n" +
+ " throw new Exception();\n" +
+ " } finally {\n" +
+ " reader.close();\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " void foo3() throws Exception {\n" +
+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
+ " try {\n" +
+ " reader.read();\n" +
+ " throw new Exception();\n" +
+ " } finally {\n" +
+ " reader.close();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
+ " ^^^^^^\n" +
+ "Resource 'reader' should be managed by try-with-resource\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 16)\n" +
+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
+ " ^^^^^^\n" +
+ "Resource 'reader' should be managed by try-with-resource\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 28)\n" +
+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
+ " ^^^^^^\n" +
+ "Resource 'reader' should be managed by try-with-resource\n" +
+ "----------\n",
+ options);
+}
+// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
+// close() nested within finally provides protection for throw
+public void test056throw3() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ runTestsExpectingErrorsOnlyIn17(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " void foo2x() throws Exception {\n" +
+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
+ " try {\n" +
+ " reader.read();\n" +
+ " throw new Exception(); // should not warn here\n" +
+ " } catch (Exception e) {\n" +
+ " throw new Exception();\n" +
+ " } finally {\n" +
+ " if (reader != null)\n" +
+ " try {\n" +
+ " reader.close();\n" +
+ " } catch (java.io.IOException io) {}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
+ " ^^^^^^\n" +
+ "Resource 'reader' should be managed by try-with-resource\n" +
+ "----------\n",
+ options);
+}
+// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
+// additional boolean should shed doubt on whether we reach the close() call
+public void test056throw4() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " void foo2x(boolean b) throws Exception {\n" +
+ " FileReader reader = new FileReader(\"file\");\n" +
+ " try {\n" +
+ " reader.read();\n" +
+ " throw new Exception(); // should warn here\n" +
+ " } catch (Exception e) {\n" +
+ " throw new Exception(); // should warn here\n" +
+ " } finally {\n" +
+ " if (reader != null && b)\n" + // this condition is too strong to protect reader
+ " try {\n" +
+ " reader.close();\n" +
+ " } catch (java.io.IOException io) {}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " throw new Exception(); // should warn here\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: 'reader' may not be closed at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 9)\n" +
+ " throw new Exception(); // should warn here\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: 'reader' may not be closed at this location\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
+// similar to test056throw3() but indirectly calling close(), so doubts remain.
+public void test056throw5() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileReader;\n" +
+ "public class X {\n" +
+ " void foo2x() throws Exception {\n" +
+ " FileReader reader = new FileReader(\"file\");\n" +
+ " try {\n" +
+ " reader.read();\n" +
+ " throw new Exception(); // should warn 'may not' here\n" +
+ " } catch (Exception e) {\n" +
+ " throw new Exception(); // should warn 'may not' here\n" +
+ " } finally {\n" +
+ " doClose(reader);\n" +
+ " }\n" +
+ " }\n" +
+ " void doClose(FileReader r) { try { r.close(); } catch (java.io.IOException ex) {}}\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " throw new Exception(); // should warn \'may not\' here\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: 'reader' may not be closed at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 9)\n" +
+ " throw new Exception(); // should warn \'may not\' here\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: 'reader' may not be closed at this location\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
+// a resource wrapper is not closed but the underlying resource is
+public void test061a() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileInputStream fileStream = new FileInputStream(file);\n" +
+ " BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
+ " System.out.println(bis.available());\n" +
+ " fileStream.close();\n" +
+ " }\n" +
+ " void inline() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileInputStream fileStream;\n" +
+ " BufferedInputStream bis = new BufferedInputStream(fileStream = new FileInputStream(file));\n" +
+ " System.out.println(bis.available());\n" +
+ " fileStream.close();\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " try {\n" +
+ " new X().foo();\n" +
+ " } catch (IOException ex) {" +
+ " System.out.println(\"Got IO Exception\");\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "Got IO Exception",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// a closeable without OS resource is not closed
+public void test061b() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.StringReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " StringReader string = new StringReader(\"content\");\n" +
+ " System.out.println(string.read());\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "99", // character 'c'
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// a resource wrapper is not closed but the underlying closeable is resource-free
+public void test061c() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.BufferedReader;\n" +
+ "import java.io.StringReader;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " StringReader input = new StringReader(\"content\");\n" +
+ " BufferedReader br = new BufferedReader(input);\n" +
+ " BufferedReader doubleWrap = new BufferedReader(br);\n" +
+ " System.out.println(br.read());\n" +
+ " }\n" +
+ " void inline() throws IOException {\n" +
+ " BufferedReader br = new BufferedReader(new StringReader(\"content\"));\n" +
+ " System.out.println(br.read());\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " new X().foo();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "99",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// a resource wrapper is not closed neither is the underlying resource
+public void test061d() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileInputStream fileStream = new FileInputStream(file);\n" +
+ " BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
+ " System.out.println(bis.available());\n" +
+ " }\n" +
+ " void inline() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(file));\n" +
+ " System.out.println(bis2.available());\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " try {\n" +
+ " new X().foo();\n" +
+ " } catch (IOException ex) {" +
+ " System.out.println(\"Got IO Exception\");\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
+ " ^^^^^^^^^^\n" +
+ "Resource leak: \'doubleWrap\' is never closed\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 15)\n" +
+ " BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(file));\n" +
+ " ^^^^\n" +
+ "Resource leak: \'bis2\' is never closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
+// a resource wrapper is closed closing also the underlying resource
+public void test061e() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " FileInputStream fis;" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileInputStream fileStream = new FileInputStream(file);\n" +
+ " BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
+ " System.out.println(bis.available());\n" +
+ " bis.close();\n" +
+ " }\n" +
+ " void inline() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " BufferedInputStream bis2 = new BufferedInputStream(fis = new FileInputStream(file));\n" + // field assignment
+ " System.out.println(bis2.available());\n" +
+ " bis2.close();\n" +
+ " FileInputStream fileStream = null;\n" +
+ " BufferedInputStream bis3 = new BufferedInputStream(fileStream = new FileInputStream(file));\n" +
+ " System.out.println(bis3.available());\n" +
+ " bis3.close();\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " try {\n" +
+ " new X().foo();\n" +
+ " } catch (IOException ex) {" +
+ " System.out.println(\"Got IO Exception\");\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "Got IO Exception",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
+// a resource wrapper is closed closing also the underlying resource - original test case
+public void test061f() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ URL url = FileLocator.toFileURL(FileLocator.find(Platform.getBundle("org.eclipse.jdt.core.tests.compiler"), new Path("META-INF/MANIFEST.MF"), null));
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.InputStream;\n" +
+ "import java.io.InputStreamReader;\n" +
+ "import java.io.BufferedReader;\n" +
+ "import java.io.IOException;\n" +
+ "import java.net.URL;\n" +
+ "public class X {\n" +
+ " boolean loadURL(final URL url) throws IOException {\n" +
+ " InputStream stream = null;\n" +
+ " BufferedReader reader = null;\n" +
+ " try {\n" +
+ " stream = url.openStream();\n" +
+ " reader = new BufferedReader(new InputStreamReader(stream));\n" +
+ " System.out.println(reader.readLine());\n" +
+ " } finally {\n" +
+ " try {\n" +
+ " if (reader != null)\n" +
+ " reader.close();\n" +
+ " } catch (IOException x) {\n" +
+ " }\n" +
+ " }\n" +
+ " return false; // 'stream' may not be closed at this location\n" +
+ " }\n" +
+ " public static void main(String[] args) throws IOException {\n" +
+ " try {\n" +
+ " new X().loadURL(new URL(\""+url.toString()+"\"));\n" +
+ " } catch (IOException ex) {\n" +
+ " System.out.println(\"Got IO Exception\"+ex);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "Manifest-Version: 1.0",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
+// a resource wrapper is closed closing also the underlying resource - from a real-world example
+public void test061f2() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.OutputStream;\n" +
+ "import java.io.FileOutputStream;\n" +
+ "import java.io.BufferedOutputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void zork() throws IOException {\n" +
+ " try {\n" +
+ " OutputStream os = null;\n" +
+ " try {\n" +
+ " os = new BufferedOutputStream(new FileOutputStream(\"somefile\"));\n" +
+ " String externalForm = \"externalPath\";\n" +
+ " } finally {\n" +
+ " if (os != null)\n" +
+ " os.close();\n" +
+ " }\n" +
+ " } catch (IOException e) {\n" +
+ " e.printStackTrace();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
+// a resource wrapper is sent to another method affecting also the underlying resource - from a real-world example
+public void test061f3() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.FileNotFoundException;\n" +
+ "import java.io.InputStream;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "public class X {\n" +
+ " String loadProfile(File profileFile) {\n" +
+ " try {\n" +
+ " InputStream stream = new BufferedInputStream(new FileInputStream(profileFile));\n" +
+ " return loadProfile(stream);\n" +
+ " } catch (FileNotFoundException e) {\n" +
+ " //null\n" +
+ " }\n" +
+ " return null;\n" +
+ " }\n" +
+ " private String loadProfile(InputStream stream) {\n" +
+ " return null;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " return loadProfile(stream);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'stream\' may not be closed at this location\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
+// Different points in a resource chain are closed
+public void test061g() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void closeMiddle() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileInputStream fileStream = new FileInputStream(file);\n" +
+ " BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
+ " System.out.println(bis.available());\n" +
+ " bis.close();\n" +
+ " }\n" +
+ " void closeOuter() throws IOException {\n" +
+ " File file2 = new File(\"somefile\");\n" +
+ " FileInputStream fileStream2 = new FileInputStream(file2);\n" +
+ " BufferedInputStream bis2 = new BufferedInputStream(fileStream2);\n" +
+ " BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" +
+ " System.out.println(bis2.available());\n" +
+ " doubleWrap2.close();\n" +
+ " }\n" +
+ " void neverClosed() throws IOException {\n" +
+ " File file3 = new File(\"somefile\");\n" +
+ " FileInputStream fileStream3 = new FileInputStream(file3);\n" +
+ " BufferedInputStream bis3 = new BufferedInputStream(fileStream3);\n" +
+ " BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" +
+ " System.out.println(doubleWrap3.available());\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 26)\n" +
+ " BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" +
+ " ^^^^^^^^^^^\n" +
+ "Resource leak: \'doubleWrap3\' is never closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
+// Different points in a resource chain are potentially closed
+public void test061h() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void closeMiddle(boolean b) throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " FileInputStream fileStream = new FileInputStream(file);\n" +
+ " BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
+ " System.out.println(bis.available());\n" +
+ " if (b)\n" +
+ " bis.close();\n" +
+ " }\n" +
+ " void closeOuter(boolean b) throws IOException {\n" +
+ " File file2 = new File(\"somefile\");\n" +
+ " FileInputStream fileStream2 = new FileInputStream(file2);\n" +
+ " BufferedInputStream dummy;\n" +
+ " BufferedInputStream bis2 = (dummy = new BufferedInputStream(fileStream2));\n" +
+ " BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" +
+ " System.out.println(bis2.available());\n" +
+ " if (b)\n" +
+ " doubleWrap2.close();\n" +
+ " }\n" +
+ " void potAndDef(boolean b) throws IOException {\n" +
+ " File file3 = new File(\"somefile\");\n" +
+ " FileInputStream fileStream3 = new FileInputStream(file3);\n" +
+ " BufferedInputStream bis3 = new BufferedInputStream(fileStream3);\n" +
+ " BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" +
+ " System.out.println(doubleWrap3.available());\n" +
+ " if (b) bis3.close();\n" +
+ " fileStream3.close();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
+ " ^^^^^^^^^^\n" +
+ "Potential resource leak: \'doubleWrap\' may not be closed\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 20)\n" +
+ " BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" +
+ " ^^^^^^^^^^^\n" +
+ "Potential resource leak: \'doubleWrap2\' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// local var is re-used for two levels of wrappers
+public void test061i() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.InputStream;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void closeMiddle() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " InputStream stream = new FileInputStream(file);\n" +
+ " stream = new BufferedInputStream(stream);\n" +
+ " InputStream middle;\n" +
+ " stream = new BufferedInputStream(middle = stream);\n" +
+ " System.out.println(stream.available());\n" +
+ " middle.close();\n" +
+ " }\n" +
+ " void closeOuter() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " InputStream stream2 = new FileInputStream(file);\n" +
+ " stream2 = new BufferedInputStream(stream2);\n" +
+ " stream2 = new BufferedInputStream(stream2);\n" +
+ " System.out.println(stream2.available());\n" +
+ " stream2.close();\n" +
+ " }\n" +
+ " void neverClosed() throws IOException {\n" +
+ " File file = new File(\"somefile\");\n" +
+ " InputStream stream3 = new FileInputStream(file);\n" +
+ " stream3 = new BufferedInputStream(stream3);\n" +
+ " stream3 = new BufferedInputStream(stream3);\n" +
+ " System.out.println(stream3.available());\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 26)\n" +
+ " InputStream stream3 = new FileInputStream(file);\n" +
+ " ^^^^^^^\n" +
+ "Resource leak: \'stream3\' is never closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// self-wrapping a method argument (caused NPE UnconditionalFlowInfo.markAsDefinitelyNull(..)).
+public void test061j() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.InputStream;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo(InputStream stream) throws IOException {\n" +
+ " stream = new BufferedInputStream(stream);\n" +
+ " System.out.println(stream.available());\n" +
+ " stream.close();\n" +
+ " }\n" +
+ " void boo(InputStream stream2) throws IOException {\n" +
+ " stream2 = new BufferedInputStream(stream2);\n" +
+ " System.out.println(stream2.available());\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// a wrapper is created in a return statement
+public void test061k() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " BufferedInputStream getReader(File file) throws IOException {\n" +
+ " FileInputStream stream = new FileInputStream(file);\n" +
+ " return new BufferedInputStream(stream);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// a closeable is assigned to a field
+public void test061l() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " BufferedInputStream stream;\n" +
+ " void foo(File file) throws IOException {\n" +
+ " FileInputStream s = new FileInputStream(file);\n" +
+ " stream = new BufferedInputStream(s);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 361407 - Resource leak warning when resource is assigned to a field outside of constructor
+// a closeable is assigned to a field - constructor vs. method
+public void test061l2() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "xy/Leaks.java",
+ "package xy;\n" +
+ "\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "\n" +
+ "public class Leaks {\n" +
+ " private FileInputStream fInput;\n" +
+ "\n" +
+ " Leaks(String name) throws IOException {\n" +
+ " FileInputStream fileInputStream= new FileInputStream(name);\n" +
+ " fInput= fileInputStream;\n" + // warning silenced by field assignment
+ " Objects.hashCode(fInput);\n" +
+ " \n" +
+ " init(name);\n" +
+ " }\n" +
+ " \n" +
+ " Leaks() throws IOException {\n" +
+ " this(new FileInputStream(\"default\")); // potential problem\n" +
+ " }\n" +
+ " \n" +
+ " Leaks(FileInputStream fis) throws IOException {\n" +
+ " fInput= fis;\n" +
+ " }\n" +
+ " void init(String name) throws IOException {\n" +
+ " FileInputStream fileInputStream= new FileInputStream(name);\n" +
+ " fInput= fileInputStream;\n" + // warning silenced by field assignment
+ " Objects.hashCode(fInput);\n" +
+ " }\n" +
+ " \n" +
+ " public void dispose() throws IOException {\n" +
+ " fInput.close();\n" +
+ " }\n" +
+ "}\n" +
+ "class Objects {\n" + // mock java.util.Objects (@since 1.7).
+ " static int hashCode(Object o) { return 13; }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in xy\\Leaks.java (at line 18)\n" +
+ " this(new FileInputStream(\"default\")); // potential problem\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value>\' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 361407 - Resource leak warning when resource is assigned to a field outside of constructor
+// a closeable is not assigned to a field - constructor vs. method
+public void test061l3() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "xy/Leaks.java",
+ "package xy;\n" +
+ "\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "\n" +
+ "public class Leaks {\n" +
+ "\n" +
+ " Leaks(String name) throws IOException {\n" +
+ " FileInputStream fileInputStream= new FileInputStream(name);\n" +
+ " Objects.hashCode(fileInputStream);\n" +
+ " \n" +
+ " init(name);\n" +
+ " }\n" +
+ " void init(String name) throws IOException {\n" +
+ " FileInputStream fileInputStream= new FileInputStream(name);\n" +
+ " Objects.hashCode(fileInputStream);\n" +
+ " }\n" +
+ "}\n" +
+ "class Objects {\n" + // mock java.util.Objects (@since 1.7).
+ " static int hashCode(Object o) { return 13; }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in xy\\Leaks.java (at line 9)\n" +
+ " FileInputStream fileInputStream= new FileInputStream(name);\n" +
+ " ^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'fileInputStream\' may not be closed\n" +
+ "----------\n" +
+ "2. ERROR in xy\\Leaks.java (at line 15)\n" +
+ " FileInputStream fileInputStream= new FileInputStream(name);\n" +
+ " ^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'fileInputStream\' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// a closeable is passed to another method in a return statement
+// example constructed after org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository#getArtifact(..)
+public void test061m() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.InputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " BufferedInputStream stream;\n" +
+ " BufferedInputStream foo(File file) throws IOException {\n" +
+ " FileInputStream s = new FileInputStream(file);\n" +
+ " return check(new BufferedInputStream(s));\n" +
+ " }\n" +
+ " BufferedInputStream foo2(FileInputStream s, File file) throws IOException {\n" +
+ " s = new FileInputStream(file);\n" +
+ " return check(s);\n" +
+ " }\n" +
+ " BufferedInputStream foo3(InputStream s) throws IOException {\n" +
+ " s = check(s);\n" +
+ " return check(s);\n" +
+ " }\n" +
+ " BufferedInputStream check(InputStream s) { return null; }\n" +
+ "}\n"
+ },
+ // TODO: also these warnings *might* be avoidable by detecting check(s) as a wrapper creation??
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " return check(new BufferedInputStream(s));\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value>\' may not be closed at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 14)\n" +
+ " return check(s);\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'s\' may not be closed at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 18)\n" +
+ " return check(s);\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'s\' may not be closed at this location\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// a resource wrapper does not wrap any provided resource
+public void test061n() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.PrintWriter;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " PrintWriter writer = new PrintWriter(\"filename\");\n" +
+ " writer.write(1);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " PrintWriter writer = new PrintWriter(\"filename\");\n" +
+ " ^^^^^^\n" +
+ "Resource leak: \'writer\' is never closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// a resource wrapper is closed only in its local block, underlying resource may leak
+public void test061o() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo(boolean bar) throws IOException {\n" +
+ " File file = new File(\"somefil\");\n" +
+ " FileInputStream fileStream = new FileInputStream(file);\n" +
+ " BufferedInputStream bis = new BufferedInputStream(fileStream); \n" +
+ " if (bar) {\n" +
+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
+ " doubleWrap.close();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " BufferedInputStream bis = new BufferedInputStream(fileStream); \n" +
+ " ^^^\n" +
+ "Potential resource leak: \'bis\' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// a resource wrapper is conditionally allocated but not closed - from a real-world example
+public void test061f4() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.FileNotFoundException;\n" +
+ "import java.io.InputStream;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "public class X {\n" +
+ " void foo(File location, String adviceFilePath) throws FileNotFoundException {\n" +
+ " InputStream stream = null;\n" +
+ " if (location.isDirectory()) {\n" +
+ " File adviceFile = new File(location, adviceFilePath);\n" +
+ " stream = new BufferedInputStream(new FileInputStream(adviceFile));\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 11)\n" +
+ " stream = new BufferedInputStream(new FileInputStream(adviceFile));\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'stream\' may not be closed\n" + // message could be stronger, but the enclosing if blurs the picture
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// a t-w-r wraps an existing resource
+public void test061p() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return;
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.PrintWriter;\n" +
+ "import java.io.BufferedWriter;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " PrintWriter writer = new PrintWriter(\"filename\");\n" +
+ " try (BufferedWriter bw = new BufferedWriter(writer)) {\n" +
+ " bw.write(1);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// a t-w-r potentially wraps an existing resource
+// DISABLED, fails because we currently don't include t-w-r managed resources in the analysis
+public void _test061q() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return;
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.PrintWriter;\n" +
+ "import java.io.BufferedWriter;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo(boolean b) throws IOException {\n" +
+ " PrintWriter writer = new PrintWriter(\"filename\");\n" +
+ " if (b)\n" +
+ " try (BufferedWriter bw = new BufferedWriter(writer)) {\n" +
+ " bw.write(1);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " PrintWriter writer = new PrintWriter(\\\"filename\\\");\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'writer\' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// the inner from a wrapper is returned
+public void test061r() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileInputStream;\n" +
+ "import java.io.File;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " FileInputStream foo() throws IOException {\n" +
+ " File file = new File(\"somefil\");\n" +
+ " FileInputStream fileStream = new FileInputStream(file);\n" +
+ " BufferedInputStream bis = new BufferedInputStream(fileStream); \n" +
+ " return fileStream;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 358903 - Filter practically unimportant resource leak warnings
+// a wrapper is forgotten, the inner is closed afterwards
+public void test061s() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileInputStream;\n" +
+ "import java.io.File;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " File file = new File(\"somefil\");\n" +
+ " FileInputStream fileStream = new FileInputStream(file);\n" +
+ " BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
+ " bis = null;\n" +
+ " fileStream.close();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 362331 - Resource leak not detected when closeable not assigned to variable
+// a resource is never assigned
+public void test062a() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileOutputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " new FileOutputStream(new File(\"C:\\temp\\foo.txt\")).write(1);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " new FileOutputStream(new File(\"C:\\temp\\foo.txt\")).write(1);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 362331 - Resource leak not detected when closeable not assigned to variable
+// a freshly allocated resource is immediately closed
+public void test062b() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileOutputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " new FileOutputStream(new File(\"C:\\temp\\foo.txt\")).close();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 362331 - Resource leak not detected when closeable not assigned to variable
+// a resource is directly passed to another method
+public void test062c() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileOutputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " writeIt(new FileOutputStream(new File(\"C:\\temp\\foo.txt\")));\n" +
+ " }\n" +
+ " void writeIt(FileOutputStream fos) throws IOException {\n" +
+ " fos.write(1);\n" +
+ " fos.close();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " writeIt(new FileOutputStream(new File(\"C:\\temp\\foo.txt\")));\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value>\' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 362331 - Resource leak not detected when closeable not assigned to variable
+// a resource is not used
+public void test062d() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileOutputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo() throws IOException {\n" +
+ " new FileOutputStream(new File(\"C:\\temp\\foo.txt\"));\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " new FileOutputStream(new File(\"C:\\temp\\foo.txt\"));\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 362332 - Only report potential leak when closeable not created in the local scope
+// a wrapper is obtained from another method
+public void test063a() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.File;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void read(File file) throws IOException {\n" +
+ " FileInputStream stream = new FileInputStream(file);\n" +
+ " BufferedInputStream bis = new BufferedInputStream(stream); // never since reassigned\n" +
+ " FileInputStream stream2 = new FileInputStream(file); // unsure since passed to method\n" +
+ " bis = getReader(stream2); // unsure since obtained from method\n" +
+ " bis.available();\n" +
+ " }\n" +
+ " BufferedInputStream getReader(FileInputStream stream) throws IOException {\n" +
+ " return new BufferedInputStream(stream);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " FileInputStream stream = new FileInputStream(file);\n" +
+ " ^^^^^^\n" +
+ "Resource leak: \'stream\' is never closed\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 9)\n" +
+ " FileInputStream stream2 = new FileInputStream(file); // unsure since passed to method\n" +
+ " ^^^^^^^\n" +
+ "Potential resource leak: \'stream2\' may not be closed\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 10)\n" +
+ " bis = getReader(stream2); // unsure since obtained from method\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'bis\' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 362332 - Only report potential leak when closeable not created in the local scope
+// a wrapper is obtained from a field read
+public void test063b() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileInputStream;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " FileInputStream stream;\n" +
+ " void read() throws IOException {\n" +
+ " FileInputStream s = this.stream;\n" +
+ " BufferedInputStream bis = new BufferedInputStream(s); // don't complain since s is obtained from a field\n" +
+ " bis.available();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 362332 - Only report potential leak when closeable not created in the local scope
+// a wrapper is assigned to a field
+public void test063c() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileInputStream;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " BufferedInputStream stream;\n" +
+ " void read() throws IOException {\n" +
+ " FileInputStream s = new FileInputStream(\"somefile\");\n" +
+ " BufferedInputStream bis = new BufferedInputStream(s);\n" +
+ " this.stream = bis;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 362332 - Only report potential leak when closeable not created in the local scope
+// a resource is obtained as a method argument and/or assigned with a cast
+public void test063d() throws IOException {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
+ runTestsExpectingErrorsOnlyIn17(
+ new String[] {
+ "X.java",
+ "import java.io.FileInputStream;\n" +
+ "import java.io.BufferedInputStream;\n" +
+ "import java.io.InputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " void foo( InputStream input) throws IOException {\n" +
+ " FileInputStream input1 = (FileInputStream)input;\n" +
+ " System.out.println(input1.read());\n" +
+ " input.close();\n" + // don't propose t-w-r for argument
+ " }\n" +
+ " void foo() throws IOException {\n" +
+ " InputStream input = new FileInputStream(\"somefile\");\n" +
+ " FileInputStream input1 = (FileInputStream)input;\n" +
+ " System.out.println(input1.read());\n" +
+ " input.close();\n" + // do propose t-w-r, not from a method argument
+ " }\n" +
+ " void foo3( InputStream input, InputStream input2) throws IOException {\n" +
+ " FileInputStream input1 = (FileInputStream)input;\n" + // still don't claim because obtained from outside
+ " System.out.println(input1.read());\n" +
+ " BufferedInputStream bis = new BufferedInputStream(input2);\n" +
+ " System.out.println(bis.read());\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 12)\n" +
+ " InputStream input = new FileInputStream(\"somefile\");\n" +
+ " ^^^^^\n" +
+ "Resource \'input\' should be managed by try-with-resource\n" +
+ "----------\n",
+ options);
+}
+// Bug 362332 - Only report potential leak when closeable not created in the local scope
+// a resource is obtained from a field read, then re-assigned
+public void test063e() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.FileInputStream;\n" +
+ "import java.io.IOException;\n" +
+ "public class X {\n" +
+ " FileInputStream input1;\n" +
+ " public void foo() throws IOException {\n" +
+ " FileInputStream input = input1;\n" +
+ " input = new FileInputStream(\"adfafd\");\n" +
+ " input.close();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null);
+}
+// Bug 368709 - Endless loop in FakedTrackingVariable.markPassedToOutside
+// original test case from jgit
+public void testBug368709a() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return;
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.*;\n" +
+ "import java.util.zip.*;\n" +
+ "public class X {\n" +
+ " Object db, pack;\n" + // mock
+ " int objectOffset, headerLength, type, size;\n" +
+ " public ObjectStream openStream() throws MissingObjectException, IOException {\n" +
+ " WindowCursor wc = new WindowCursor(db);\n" +
+ " InputStream in;\n" +
+ " try\n" +
+ " {\n" +
+ " in = new PackInputStream(pack, (objectOffset + headerLength), wc);\n" +
+ " }\n" +
+ " catch (IOException packGone)\n" +
+ " {\n" +
+ " return wc.open(getObjectId(), type).openStream();\n" +
+ " }\n" +
+ " in = new BufferedInputStream(new InflaterInputStream(in, wc.inflater(), 8192), 8192);\n" +
+ " return new ObjectStream.Filter(type, size, in);\n" +
+ " }\n" +
+ " String getObjectId() { return \"\"; }\n" + // mock
+ "}\n" +
+ // mock:
+ "class WindowCursor {\n" +
+ " WindowCursor(Object db) {}\n" +
+ " ObjectStream open(String id, int type) { return null; }\n" +
+ " Inflater inflater() { return null; }\n" +
+ "}\n" +
+ "class MissingObjectException extends Exception {\n" +
+ " public static final long serialVersionUID = 13L;\n" +
+ " MissingObjectException() { super();}\n" +
+ "}\n" +
+ "class PackInputStream extends InputStream {\n" +
+ " PackInputStream(Object pack, int offset, WindowCursor wc) throws IOException {}\n" +
+ " public int read() { return 0; }\n" +
+ "}\n" +
+ "class ObjectStream extends InputStream {\n" +
+ " static class Filter extends ObjectStream {\n" +
+ " Filter(int type, int size, InputStream in) { }\n" +
+ " }\n" +
+ " ObjectStream openStream() { return this; }\n" +
+ " public int read() { return 0; }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 15)\n" +
+ " return wc.open(getObjectId(), type).openStream();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'in\' is not closed at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 18)\n" +
+ " return new ObjectStream.Filter(type, size, in);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'in\' may not be closed at this location\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+// Bug 368709 - Endless loop in FakedTrackingVariable.markPassedToOutside
+// minimal test case: constructing an indirect self-wrapper
+public void testBug368709b() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return;
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.io.*;\n" +
+ "import java.util.zip.*;\n" +
+ "public class X {\n" +
+ " void doit() throws IOException {\n" +
+ " InputStream in = new FileInputStream(\"somefile\");\n" +
+ " in = new BufferedInputStream(new InflaterInputStream(in, inflater(), 8192), 8192);\n" +
+ " process(in);\n" +
+ " }\n" +
+ " Inflater inflater() { return null; }\n" +
+ " void process(InputStream is) { }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " InputStream in = new FileInputStream(\"somefile\");\n" +
+ " ^^\n" +
+ "Potential resource leak: \'in\' may not be closed\n" +
+ "----------\n",
+ null,
+ true,
+ options);
+}
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java
index f6543aa96..8b83af74d 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2011 IBM Corporation and others.
+ * Copyright (c) 2006, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -19,6 +19,7 @@ import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
public class StackMapAttributeTest extends AbstractRegressionTest {
public StackMapAttributeTest(String name) {
@@ -7089,4 +7090,530 @@ public class StackMapAttributeTest extends AbstractRegressionTest {
},
"");
}
+ //https://bugs.eclipse.org/bugs/show_bug.cgi?id=366999
+ public void test056() throws Exception {
+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return;
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.BufferedReader;\n" +
+ "import java.io.Closeable;\n" +
+ "import java.io.File;\n" +
+ "import java.io.FileReader;\n" +
+ "import java.io.IOException;\n" +
+ "\n" +
+ "public class X {\n" +
+ "\n" +
+ " static class C implements Closeable {\n" +
+ " @Override\n" +
+ " public void close() throws IOException {\n" +
+ " //\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " int run() throws IOException {\n" +
+ " int lcnt = 0;\n" +
+ " try (C c = new C();) {\n" +
+ " try (final BufferedReader br = new BufferedReader(new FileReader(\n" +
+ " new File(\"logging.properties\")))) {\n" +
+ " String s = null;\n" +
+ " while ((s = br.readLine()) != null)\n" +
+ " lcnt++;\n" +
+ " return lcnt;\n" +
+ " }\n" +
+ " } finally {\n" +
+ " System.out.println(\"read \" + lcnt + \" lines\");\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " public static void main(final String[] args) throws IOException {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}",
+ },
+ "SUCCESS");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test057() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " for (;;) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n",
+ },
+ "SUCCESS");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test058() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " for (;true;) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n" },
+ "SUCCESS");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test059() throws Exception {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " for (;false;) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n" },
+ "----------\n" +
+ "1. WARNING in X.java (at line 4)\n" +
+ " label1: do {\n" +
+ " ^^^^^^\n" +
+ "The label label1 is never explicitly referenced\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 5)\n" +
+ " for (;false;) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Unreachable code\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 10)\n" +
+ " } while (s != null);\n" +
+ " ^\n" +
+ "The local variable s may not have been initialized\n" +
+ "----------\n");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test060() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " for (; 5 < 10;) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n" },
+ "SUCCESS");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test061() throws Exception {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " int five = 5, ten = 10;\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " for (; five < ten;) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n" },
+ "----------\n" +
+ "1. WARNING in X.java (at line 9)\n" +
+ " continue label1;\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 11)\n" +
+ " } while (s != null);\n" +
+ " ^\n" +
+ "The local variable s may not have been initialized\n" +
+ "----------\n");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test062() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " final int five = 5, ten = 10;\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " for (; five < ten;) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n" },
+ "SUCCESS");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test063() throws Exception {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " final int five = 5, ten = 10;\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " for (; five > ten;) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n" },
+ "----------\n" +
+ "1. WARNING in X.java (at line 5)\n" +
+ " label1: do {\n" +
+ " ^^^^^^\n" +
+ "The label label1 is never explicitly referenced\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 6)\n" +
+ " for (; five > ten;) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Unreachable code\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 11)\n" +
+ " } while (s != null);\n" +
+ " ^\n" +
+ "The local variable s may not have been initialized\n" +
+ "----------\n");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test064() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " while (true) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n",
+ },
+ "SUCCESS");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test065() throws Exception {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " while (false) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n" },
+ "----------\n" +
+ "1. WARNING in X.java (at line 4)\n" +
+ " label1: do {\n" +
+ " ^^^^^^\n" +
+ "The label label1 is never explicitly referenced\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 5)\n" +
+ " while (false) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Unreachable code\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 10)\n" +
+ " } while (s != null);\n" +
+ " ^\n" +
+ "The local variable s may not have been initialized\n" +
+ "----------\n");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test066() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " while(5 < 10) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n" },
+ "SUCCESS");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test067() throws Exception {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " int five = 5, ten = 10;\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " while (five < ten) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n" },
+ "----------\n" +
+ "1. WARNING in X.java (at line 9)\n" +
+ " continue label1;\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 11)\n" +
+ " } while (s != null);\n" +
+ " ^\n" +
+ "The local variable s may not have been initialized\n" +
+ "----------\n");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test068() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " final int five = 5, ten = 10;\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " while (five < ten) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n" },
+ "SUCCESS");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test069() throws Exception {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void run() {\n" +
+ " final int five = 5, ten = 10;\n" +
+ " String s;\n" +
+ " label1: do {\n" +
+ " while (five > ten) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " } while (s != null);\n" +
+ "}\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}\n" },
+ "----------\n" +
+ "1. WARNING in X.java (at line 5)\n" +
+ " label1: do {\n" +
+ " ^^^^^^\n" +
+ "The label label1 is never explicitly referenced\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 6)\n" +
+ " while (five > ten) {\n" +
+ " s = \"\";\n" +
+ " if (s == null) \n" +
+ " continue label1;\n" +
+ " }\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Unreachable code\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 11)\n" +
+ " } while (s != null);\n" +
+ " ^\n" +
+ "The local variable s may not have been initialized\n" +
+ "----------\n");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023
+ public void test070() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.util.ArrayList;\n" +
+ "import java.util.Arrays;\n" +
+ "import java.util.Iterator;\n" +
+ "import java.util.List;\n" +
+ "import java.util.Properties;\n" +
+ "import org.w3c.dom.*;\n" +
+ "public class X extends Object {\n" +
+ " public static void main(String [] args) {\n" +
+ " System.out.println (\"SUCCESS\");\n" +
+ " }\n" +
+ " private static class Handler extends Object {\n" +
+ " public int getStuff() {\n" +
+ " return 1;\n" +
+ " }\n" +
+ " public void handle(Element element) {\n" +
+ " Properties properties = new Properties();\n" +
+ " NamedNodeMap atts = element.getAttributes();\n" +
+ " if (atts != null) {\n" +
+ " for (int a = 0; a < atts.getLength(); a++) {\n" +
+ " Node att = atts.item(a);\n" +
+ " String name = att.getNodeName();\n" +
+ " String value = att.getNodeValue();\n" +
+ " if (\"foo\".equals(name)) {\n" +
+ " name = value;\n" +
+ " } else {\n" +
+ " if (!\"bar\".equals(name))\n" +
+ " continue;\n" +
+ " name = value;\n" +
+ " }\n" +
+ " properties.put(name, value);\n" +
+ " }\n" +
+ " }\n" +
+ " label0: do {\n" +
+ " Node node;\n" +
+ " String nodeName;\n" +
+ " label1: do {\n" +
+ " for (Iterator i = (new ArrayList(1)).iterator(); i\n" +
+ " .hasNext(); members.add(equals(node))) {\n" +
+ " node = (Node) i.next();\n" +
+ " nodeName = \"\" + equals(node.getNodeName());\n" +
+ " if (!\"foo\".equals(nodeName))\n" +
+ " continue label1;\n" +
+ " }\n" +
+ " break label0;\n" +
+ " } while (!\"bar\".equals(nodeName));\n" +
+ " Iterator i = (new ArrayList(1)).iterator();\n" +
+ " while (i.hasNext()) {\n" +
+ " Node n = (Node) i.next();\n" +
+ " String name = toString() + n.getNodeName();\n" +
+ " if (\"wtf\".equals(name)) {\n" +
+ " String propertyName = (toString() + n.getAttributes()\n" +
+ " .getNamedItem(\"broken\")).trim();\n" +
+ " String value = toString() + n;\n" +
+ " properties.put(propertyName, value);\n" +
+ " }\n" +
+ " }\n" +
+ " } while (true);\n" +
+ " propertiesBuilder.equals(properties);\n" +
+ " builder.equals(propertiesBuilder.hashCode());\n" +
+ " builder.equals(members);\n" +
+ " }\n" +
+ " private final Object c;\n" +
+ " private Object builder;\n" +
+ " private List members;\n" +
+ " private Object propertiesBuilder;\n" +
+ " public Handler(Object c) {\n" +
+ " this.c = c;\n" +
+ " builder = Arrays.asList(Object.class);\n" +
+ " builder.equals(\"foo\");\n" +
+ " builder.equals(\"bar\");\n" +
+ " members = new ArrayList();\n" +
+ " propertiesBuilder = Arrays.asList(Object.class);\n" +
+ " Object beanDefinition = propertiesBuilder.toString();\n" +
+ " Object holder = new String(\"stirng\");\n" +
+ " Arrays.asList(holder, c.toString());\n" +
+ " }\n" +
+ " }\n" +
+ " public X() {\n" +
+ " }\n" +
+ " protected Object parseInternal(Element element, Object c) {\n" +
+ " Handler h = new Handler(c);\n" +
+ " h.handle(element);\n" +
+ " return h.getStuff();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "SUCCESS");
+ }
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
index e3c1ded8a..d41115e7f 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,7 +8,9 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Technical University Berlin - adapted for Object Teams
- * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
+ * Stephan Herrmann - Contributions for
+ * bug 186342 - [compiler][null] Using annotations for null checking
+ * bug 358903 - Filter practically unimportant resource leak warnings
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -79,6 +81,7 @@ public static Test suite() {
standardTests.add(ProgrammingProblemsTest.class);
standardTests.add(ManifestAnalyzerTest.class);
standardTests.add(InitializationTests.class);
+ standardTests.add(ResourceLeakTests.class);
// add all javadoc tests
for (int i=0, l=JavadocTest.ALL_CLASSES.size(); i<l; i++) {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java
index 563cc0b99..48b9ad339 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011 IBM Corporation and others.
+ * Copyright (c) 2011, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -16,14 +16,13 @@ package org.eclipse.jdt.core.tests.compiler.regression;
import java.util.Map;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
-
import junit.framework.Test;
+
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
static {
-// TESTS_NAMES = new String[] { "test056throw"};
+// TESTS_NAMES = new String[] { "test061m"};
// TESTS_NUMBERS = new int[] { 50 };
// TESTS_RANGE = new int[] { 11, -1 };
}
@@ -3454,1736 +3453,9 @@ public void test055a() {
},
"Done");
}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// a method uses an AutoCloseable without ever closing it.
-public void test056() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader fileReader = new FileReader(file);\n" +
-// not invoking any methods on FileReader, try to avoid necessary call to superclass() in the compiler
-// " char[] in = new char[50];\n" +
-// " fileReader.read(in);\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " ^^^^^^^^^^\n" +
- "Resource leak: 'fileReader' is never closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// a method uses an AutoCloseable and closes it but not protected by t-w-r nor regular try-finally
-public void test056a() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " fileReader.close();\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " try {\n" +
- " new X().foo();\n" +
- " } catch (IOException ioex) {\n" +
- " System.out.println(\"caught\");\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " ^^^^^^^^^^\n" +
- "Resource 'fileReader' should be managed by try-with-resource\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// a method uses an AutoCloseable and closes it properly in a finally block
-public void test056b() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
- this.runConformTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " try {\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " } finally {\n" +
- " fileReader.close();\n" +
- " }\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " try {\n" +
- " new X().foo();\n" +
- " } catch (IOException ioex) {\n" +
- " System.out.println(\"caught\");\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- "caught", /*output*/
- null/*classLibs*/,
- true/*shouldFlush*/,
- null/*vmargs*/,
- options,
- null/*requestor*/);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// a method uses an AutoCloseable properly within try-with-resources.
-public void test056c() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
- this.runConformTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " try (FileReader fileReader = new FileReader(file)) {\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " }\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " try {\n" +
- " new X().foo();\n" +
- " } catch (IOException ioex) {\n" +
- " System.out.println(\"caught\");\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- "caught", /*output*/
- null/*classLibs*/,
- true/*shouldFlush*/,
- null/*vmargs*/,
- options,
- null/*requestor*/);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// a method uses two AutoCloseables (testing independent analysis)
-// - one closeable may be unclosed at a conditional return
-// - the other is only conditionally closed
-public void test056d() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo(boolean flag1, boolean flag2) throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " char[] in = new char[50];\n" +
- " FileReader fileReader1 = new FileReader(file);\n" +
- " fileReader1.read(in);\n" +
- " FileReader fileReader2 = new FileReader(file);\n" +
- " fileReader2.read(in);\n" +
- " if (flag1) {\n" +
- " fileReader2.close();\n" +
- " return;\n" +
- " } else if (flag2) {\n" +
- " fileReader2.close();\n" +
- " }\n" +
- " fileReader1.close();\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo(false, true);\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. WARNING in X.java (at line 10)\n" +
- " FileReader fileReader2 = new FileReader(file);\n" +
- " ^^^^^^^^^^^\n" +
- "Potential resource leak: 'fileReader2' may not be closed\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 14)\n" +
- " return;\n" +
- " ^^^^^^^\n" +
- "Resource leak: 'fileReader1' is not closed at this location\n" +
- "----------\n",
- null,
- true,
- options);
-}
-//Bug 349326 - [1.7] new warning for missing try-with-resources
-//a method uses two AutoCloseables (testing independent analysis)
-//- one closeable may be unclosed at a conditional return
-//- the other is only conditionally closed
-public void test056d_suppress() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
- options.put(CompilerOptions.OPTION_SuppressOptionalErrors, CompilerOptions.ENABLED);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo(boolean flag1, boolean flag2) throws IOException {\n" +
- " @SuppressWarnings(\"resource\") File file = new File(\"somefile\"); // unnecessary suppress\n" +
- " char[] in = new char[50];\n" +
- " FileReader fileReader1 = new FileReader(file);\n" +
- " fileReader1.read(in);\n" +
- " @SuppressWarnings(\"resource\") FileReader fileReader2 = new FileReader(file); // useful suppress\n" +
- " fileReader2.read(in);\n" +
- " if (flag1) {\n" +
- " fileReader2.close();\n" +
- " return; // not suppressed\n" +
- " } else if (flag2) {\n" +
- " fileReader2.close();\n" +
- " }\n" +
- " fileReader1.close();\n" +
- " }\n" +
- " @SuppressWarnings(\"resource\") // useful suppress\n" +
- " void bar() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo(false, true);\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. WARNING in X.java (at line 6)\n" +
- " @SuppressWarnings(\"resource\") File file = new File(\"somefile\"); // unnecessary suppress\n" +
- " ^^^^^^^^^^\n" +
- "Unnecessary @SuppressWarnings(\"resource\")\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 14)\n" +
- " return; // not suppressed\n" +
- " ^^^^^^^\n" +
- "Resource leak: 'fileReader1' is not closed at this location\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// one method returns an AutoCleasble, a second method uses this object without ever closing it.
-public void test056e() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " FileReader getReader(String filename) throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " return fileReader;\n" + // don't complain here, pass responsibility to caller
- " }\n" +
- " void foo() throws IOException {\n" +
- " FileReader reader = getReader(\"somefile\");\n" +
- " char[] in = new char[50];\n" +
- " reader.read(in);\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 11)\n" +
- " FileReader reader = getReader(\"somefile\");\n" +
- " ^^^^^^\n" +
- "Resource leak: 'reader' is never closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// a method explicitly closes its AutoCloseable rather than using t-w-r
-public void test056f() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
- options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader fileReader = null;\n" +
- " try {\n" +
- " fileReader = new FileReader(file);\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " } finally {\n" +
- " fileReader.close();\n" +
- " }\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " FileReader fileReader = null;\n" +
- " ^^^^^^^^^^\n" +
- "Resource 'fileReader' should be managed by try-with-resource\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// an AutoCloseable local is re-assigned
-public void test056g() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " fileReader = new FileReader(file);\n" +
- " fileReader.read(in);\n" +
- " fileReader.close();\n" +
- " fileReader = null;\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " fileReader = new FileReader(file);\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Resource leak: 'fileReader' is not closed at this location\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// an AutoCloseable local is re-assigned after null-assigned
-public void test056g2() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " fileReader = null;\n" +
- " fileReader = new FileReader(file);\n" + // don't complain again, fileReader is null, so nothing can leak here
- " fileReader.read(in);\n" +
- " fileReader.close();\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " fileReader = null;\n" +
- " ^^^^^^^^^^^^^^^^^\n" +
- "Resource leak: 'fileReader' is not closed at this location\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// two AutoCloseables at different nesting levels (anonymous local type)
-public void test056h() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " final File file = new File(\"somefile\");\n" +
- " final FileReader fileReader = new FileReader(file);\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " new Runnable() {\n public void run() {\n" +
- " try {\n" +
- " fileReader.close();\n" +
- " FileReader localReader = new FileReader(file);\n" +
- " } catch (IOException ex) { /* nop */ }\n" +
- " }}.run();\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. WARNING in X.java (at line 7)\n" +
- " final FileReader fileReader = new FileReader(file);\n" +
- " ^^^^^^^^^^\n" +
- "Potential resource leak: 'fileReader' may not be closed\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 14)\n" +
- " FileReader localReader = new FileReader(file);\n" +
- " ^^^^^^^^^^^\n" +
- "Resource leak: 'localReader' is never closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// three AutoCloseables in different blocks of the same method
-public void test056i() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo(boolean f1, boolean f2) throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " if (f1) {\n" +
- " FileReader fileReader = new FileReader(file); // err: not closed\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " while (true) {\n" +
- " FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" +
- " loopReader.close();" +
- " break;\n" +
- " }\n" +
- " } else {\n" +
- " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
- " if (f2)\n" +
- " fileReader.close();\n" +
- " }\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo(true, true);\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 8)\n" +
- " FileReader fileReader = new FileReader(file); // err: not closed\n" +
- " ^^^^^^^^^^\n" +
- "Resource leak: 'fileReader' is never closed\n" +
- "----------\n" +
- "2. WARNING in X.java (at line 16)\n" +
- " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
- " ^^^^^^^^^^\n" +
- "Potential resource leak: 'fileReader' may not be closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// three AutoCloseables in different blocks of the same method
-public void test056i2() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo(boolean f1, boolean f2) throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " if (f1) {\n" +
- " FileReader fileReader = new FileReader(file); // properly closed\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " while (true) {\n" +
- " fileReader.close();\n" +
- " FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" +
- " loopReader.close();\n" +
- " break;\n" +
- " }\n" +
- " } else {\n" +
- " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
- " if (f2)\n" +
- " fileReader.close();\n" +
- " }\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo(true, true);\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 18)\n" +
- " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
- " ^^^^^^^^^^\n" +
- "Potential resource leak: 'fileReader' may not be closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// a method uses an AutoCloseable without closing it locally but passing as arg to another method
-public void test056j() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " read(fileReader);\n" +
- " }\n" +
- " void read(FileReader reader) { }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " ^^^^^^^^^^\n" +
- "Potential resource leak: 'fileReader' may not be closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// a method uses an AutoCloseable without closing it locally but passing as arg to another method
-public void test056jconditional() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo(boolean b) throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " synchronized (b ? this : new X()) {\n" +
- " new ReadDelegator(fileReader);\n" +
- " }\n" +
- " }\n" +
- " class ReadDelegator { ReadDelegator(FileReader reader) { } }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo(true);\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " ^^^^^^^^^^\n" +
- "Potential resource leak: 'fileReader' may not be closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// many locals, some are AutoCloseable.
-// Unfortunately analysis cannot respect how exception exits may affect ra3 and rb3,
-// doing so would create false positives.
-public void test056k() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
- options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " int i01, i02, i03, i04, i05, i06, i07, i08, i09,\n" +
- " i11, i12, i13, i14, i15, i16, i17, i18, i19,\n" +
- " i21, i22, i23, i24, i25, i26, i27, i28, i29,\n" +
- " i31, i32, i33, i34, i35, i36, i37, i38, i39,\n" +
- " i41, i42, i43, i44, i45, i46, i47, i48, i49;\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader ra1 = null, ra2 = null;\n" +
- " try {\n" +
- " ra1 = new FileReader(file);\n" +
- " ra2 = new FileReader(file);\n" +
- " FileReader ra3 = new FileReader(file);\n" +
- " char[] in = new char[50];\n" +
- " ra1.read(in);\n" +
- " ra2.read(in);\n" +
- " ra3.close();\n" +
- " } finally {\n" +
- " ra1.close();\n" +
- " }\n" +
- " int i51, i52, i53, i54, i55, i56, i57, i58, i59, i60;\n" + // beyond this point locals are analyzed using extraBits
- " FileReader rb1 = null, rb2 = null;\n" +
- " try {\n" +
- " rb1 = new FileReader(file);\n" +
- " rb2 = new FileReader(file);\n" +
- " FileReader rb3 = new FileReader(file);\n" +
- " char[] in = new char[50];\n" +
- " rb1.read(in);\n" +
- " rb2.read(in);\n" +
- " rb3.close();\n" +
- " } finally {\n" +
- " rb1.close();\n" +
- " }\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 12)\n" +
- " FileReader ra1 = null, ra2 = null;\n" +
- " ^^^\n" +
- "Resource 'ra1' should be managed by try-with-resource\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 15)\n" +
- " ra2 = new FileReader(file);\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Resource leak: 'ra2' is never closed\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 16)\n" +
- " FileReader ra3 = new FileReader(file);\n" +
- " ^^^\n" +
- "Resource 'ra3' should be managed by try-with-resource\n" +
- "----------\n" +
- "4. ERROR in X.java (at line 25)\n" +
- " FileReader rb1 = null, rb2 = null;\n" +
- " ^^^\n" +
- "Resource 'rb1' should be managed by try-with-resource\n" +
- "----------\n" +
- "5. ERROR in X.java (at line 28)\n" +
- " rb2 = new FileReader(file);\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Resource leak: 'rb2' is never closed\n" +
- "----------\n" +
- "6. ERROR in X.java (at line 29)\n" +
- " FileReader rb3 = new FileReader(file);\n" +
- " ^^^\n" +
- "Resource 'rb3' should be managed by try-with-resource\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// various non-problems
-public void test056l() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " X(FileReader r0) {}\n" + // don't complain against argument
- " FileReader getReader() { return null; }\n" +
- " void foo(FileReader r1) throws IOException {\n" +
- " FileReader fileReader = getReader();\n" +
- " if (fileReader == null)\n" +
- " return;\n" + // don't complain, resource is actually null
- " FileReader r3 = getReader();\n" +
- " if (r3 == null)\n" +
- " r3 = new FileReader(new File(\"absent\"));\n" + // don't complain, previous resource is actually null
- " try {\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " r1.read(in);\n" +
- " } finally {\n" +
- " fileReader.close();\n" +
- " r3.close();\n" + // the effect of this close() call might be spoiled by exception in fileReader.close() above, but we ignore exception exits in the analysis
- " }\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" +
- " new X(r2).foo(new FileReader(new File(\"notthere\")));\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 8)\n" +
- " FileReader fileReader = getReader();\n" +
- " ^^^^^^^^^^\n" +
- "Resource 'fileReader' should be managed by try-with-resource\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 11)\n" +
- " FileReader r3 = getReader();\n" +
- " ^^\n" +
- "Resource 'r3' should be managed by try-with-resource\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 24)\n" +
- " FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" +
- " ^^\n" +
- "Potential resource leak: 'r2' may not be closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// nested try with early exit
-public void test056m() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
- this.runConformTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() {\n" +
- " File file = new File(\"somefile\");" +
- " try {\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " try {\n" +
- " char[] in = new char[50];\n" +
- " if (fileReader.read(in)==0)\n" +
- " return;\n" +
- " } finally {\n" +
- " fileReader.close();\n" +
- " }\n" +
- " } catch (IOException e) {\n" +
- " System.out.println(\"caught\");\n" +
- " }\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " new X().foo();\n" +
- " }\n" +
- "}\n"
- },
- "caught", /*output*/
- null/*classLibs*/,
- true/*shouldFlush*/,
- null/*vmargs*/,
- options,
- null/*requestor*/);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// nested try should not interfere with earlier analysis.
-public void test056n() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
- this.runConformTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "import java.io.FileNotFoundException;\n" +
- "public class X {\n" +
- " void foo(File someFile, char[] buf) throws IOException {\n" +
- " FileReader fr1 = new FileReader(someFile);\n" +
- " try {\n" +
- " fr1.read(buf);\n" +
- " } finally {\n" +
- " fr1.close();\n" +
- " }\n" +
- " try {\n" +
- " FileReader fr3 = new FileReader(someFile);\n" +
- " try {\n" +
- " } finally {\n" +
- " fr3.close();\n" +
- " }\n" +
- " } catch (IOException e) {\n" +
- " }\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " try {\n" +
- " new X().foo(new File(\"missing\"), new char[100]);\n" +
- " } catch (FileNotFoundException e) {\n" +
- " System.out.println(\"caught\");\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- "caught", /*output*/
- null/*classLibs*/,
- true/*shouldFlush*/,
- null/*vmargs*/,
- options,
- null/*requestor*/);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// if close is guarded by null check this should still be recognized as definitely closed
-public void test056o() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
- this.runConformTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "import java.io.FileNotFoundException;\n" +
- "public class X {\n" +
- " void foo(File someFile, char[] buf) throws IOException {\n" +
- " FileReader fr1 = null;\n" +
- " try {\n" +
- " fr1 = new FileReader(someFile);" +
- " fr1.read(buf);\n" +
- " } finally {\n" +
- " if (fr1 != null)\n" +
- " try {\n" +
- " fr1.close();\n" +
- " } catch (IOException e) { /*do nothing*/ }\n" +
- " }\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " try {\n" +
- " new X().foo(new File(\"missing\"), new char[100]);\n" +
- " } catch (FileNotFoundException e) {\n" +
- " System.out.println(\"caught\");\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- "caught", /*output*/
- null/*classLibs*/,
- true/*shouldFlush*/,
- null/*vmargs*/,
- options,
- null/*requestor*/);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// a method uses an AutoCloseable without ever closing it, type from a type variable
-public void test056p() {
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.Reader;\n" +
- "import java.io.IOException;\n" +
- "public abstract class X <T extends Reader> {\n" +
- " void foo() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " T fileReader = newReader(file);\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " }\n" +
- " abstract T newReader(File file) throws IOException;\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X<FileReader>() {\n" +
- " FileReader newReader(File f) throws IOException { return new FileReader(f); }\n" +
- " }.foo();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 8)\n" +
- " T fileReader = newReader(file);\n" +
- " ^^^^^^^^^^\n" +
- "Resource leak: 'fileReader' is never closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// closed in dead code
-public void test056q() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " if (2*2 == 4)\n" +
- " return;\n" +
- " fileReader.close();\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " FileReader fileReader = new FileReader(file);\n" +
- " ^^^^^^^^^^\n" +
- "Resource leak: 'fileReader' is never closed\n" +
- "----------\n" +
- "2. WARNING in X.java (at line 10)\n" +
- " if (2*2 == 4)\n" +
- " ^^^^^^^^\n" +
- "Comparing identical expressions\n" +
- "----------\n" +
- "3. WARNING in X.java (at line 12)\n" +
- " fileReader.close();\n" +
- " ^^^^^^^^^^^^^^^^^^\n" +
- "Dead code\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// closed in dead code
-public void test056r() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " FileReader fr = new FileReader(file);\n" +
- " Object b = null;\n" +
- " fr.close();\n" +
- " if (b != null) {\n" +
- " fr = new FileReader(file);\n" +
- " return;\n" +
- " } else {\n" +
- " System.out.print(42);\n" +
- " }\n" +
- " return; // Should not complain about fr\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " if (b != null) {\n" +
- " fr = new FileReader(file);\n" +
- " return;\n" +
- " } else {\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Dead code\n" +
- "----------\n" +
- "2. WARNING in X.java (at line 13)\n" +
- " } else {\n" +
- " System.out.print(42);\n" +
- " }\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Statement unnecessarily nested within else clause. The corresponding then clause does not complete normally\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// resource inside t-w-r is re-assigned, shouldn't even record an errorLocation
-public void test056s() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.File;\n" +
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo() throws IOException {\n" +
- " File file = new File(\"somefile\");\n" +
- " try (FileReader fileReader = new FileReader(file);) {\n" +
- " char[] in = new char[50];\n" +
- " fileReader.read(in);\n" +
- " fileReader = new FileReader(file); // debug here\n" +
- " fileReader.read(in);\n" +
- " }\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " fileReader = new FileReader(file); // debug here\n" +
- " ^^^^^^^^^^\n" +
- "The resource fileReader of a try-with-resources statement cannot be assigned\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// resource is closed, dead code follows
-public void test056t() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "import java.io.IOException;\n" +
- "public class X {\n" +
- " void foo31() throws IOException {\n" +
- " FileReader reader = new FileReader(\"file\"); //warning\n" +
- " if (reader != null) {\n" +
- " reader.close();\n" +
- " } else {\n" +
- " // nop\n" +
- " }\n" +
- " }\n" +
- " public static void main(String[] args) throws IOException {\n" +
- " new X().foo31();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 8)\n" +
- " } else {\n" +
- " // nop\n" +
- " }\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Dead code\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// resource is reassigned within t-w-r with different resource
-// was initially broken due to https://bugs.eclipse.org/358827
-public void test056u() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " void foo() throws Exception {\n" +
- " FileReader reader1 = new FileReader(\"file1\");\n" +
- " FileReader reader2 = new FileReader(\"file2\");\n" +
- " reader2 = reader1;// this disconnects reader 2\n" +
- " try (FileReader reader3 = new FileReader(\"file3\")) {\n" +
- " int ch;\n" +
- " while ((ch = reader2.read()) != -1) {\n" +
- " System.out.println(ch);\n" +
- " reader1.read();\n" +
- " }\n" +
- " reader2 = reader1; // warning 1 regarding original reader1\n" + // this warning was missing
- " reader2 = reader1; // warning 2 regarding original reader1\n" +
- " } finally {\n" +
- " if (reader2 != null) {\n" +
- " reader2.close();\n" +
- " } else {\n" +
- " System.out.println();\n" +
- " }\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " FileReader reader2 = new FileReader(\"file2\");\n" +
- " ^^^^^^^\n" +
- "Resource leak: 'reader2' is never closed\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 13)\n" +
- " reader2 = reader1; // warning 1 regarding original reader1\n" +
- " ^^^^^^^^^^^^^^^^^\n" +
- "Resource leak: 'reader1' is not closed at this location\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 14)\n" +
- " reader2 = reader1; // warning 2 regarding original reader1\n" +
- " ^^^^^^^^^^^^^^^^^\n" +
- "Resource leak: 'reader1' is not closed at this location\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// scope-related pbs reported in https://bugs.eclipse.org/349326#c70 and https://bugs.eclipse.org/349326#c82
-public void test056v() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " boolean foo1() throws Exception {\n" +
- " FileReader reader = new FileReader(\"file\");\n" +
- " try {\n" +
- " int ch;\n" +
- " while ((ch = reader.read()) != -1) {\n" +
- " System.out.println(ch);\n" +
- " reader.read();\n" +
- " }\n" +
- " if (ch > 10) {\n" +
- " return true;\n" +
- " }\n" +
- " return false;\n" + // return while resource from enclosing scope remains unclosed
- " } finally {\n" +
- " }\n" +
- " }\n" +
- " void foo111() throws Exception {\n" +
- " FileReader reader111 = new FileReader(\"file2\");\n" +
- " try {\n" +
- " int ch;\n" +
- " while ((ch = reader111.read()) != -1) {\n" +
- " System.out.println(ch);\n" +
- " reader111.read();\n" +
- " }\n" +
- " return;\n" + // this shouldn't spoil the warning "should be managed with t-w-r"
- " } finally {\n" +
- " if (reader111 != null) {\n" +
- " reader111.close();\n" +
- " }\n" +
- " }\n" +
- " }\n" +
- " void foo2() throws Exception {\n" +
- " FileReader reader2 = new FileReader(\"file\");\n" +
- " try {\n" +
- " int ch;\n" +
- " while ((ch = reader2.read()) != -1) {\n" +
- " System.out.println(ch);\n" +
- " reader2.read();\n" +
- " }\n" +
- " if (ch > 10) {\n" +
- " return;\n" + // potential leak
- " }\n" +
- " } finally {\n" +
- " }\n" +
- " reader2.close();\n" + // due to this close we don't say "never closed"
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " FileReader reader = new FileReader(\"file\");\n" +
- " ^^^^^^\n" +
- "Resource leak: 'reader' is never closed\n" +
- "----------\n" +
- "2. WARNING in X.java (at line 19)\n" +
- " FileReader reader111 = new FileReader(\"file2\");\n" +
- " ^^^^^^^^^\n" +
- "Resource 'reader111' should be managed by try-with-resource\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 42)\n" +
- " return;\n" +
- " ^^^^^^^\n" +
- "Resource leak: 'reader2' is not closed at this location\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// end of method is dead end, but before we have both a close() and an early return
-public void test056w() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " boolean foo1() throws Exception {\n" +
- " FileReader reader = new FileReader(\"file\");\n" +
- " try {\n" +
- " int ch;\n" +
- " while ((ch = reader.read()) != -1) {\n" +
- " System.out.println(ch);\n" +
- " reader.read();\n" +
- " }\n" +
- " if (ch > 10) {\n" +
- " reader.close();\n" +
- " return true;\n" +
- " }\n" +
- " return false;\n" +
- " } finally {\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 15)\n" +
- " return false;\n" +
- " ^^^^^^^^^^^^^\n" +
- "Resource leak: 'reader' is not closed at this location\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// different early exits, if no close seen report as definitely unclosed
-public void test056x() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " void foo31(boolean b) throws Exception {\n" +
- " FileReader reader = new FileReader(\"file\");\n" +
- " if (b) {\n" +
- " reader.close();\n" +
- " } else {\n" +
- " return; // warning\n" +
- " }\n" +
- " }\n" +
- " void foo32(boolean b) throws Exception {\n" +
- " FileReader reader = new FileReader(\"file\"); // warn here\n" +
- " return;\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 8)\n" +
- " return; // warning\n" +
- " ^^^^^^^\n" +
- "Resource leak: 'reader' is not closed at this location\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 12)\n" +
- " FileReader reader = new FileReader(\"file\"); // warn here\n" +
- " ^^^^^^\n" +
- "Resource leak: 'reader' is never closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// nested method passes the resource to outside code
-public void test056y() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " void foo31(boolean b) throws Exception {\n" +
- " final FileReader reader31 = new FileReader(\"file\");\n" +
- " new Runnable() {\n" +
- " public void run() {\n" +
- " foo18(reader31);\n" +
- " }\n" +
- " }.run();\n" +
- " }\n" +
- " void foo18(FileReader r18) {\n" +
- " // could theoretically close r18;\n" +
- " }\n" +
- " abstract class ResourceProvider {\n" +
- " abstract FileReader provide();" +
- " }\n" +
- " ResourceProvider provider;" +
- " void foo23() throws Exception {\n" +
- " final FileReader reader23 = new FileReader(\"file\");\n" +
- " provider = new ResourceProvider() {\n" +
- " public FileReader provide() {\n" +
- " return reader23;\n" +
- " }\n" +
- " };\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. WARNING in X.java (at line 4)\n" +
- " final FileReader reader31 = new FileReader(\"file\");\n" +
- " ^^^^^^^^\n" +
- "Potential resource leak: 'reader31' may not be closed\n" +
- "----------\n" +
- "2. WARNING in X.java (at line 17)\n" +
- " final FileReader reader23 = new FileReader(\"file\");\n" +
- " ^^^^^^^^\n" +
- "Potential resource leak: 'reader23' may not be closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// resource assigned to second local and is (potentially) closed on the latter
-public void test056z() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " void foo17() throws Exception {\n" +
- " FileReader reader17 = new FileReader(\"file\");\n" +
- " final FileReader readerCopy = reader17;\n" +
- " readerCopy.close();\n" +
- " }\n" +
- " void foo17a() throws Exception {\n" +
- " FileReader reader17a = new FileReader(\"file\");\n" +
- " FileReader readerCopya;" +
- " readerCopya = reader17a;\n" +
- " bar(readerCopya);\n" + // potentially closes
- " }\n" +
- " void bar(FileReader r) {}\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 9)\n" +
- " FileReader reader17a = new FileReader(\"file\");\n" +
- " ^^^^^^^^^\n" +
- "Potential resource leak: 'reader17a' may not be closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// multiple early exists from nested scopes (always closed)
-public void test056zz() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " void foo16() throws Exception {\n" +
- " FileReader reader16 = new FileReader(\"file\");\n" +
- " try {\n" +
- " reader16.close();\n " +
- " return;\n" +
- " } catch (RuntimeException re) {\n" +
- " return;\n" +
- " } catch (Error e) {\n" +
- " return;\n" +
- " } finally {\n" +
- " reader16.close();\n " +
- " }\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " FileReader reader16 = new FileReader(\"file\");\n" +
- " ^^^^^^^^\n" +
- "Resource 'reader16' should be managed by try-with-resource\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 349326 - [1.7] new warning for missing try-with-resources
-// multiple early exists from nested scopes (never closed)
-public void test056zzz() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " void foo16() throws Exception {\n" +
- " FileReader reader16 = new FileReader(\"file\");\n" +
- " try {\n" +
- " return;\n" +
- " } catch (RuntimeException re) {\n" +
- " return;\n" +
- " } catch (Error e) {\n" +
- " return;\n" +
- " } finally {\n" +
- " System.out.println();\n " +
- " }\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " FileReader reader16 = new FileReader(\"file\");\n" +
- " ^^^^^^^^\n" +
- "Resource leak: 'reader16' is never closed\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
-// explicit throw is a true method exit here
-public void test056throw1() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " void foo2(boolean a, boolean b, boolean c) throws Exception {\n" +
- " FileReader reader = new FileReader(\"file\");\n" +
- " if(a)\n" +
- " throw new Exception(); //warning 1\n" +
- " else if (b)\n" +
- " reader.close();\n" +
- " else if(c)\n" +
- " throw new Exception(); //warning 2\n" +
- " reader.close();\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " throw new Exception(); //warning 1\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Resource leak: 'reader' is not closed at this location\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 10)\n" +
- " throw new Exception(); //warning 2\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Resource leak: 'reader' is not closed at this location\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
-// close() within finally provides protection for throw
-public void test056throw2() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " void foo1() throws Exception {\n" +
- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
- " try {\n" +
- " reader.read();\n" +
- " return;\n" +
- " } catch (Exception e) {\n" +
- " throw new Exception();\n" +
- " } finally {\n" +
- " reader.close();\n" +
- " }\n" +
- " }\n" +
- "\n" +
- " void foo2() throws Exception {\n" +
- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
- " try {\n" +
- " reader.read();\n" +
- " throw new Exception(); // should not warn here\n" +
- " } catch (Exception e) {\n" +
- " throw new Exception();\n" +
- " } finally {\n" +
- " reader.close();\n" +
- " }\n" +
- " }\n" +
- "\n" +
- " void foo3() throws Exception {\n" +
- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
- " try {\n" +
- " reader.read();\n" +
- " throw new Exception();\n" +
- " } finally {\n" +
- " reader.close();\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
- " ^^^^^^\n" +
- "Resource 'reader' should be managed by try-with-resource\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 16)\n" +
- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
- " ^^^^^^\n" +
- "Resource 'reader' should be managed by try-with-resource\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 28)\n" +
- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
- " ^^^^^^\n" +
- "Resource 'reader' should be managed by try-with-resource\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
-// close() nested within finally provides protection for throw
-public void test056throw3() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " void foo2x() throws Exception {\n" +
- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
- " try {\n" +
- " reader.read();\n" +
- " throw new Exception(); // should not warn here\n" +
- " } catch (Exception e) {\n" +
- " throw new Exception();\n" +
- " } finally {\n" +
- " if (reader != null)\n" +
- " try {\n" +
- " reader.close();\n" +
- " } catch (java.io.IOException io) {}\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
- " ^^^^^^\n" +
- "Resource 'reader' should be managed by try-with-resource\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
-// additional boolean should shed doubt on whether we reach the close() call
-public void test056throw4() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " void foo2x(boolean b) throws Exception {\n" +
- " FileReader reader = new FileReader(\"file\");\n" +
- " try {\n" +
- " reader.read();\n" +
- " throw new Exception(); // should warn here\n" +
- " } catch (Exception e) {\n" +
- " throw new Exception(); // should warn here\n" +
- " } finally {\n" +
- " if (reader != null && b)\n" + // this condition is too strong to protect reader
- " try {\n" +
- " reader.close();\n" +
- " } catch (java.io.IOException io) {}\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " throw new Exception(); // should warn here\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Potential resource leak: 'reader' may not be closed at this location\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 9)\n" +
- " throw new Exception(); // should warn here\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Potential resource leak: 'reader' may not be closed at this location\n" +
- "----------\n",
- null,
- true,
- options);
-}
-// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
-// similar to test056throw3() but indirectly calling close(), so doubts remain.
-public void test056throw5() {
- Map options = getCompilerOptions();
- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.FileReader;\n" +
- "public class X {\n" +
- " void foo2x() throws Exception {\n" +
- " FileReader reader = new FileReader(\"file\");\n" +
- " try {\n" +
- " reader.read();\n" +
- " throw new Exception(); // should warn 'may not' here\n" +
- " } catch (Exception e) {\n" +
- " throw new Exception(); // should warn 'may not' here\n" +
- " } finally {\n" +
- " doClose(reader);\n" +
- " }\n" +
- " }\n" +
- " void doClose(FileReader r) { try { r.close(); } catch (java.io.IOException ex) {}}\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " throw new Exception(); // should warn \'may not\' here\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Potential resource leak: 'reader' may not be closed at this location\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 9)\n" +
- " throw new Exception(); // should warn \'may not\' here\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Potential resource leak: 'reader' may not be closed at this location\n" +
- "----------\n",
- null,
- true,
- options);
-}
+
+// Note: test056* have been moved to ResourceLeakTests.java
+
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=361053
public void test057() {
this.runConformTest(
@@ -5226,6 +3498,134 @@ public void test058() {
"}\n"
}, "");
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=367566 - In try-with-resources statement close() method of resource is not called
+public void test059() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.IOException;\n" +
+ "\n" +
+ "public class X implements java.lang.AutoCloseable {\n" +
+ " static boolean isOpen = true;\n" +
+ " public static void main(final String[] args) throws IOException {\n" +
+ " foo();\n" +
+ " System.out.println(isOpen);\n" +
+ " }\n" +
+ " static boolean foo() {\n" +
+ " try (final X x = new X()) {\n" +
+ " return x.num() >= 1;\n" +
+ " }\n" +
+ " }\n" +
+ " int num() { return 2; }\n" +
+ " public void close() {\n" +
+ " isOpen = false;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "false");
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=367566 - In try-with-resources statement close() method of resource is not called
+public void test060() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X implements AutoCloseable {\n" +
+ " static int num = 10 ;\n" +
+ " public static void main(String [] args) throws Exception { \n" +
+ " System.out.println(foo(1));\n" +
+ " System.out.println(foo(2));\n" +
+ " System.out.println(foo(3));\n" +
+ " }\n" +
+ " private static boolean foo(int where) throws Exception {\n" +
+ " final boolean getOut = true;\n" +
+ " System.out.println(\"Main\");\n" +
+ " try (X x1 = new X(); X x2 = new X()) {\n" +
+ " if (where == 1) {\n" +
+ " return where == 1;\n" +
+ " }\n" +
+ " System.out.println(\"Outer Try\");\n" +
+ " while (true) {\n" +
+ " try (Y y1 = new Y(); Y y2 = new Y()) { \n" +
+ " if (where == 2) {\n" +
+ " return where == 2;\n" +
+ " } \n" +
+ " System.out.println(\"Middle Try\");\n" +
+ " try (Z z1 = new Z(); Z z2 = new Z()) {\n" +
+ " System.out.println(\"Inner Try\");\n" +
+ " if (getOut) \n" +
+ " return num >= 10;\n" +
+ " else\n" +
+ " break; \n" +
+ " }\n" +
+ " }\n" +
+ " }\n" +
+ " System.out.println(\"Out of while\");\n" +
+ " }\n" +
+ " return false;\n" +
+ " }\n" +
+ " public X() {\n" +
+ " System.out.println(\"X::X\");\n" +
+ " }\n" +
+ " @Override\n" +
+ " public void close() throws Exception {\n" +
+ " System.out.println(\"X::~X\");\n" +
+ " }\n" +
+ "}\n" +
+ "class Y implements AutoCloseable {\n" +
+ " public Y() {\n" +
+ " System.out.println(\"Y::Y\");\n" +
+ " }\n" +
+ " @Override\n" +
+ " public void close() throws Exception {\n" +
+ " System.out.println(\"Y::~Y\");\n" +
+ " }\n" +
+ "}\n" +
+ "class Z implements AutoCloseable {\n" +
+ " public Z() {\n" +
+ " System.out.println(\"Z::Z\");\n" +
+ " }\n" +
+ " @Override\n" +
+ " public void close() throws Exception {\n" +
+ " System.out.println(\"Z::~Z\");\n" +
+ " }\n" +
+ "}\n"
+ },
+ "Main\n" +
+ "X::X\n" +
+ "X::X\n" +
+ "X::~X\n" +
+ "X::~X\n" +
+ "true\n" +
+ "Main\n" +
+ "X::X\n" +
+ "X::X\n" +
+ "Outer Try\n" +
+ "Y::Y\n" +
+ "Y::Y\n" +
+ "Y::~Y\n" +
+ "Y::~Y\n" +
+ "X::~X\n" +
+ "X::~X\n" +
+ "true\n" +
+ "Main\n" +
+ "X::X\n" +
+ "X::X\n" +
+ "Outer Try\n" +
+ "Y::Y\n" +
+ "Y::Y\n" +
+ "Middle Try\n" +
+ "Z::Z\n" +
+ "Z::Z\n" +
+ "Inner Try\n" +
+ "Z::~Z\n" +
+ "Z::~Z\n" +
+ "Y::~Y\n" +
+ "Y::~Y\n" +
+ "X::~X\n" +
+ "X::~X\n" +
+ "true");
+}
public static Class testClass() {
return TryWithResourcesStatementTest.class;
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/XLargeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/XLargeTest.java
index ecb738769..215c9e6ff 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/XLargeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/XLargeTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -30,6 +30,100 @@ public static Test suite() {
return buildAllCompliancesTestSuite(testClass());
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=368435
+public void test368435() {
+ Map settings = getCompilerOptions();
+ settings.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
+ StringBuffer sourceCode = new StringBuffer(
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ " public void print() {\n" +
+ " int i = 0;\n" +
+ " if (System.currentTimeMillis() > 17000L) {\n" +
+ " System.out.println(i++);\n");
+
+ for (int i = 0; i < 5000; i++) {
+ sourceCode.append("\t\t System.out.println(\"xyz\");\n");
+ }
+ sourceCode.append("}\n}\n}\n");
+
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ sourceCode.toString()
+ },
+ "SUCCESS",
+ null,
+ true,
+ null,
+ settings,
+ null);
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=368435
+public void test368435b() {
+ Map settings = getCompilerOptions();
+ settings.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
+ StringBuffer sourceCode = new StringBuffer(
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ " public X() {\n" +
+ " int i = 0;\n" +
+ " if (System.currentTimeMillis() > 17000L) {\n" +
+ " System.out.println(i++);\n");
+
+ for (int i = 0; i < 5000; i++) {
+ sourceCode.append("\t\t System.out.println(\"xyz\");\n");
+ }
+ sourceCode.append("}\n}\n}\n");
+
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ sourceCode.toString()
+ },
+ "SUCCESS",
+ null,
+ true,
+ null,
+ settings,
+ null);
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=368435
+public void test368435c() {
+ Map settings = getCompilerOptions();
+ settings.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
+ StringBuffer sourceCode = new StringBuffer(
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ " {\n" +
+ " int i = 0;\n" +
+ " if (System.currentTimeMillis() > 17000L) {\n" +
+ " System.out.println(i++);\n");
+
+ for (int i = 0; i < 5000; i++) {
+ sourceCode.append("\t\t System.out.println(\"xyz\");\n");
+ }
+ sourceCode.append("}\n}\n}\n");
+
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ sourceCode.toString()
+ },
+ "SUCCESS",
+ null,
+ true,
+ null,
+ settings,
+ null);
+}
+
public void test001() {
this.runConformTest(
new String[] {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java
index 8b4171218..70415afd8 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java
@@ -1348,6 +1348,34 @@ private static void zip(File dir, ZipOutputStream zip, int rootPathLength) throw
}
}
}
+
+/**
+ * Zips the given files into the given jar. All the files are kept at the root of the zip.
+ */
+public static void zipFiles(File[] files, String zipPath) throws IOException {
+ File zipFile = new File(zipPath);
+ if (zipFile.exists()) {
+ if (!delete(zipFile))
+ throw new IOException("Could not delete " + zipPath);
+ // ensure the new zip file has a different timestamp than the previous one
+ int timeToWait = 1000; // some platform (like Linux) have a 1s granularity)
+ waitAtLeast(timeToWait);
+ } else {
+ zipFile.getParentFile().mkdirs();
+ }
+ ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(zipFile));
+ try {
+ for (int i = 0, length = files.length; i < length; i++) {
+ File file = files[i];
+ ZipEntry entry = new ZipEntry(file.getName());
+ zip.putNextEntry(entry);
+ zip.write(org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file));
+ zip.closeEntry();
+ }
+ } finally {
+ zip.close();
+ }
+}
/**
* Returns the compilation errors / warnings for the given CompilationResult.
*

Back to the top