diff options
author | Stephan Herrmann | 2012-01-28 19:42:28 +0000 |
---|---|---|
committer | Stephan Herrmann | 2012-01-28 19:42:28 +0000 |
commit | 2c38ab4d76d7def0495e781b84c159ff2b585512 (patch) | |
tree | d4e6d53cca5f3dd7402b444af6018b432d29887f /org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler | |
parent | 8574731a0f2dc482cebc92613334e05b97ad83d0 (diff) | |
download | org.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/src/org/eclipse/jdt/core/tests/compiler')
19 files changed, 9140 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[] { |