Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 204041 Details for
Bug 349326
[1.7] new warning for missing try-with-resources
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
patch v1.0.0
Bug_349326_v1.0.0.patch (text/plain), 159.59 KB, created by
Stephan Herrmann
on 2011-09-26 22:06:33 EDT
(
hide
)
Description:
patch v1.0.0
Filename:
MIME Type:
Creator:
Stephan Herrmann
Created:
2011-09-26 22:06:33 EDT
Size:
159.59 KB
patch
obsolete
>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 eb6e3f7..2aa3691 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 >@@ -8,9 +8,11 @@ > * Contributors: > * IBM Corporation - initial API and implementation > * Benjamin Muskalla - Contribution for bug 239066 >- * Stephan Herrmann - Contribution for bug 236385 >- * 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 <stephan@cs.tu-berlin.de> - Contributions for >+ * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used >+ * bug 295551 - Add option to automatically promote all warnings to errors >+ * bug 185682 - Increment/decrement operators mark local variables as read >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.core.tests.compiler.regression; > >@@ -1816,6 +1818,7 @@ public void test012b(){ > " <option key=\"org.eclipse.jdt.core.compiler.problem.discouragedReference\" value=\"warning\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.emptyStatement\" value=\"ignore\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.enumIdentifier\" value=\"warning\"/>\n" + >+ " <option key=\"org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable\" value=\"ignore\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.fallthroughCase\" value=\"ignore\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.fatalOptionalError\" value=\"disabled\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.fieldHiding\" value=\"ignore\"/>\n" + >@@ -1857,6 +1860,7 @@ public void test012b(){ > " <option key=\"org.eclipse.jdt.core.compiler.problem.parameterAssignment\" value=\"ignore\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment\" value=\"ignore\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullReference\" value=\"ignore\"/>\n" + >+ " <option key=\"org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable\" value=\"ignore\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.rawTypeReference\" value=\"warning\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.redundantNullCheck\" value=\"ignore\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments\" value=\"ignore\"/>\n" + >@@ -1872,6 +1876,7 @@ public void test012b(){ > " <option key=\"org.eclipse.jdt.core.compiler.problem.typeParameterHiding\" value=\"warning\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems\" value=\"enabled\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation\" value=\"warning\"/>\n" + >+ " <option key=\"org.eclipse.jdt.core.compiler.problem.unclosedCloseable\" value=\"warning\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock\" value=\"ignore\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.unhandledWarningToken\" value=\"warning\"/>\n" + > " <option key=\"org.eclipse.jdt.core.compiler.problem.unnecessaryElse\" value=\"ignore\"/>\n" + >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 da7a3b6..4e1cba7 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 >@@ -8,7 +8,9 @@ > * Contributors: > * IBM Corporation - initial API and implementation > * Benjamin Muskalla - Contribution for bug 239066 >- * Stephan Herrmann - Contribution for bug 236385 >+ * Stephan Herrmann - Contributions for >+ * 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 > *******************************************************************************/ > package org.eclipse.jdt.core.tests.compiler.regression; > >@@ -440,6 +442,7 @@ public void test011_problem_categories() { > expectedProblemAttributes.put("ExceptionTypeInternalNameProvided", DEPRECATED); > expectedProblemAttributes.put("ExceptionTypeNotFound", DEPRECATED); > expectedProblemAttributes.put("ExceptionTypeNotVisible", DEPRECATED); >+ expectedProblemAttributes.put("ExplicitlyClosedAutoCloseable", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE)); > expectedProblemAttributes.put("ExpressionShouldBeAVariable", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX)); > expectedProblemAttributes.put("ExternalProblemFixable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL)); > expectedProblemAttributes.put("ExternalProblemNotFixable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL)); >@@ -765,6 +768,8 @@ public void test011_problem_categories() { > expectedProblemAttributes.put("PolymorphicMethodNotBelow17", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); > expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > 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("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); > expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); >@@ -828,6 +833,8 @@ public void test011_problem_categories() { > expectedProblemAttributes.put("TypeMissingDeprecatedAnnotation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE)); > expectedProblemAttributes.put("TypeParameterHidingType", new ProblemAttributes(CategorizedProblem.CAT_NAME_SHADOWING_CONFLICT)); > expectedProblemAttributes.put("UnboxingConversion", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE)); >+ expectedProblemAttributes.put("UnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); >+ expectedProblemAttributes.put("UnclosedCloseableAtExit", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("UndefinedAnnotationMember", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); > expectedProblemAttributes.put("UndefinedConstructor", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); > expectedProblemAttributes.put("UndefinedConstructorInDefaultConstructor", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); >@@ -1108,6 +1115,7 @@ public void test012_compiler_problems_tuning() { > expectedProblemAttributes.put("ExceptionTypeInternalNameProvided", SKIP); > expectedProblemAttributes.put("ExceptionTypeNotFound", SKIP); > expectedProblemAttributes.put("ExceptionTypeNotVisible", SKIP); >+ expectedProblemAttributes.put("ExplicitlyClosedAutoCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE)); > expectedProblemAttributes.put("ExpressionShouldBeAVariable", SKIP); > expectedProblemAttributes.put("ExternalProblemFixable", SKIP); > expectedProblemAttributes.put("ExternalProblemNotFixable", SKIP); >@@ -1433,6 +1441,8 @@ public void test012_compiler_problems_tuning() { > expectedProblemAttributes.put("PolymorphicMethodNotBelow17", SKIP); > expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT)); > 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("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE)); > expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP); > expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP); >@@ -1496,6 +1506,8 @@ public void test012_compiler_problems_tuning() { > expectedProblemAttributes.put("TypeMissingDeprecatedAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_DEPRECATED_ANNOTATION)); > expectedProblemAttributes.put("TypeParameterHidingType", new ProblemAttributes(JavaCore.COMPILER_PB_TYPE_PARAMETER_HIDING)); > expectedProblemAttributes.put("UnboxingConversion", new ProblemAttributes(JavaCore.COMPILER_PB_AUTOBOXING)); >+ expectedProblemAttributes.put("UnclosedCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE)); >+ expectedProblemAttributes.put("UnclosedCloseableAtExit", new ProblemAttributes(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE)); > expectedProblemAttributes.put("UndefinedAnnotationMember", SKIP); > expectedProblemAttributes.put("UndefinedConstructor", SKIP); > expectedProblemAttributes.put("UndefinedConstructorInDefaultConstructor", SKIP); >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 32b50af..5c83d04 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 >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann - Contribution for bug 236385 >+ * Stephan Herrmann - Contributions for >+ * 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 > *******************************************************************************/ > package org.eclipse.jdt.core.tests.compiler.regression; > >@@ -2360,6 +2362,52 @@ public void testBug338234d() { > "The local variable i may not have been initialized\n" + > "----------\n"); > } >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// variant < 1.7 using Closeable: not closed >+public void testCloseable1() { >+ 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); // not closed\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. WARNING in X.java (at line 7)\n" + >+ " FileReader fileReader = new FileReader(file); // not closed\n" + >+ " ^^^^^^^^^^\n" + >+ "Resource leak: 'fileReader' is never closed\n" + >+ "----------\n"); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// variant < 1.7 using Closeable: resource is closed, cannot suggest try-with-resources < 1.7 >+public void testCloseable2() { >+ 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); // not closed\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " fileReader.close();\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/NullReferenceTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java >index 5d3e349..371a228 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 >@@ -6029,12 +6029,17 @@ public void test0562_try_catch_unchecked_exception() { > " }\n" + > " }\n" + > "}\n"}, >- "----------\n" + >- "1. ERROR in X.java (at line 8)\n" + >- " o.toString();\n" + >- " ^\n" + >- "Potential null pointer access: The variable o may be null at this location\n" + >- "----------\n", >+ "----------\n" + >+ "1. WARNING in X.java (at line 6)\n" + >+ " o = new LineNumberReader(new FileReader(\"dummy\"));\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: \'o\' is never closed\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 8)\n" + >+ " o.toString();\n" + >+ " ^\n" + >+ "Potential null pointer access: The variable o may be null at this location\n" + >+ "----------\n", > JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); > } > >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 e178b04..3d71c4f 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 >@@ -7,18 +7,20 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > 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; > public class TryWithResourcesStatementTest extends AbstractRegressionTest { > > static { >-// TESTS_NAMES = new String[] { "test055", "test055a" }; >+// TESTS_NAMES = new String[] { "test056" }; > // TESTS_NUMBERS = new int[] { 50 }; > // TESTS_RANGE = new int[] { 11, -1 }; > } >@@ -485,12 +487,17 @@ public void test014() { > " ^^\n" + > "Dead code\n" + > "----------\n" + >- "3. ERROR in X.java (at line 5)\n" + >+ "3. WARNING in X.java (at line 5)\n" + >+ " Y why = new Y();\n" + >+ " ^^^\n" + >+ "Resource leak: 'why' is never closed\n" + >+ "----------\n" + >+ "4. ERROR in X.java (at line 5)\n" + > " Y why = new Y();\n" + > " ^^^^^^^\n" + > "Unhandled exception type WeirdException\n" + > "----------\n" + >- "4. WARNING in X.java (at line 22)\n" + >+ "5. WARNING in X.java (at line 22)\n" + > " class WeirdException extends Throwable {}\n" + > " ^^^^^^^^^^^^^^\n" + > "The serializable class WeirdException does not declare a static final serialVersionUID field of type long\n" + >@@ -558,12 +565,17 @@ public void test016() { > " ^^\n" + > "Dead code\n" + > "----------\n" + >- "3. ERROR in X.java (at line 5)\n" + >+ "3. WARNING in X.java (at line 5)\n" + >+ " Y why = new Y();\n" + >+ " ^^^\n" + >+ "Resource leak: 'why' is never closed\n" + >+ "----------\n" + >+ "4. ERROR in X.java (at line 5)\n" + > " Y why = new Y();\n" + > " ^^^^^^^\n" + > "Unhandled exception type WeirdException\n" + > "----------\n" + >- "4. WARNING in X.java (at line 20)\n" + >+ "5. WARNING in X.java (at line 20)\n" + > " class WeirdException extends Throwable {}\n" + > " ^^^^^^^^^^^^^^\n" + > "The serializable class WeirdException does not declare a static final serialVersionUID field of type long\n" + >@@ -3380,6 +3392,1412 @@ 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 >+// disabled due to Bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis >+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;// warning 1\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 2\n" + >+ " reader2 = reader1;// warning 3\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 4)\n" + >+ " FileReader reader1 = new FileReader(\"file1\");\n" + >+ " ^^^^^^^\n" + >+ "Resource leak: \'reader1\' is never closed\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 4)\n" + >+ " reader2 = reader1;// warning 1\n" + >+ " ^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: \'reader2\' is not closed at this location\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 13)\n" + >+ " reader2 = reader1;// warning 2\n" + >+ " ^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: \'reader2\' is not closed at this location\n" + >+ "----------\n" + >+ "4. ERROR in X.java (at line 14)\n" + >+ " reader2 = reader1;// warning 3\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 >+// pb reported in https://bugs.eclipse.org/bugs/show_bug.cgi?id=349326#c70 >+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_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 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. ERROR in X.java (at line 27)\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); >+} > public static Class testClass() { > return TryWithResourcesStatementTest.class; > } >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java >index fa88bd9..4375e48 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java >@@ -116,7 +116,12 @@ > * Benjamin Muskalla - added the following constants > * MissingSynchronizedModifierInInheritedMethod > * Stephan Herrmann - added the following constants >- * UnusedObjectAllocation >+ * UnusedObjectAllocation >+ * PotentiallyUnclosedCloseable >+ * PotentiallyUnclosedCloseableAtExit >+ * UnclosedCloseable >+ * UnclosedCloseableAtExit >+ * ExplicitlyClosedAutoCloseable > *******************************************************************************/ > package org.eclipse.jdt.core.compiler; > >@@ -1394,6 +1399,16 @@ void setSourceStart(int sourceStart); > int DiamondNotBelow17 = TypeRelated + 883; > /** @since 3.7.1 */ > int RedundantSpecificationOfTypeArguments = TypeRelated + 884; >+ /** @since 3.8 */ >+ int PotentiallyUnclosedCloseable = Internal + 885; >+ /** @since 3.8 */ >+ int PotentiallyUnclosedCloseableAtExit = Internal + 886; >+ /** @since 3.8 */ >+ int UnclosedCloseable = Internal + 887; >+ /** @since 3.8 */ >+ int UnclosedCloseableAtExit = Internal + 888; >+ /** @since 3.8 */ >+ int ExplicitlyClosedAutoCloseable = Internal + 889; > /** > * External problems -- These are problems defined by other plugins > */ >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java >index 2519ee4..6baa903 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java >@@ -10,6 +10,7 @@ > * Stephan Herrmann - Contributions for > * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used > * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -42,6 +43,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > // process arguments > if (this.arguments != null) { > for (int i = 0, count = this.arguments.length; i < count; i++) { >+ // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.) >+ flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo); > flowInfo = > this.arguments[i] > .analyseCode(currentScope, flowContext, flowInfo) >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java >index 5404643..6a8fa14 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java >@@ -12,6 +12,7 @@ > * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE > * bug 292478 - Report potentially null across variable assignment > * bug 335093 - [compiler][null] minimal hook for future null annotation support >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -47,6 +48,16 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > flowInfo = ((Reference) this.lhs) > .analyseAssignment(currentScope, flowContext, flowInfo, this, false) > .unconditionalInits(); >+ if (local != null) { >+ LocalVariableBinding previousTrackerBinding = null; >+ if (local.closeTracker != null) { >+ // Assigning to a variable already holding an AutoCloseable, has it been closed before? >+ previousTrackerBinding = local.closeTracker.binding; >+ if (!flowInfo.isDefinitelyNull(local)) // only if previous value may be non-null >+ local.closeTracker.recordErrorLocation(this, flowInfo.nullStatus(previousTrackerBinding)); >+ } >+ FakedTrackingVariable.handleResourceAssignment(flowInfo, this, this.expression, local, previousTrackerBinding); >+ } > int nullStatus = this.expression.nullStatus(flowInfo); > if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { > if (nullStatus == FlowInfo.NULL) { >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java >index cb789a4..f446ce9 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2009 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 >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -32,10 +33,12 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > int complaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED; > for (int i = 0, max = this.statements.length; i < max; i++) { > Statement stat = this.statements[i]; >- if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel)) < Statement.COMPLAINED_UNREACHABLE) { >+ if ((complaintLevel = stat.complainIfUnreachable(flowInfo, flowContext, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) { > flowInfo = stat.analyseCode(this.scope, flowContext, flowInfo); > } > } >+ if (this.explicitDeclarations > 0) // if block has its own scope analyze tracking vars now: >+ this.scope.checkUnclosedCloseables(flowInfo, flowContext, null); > return flowInfo; > } > /** >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java >index f5d9416..9ff71db 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java >@@ -12,6 +12,7 @@ > * bug 292478 - Report potentially null across variable assignment > * bug 324178 - [null] ConditionalExpression.nullStatus(..) doesn't take into account the analysis of condition itself > * bug 354554 - [null] conditional with redundant condition yields weak error message >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -65,7 +66,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, > trueFlowInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); > } > if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) { >- this.valueIfTrue.complainIfUnreachable(trueFlowInfo, currentScope, initialComplaintLevel); >+ this.valueIfTrue.complainIfUnreachable(trueFlowInfo, flowContext, currentScope, initialComplaintLevel, false); > } > } > this.trueInitStateIndex = currentScope.methodScope().recordInitializationStates(trueFlowInfo); >@@ -78,7 +79,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, > falseFlowInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); > } > if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) { >- this.valueIfFalse.complainIfUnreachable(falseFlowInfo, currentScope, initialComplaintLevel); >+ this.valueIfFalse.complainIfUnreachable(falseFlowInfo, flowContext, currentScope, initialComplaintLevel, true); > } > } > this.falseInitStateIndex = currentScope.methodScope().recordInitializationStates(falseFlowInfo); >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java >index e7c790a..99def1c 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann - Contribution for Bug 343713 - [compiler] bogus line number in constructor of inner class in 1.5 compliance >+ * Stephan Herrmann - Contributions for >+ * bug 343713 - [compiler] bogus line number in constructor of inner class in 1.5 compliance >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -151,7 +153,7 @@ public void analyseCode(ClassScope classScope, InitializationFlowContext initial > int complaintLevel = (nonStaticFieldInfoReachMode & FlowInfo.UNREACHABLE) == 0 ? Statement.NOT_COMPLAINED : Statement.COMPLAINED_FAKE_REACHABLE; > for (int i = 0, count = this.statements.length; i < count; i++) { > Statement stat = this.statements[i]; >- if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel)) < Statement.COMPLAINED_UNREACHABLE) { >+ if ((complaintLevel = stat.complainIfUnreachable(flowInfo, constructorContext, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) { > flowInfo = stat.analyseCode(this.scope, constructorContext, flowInfo); > } > } >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java >index d6cbd10..b74fded 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2009 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 >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -29,12 +30,12 @@ public class EmptyStatement extends Statement { > } > > // Report an error if necessary >- public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int complaintLevel) { >+ public int complainIfUnreachable(FlowInfo flowInfo, FlowContext flowContext, BlockScope scope, int complaintLevel, boolean endOfBlock) { > // before 1.4, empty statements are tolerated anywhere > if (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_4) { > return complaintLevel; > } >- return super.complainIfUnreachable(flowInfo, scope, complaintLevel); >+ return super.complainIfUnreachable(flowInfo, flowContext, scope, complaintLevel, endOfBlock); > } > > public void generateCode(BlockScope currentScope, CodeStream codeStream){ >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java >index 41e569b..e816169 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * Stephan Herrmann - Contributions for >+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -138,7 +140,7 @@ public class ForStatement extends Statement { > actionInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); > } > } >- if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel) < Statement.COMPLAINED_UNREACHABLE) { >+ if (this.action.complainIfUnreachable(actionInfo, flowContext, this.scope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) { > actionInfo = this.action.analyseCode(this.scope, loopingContext, actionInfo).unconditionalInits(); > } > >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java >index 17693c8..6d8e62d 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -99,7 +100,7 @@ public class ForeachStatement extends Statement { > if (!(this.action == null || (this.action.isEmptyBlock() > && currentScope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_3))) { > >- if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel) < Statement.COMPLAINED_UNREACHABLE) { >+ if (this.action.complainIfUnreachable(actionInfo, flowContext, this.scope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) { > actionInfo = this.action.analyseCode(this.scope, loopingContext, actionInfo).unconditionalCopy(); > } > >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java >index 2f3b1a7..2b9c876 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * Stephan Herrmann - Contributions for >+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -89,7 +91,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > this.thenInitStateIndex = currentScope.methodScope().recordInitializationStates(thenFlowInfo); > if (isConditionOptimizedFalse || ((this.bits & ASTNode.IsThenStatementUnreachable) != 0)) { > if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) { >- this.thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, initialComplaintLevel); >+ this.thenStatement.complainIfUnreachable(thenFlowInfo, flowContext, currentScope, initialComplaintLevel, false); > } else { > // its a known coding pattern which should be tolerated by dead code analysis > // according to isKnowDeadCodePattern() >@@ -115,7 +117,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > this.elseInitStateIndex = currentScope.methodScope().recordInitializationStates(elseFlowInfo); > if (isConditionOptimizedTrue || ((this.bits & ASTNode.IsElseStatementUnreachable) != 0)) { > if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) { >- this.elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, initialComplaintLevel); >+ this.elseStatement.complainIfUnreachable(elseFlowInfo, flowContext, currentScope, initialComplaintLevel, false); > } else { > // its a known coding pattern which should be tolerated by dead code analysis > // according to isKnowDeadCodePattern() >@@ -124,6 +126,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > } > elseFlowInfo = this.elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo); > } >+ // process AutoCloseable resources closed in only one branch: >+ currentScope.correlateTrackingVarsIfElse(thenFlowInfo, elseFlowInfo); > // merge THEN & ELSE initializations > FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranchesIfElse( > thenFlowInfo, >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java >index 7606dc4..b11e476 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java >@@ -11,6 +11,7 @@ > * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE > * bug 292478 - Report potentially null across variable assignment > * bug 335093 - [compiler][null] minimal hook for future null annotation support >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -76,6 +77,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > this.initialization > .analyseCode(currentScope, flowContext, flowInfo) > .unconditionalInits(); >+ FakedTrackingVariable.handleResourceAssignment(flowInfo, this, this.initialization, this.binding, null); > int nullStatus = this.initialization.nullStatus(flowInfo); > if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes > this.bits |= FirstAssignmentToLocal; >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java >index f913302..795a345 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java >@@ -8,7 +8,9 @@ > * Contributors: > * IBM Corporation - initial API and implementation > * Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752) >- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * Stephan Herrmann - Contributions for >+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -38,6 +40,7 @@ import org.eclipse.jdt.internal.compiler.lookup.Scope; > import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; > import org.eclipse.jdt.internal.compiler.lookup.TagBits; > import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; >+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; > import org.eclipse.jdt.internal.compiler.lookup.TypeIds; > import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; > >@@ -60,6 +63,18 @@ public class MessageSend extends Expression implements InvocationSite { > public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { > boolean nonStatic = !this.binding.isStatic(); > flowInfo = this.receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits(); >+ // recording the closing of AutoCloseable resources: >+ if (CharOperation.equals(TypeConstants.CLOSE, this.selector)) >+ { >+ FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.receiver); >+ if (trackingVariable != null) { // null happens if receiver is not a local variable or not an AutoCloseable >+ if (trackingVariable.methodScope == currentScope.methodScope()) { >+ trackingVariable.markClose(flowInfo, flowContext); >+ } else { >+ trackingVariable.markClosedInNestedMethod(); >+ } >+ } >+ } > if (nonStatic) { > this.receiver.checkNPE(currentScope, flowContext, flowInfo); > // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682 >@@ -80,6 +95,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) { > this.arguments[i].checkNPE(currentScope, flowContext, flowInfo); > } >+ // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.) >+ flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo); > flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); > } > } >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java >index 53fade3..ab7e7f6 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -100,7 +101,7 @@ public class MethodDeclaration extends AbstractMethodDeclaration { > int complaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) == 0 ? Statement.NOT_COMPLAINED : Statement.COMPLAINED_FAKE_REACHABLE; > for (int i = 0, count = this.statements.length; i < count; i++) { > Statement stat = this.statements[i]; >- if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel)) < Statement.COMPLAINED_UNREACHABLE) { >+ if ((complaintLevel = stat.complainIfUnreachable(flowInfo, methodContext, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) { > flowInfo = stat.analyseCode(this.scope, methodContext, flowInfo); > } > } >@@ -134,6 +135,7 @@ public class MethodDeclaration extends AbstractMethodDeclaration { > } > > } >+ this.scope.checkUnclosedCloseables(flowInfo, methodContext, null/*don't report against a specific location*/); > } catch (AbortMethod e) { > this.ignoreFurtherInvestigation = true; > } >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java >index 6818e1d..ed65559 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * Stephan Herrmann - Contributions for >+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -72,6 +74,8 @@ public class QualifiedAllocationExpression extends AllocationExpression { > // process arguments > if (this.arguments != null) { > for (int i = 0, count = this.arguments.length; i < count; i++) { >+ // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.) >+ flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo); > flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo); > if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) { > this.arguments[i].checkNPE(currentScope, flowContext, flowInfo); >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java >index b3f2ede..1be2ead 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * Stephan Herrmann - Contributions for >+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -40,6 +42,14 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) { > this.expression.checkNPE(currentScope, flowContext, flowInfo); > } >+ FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.expression); >+ if (trackingVariable != null) { >+ if (currentScope.methodScope() != trackingVariable.methodScope) >+ trackingVariable.markClosedInNestedMethod(); >+ // don't report issues concerning this local, since by returning >+ // the method passes the responsibility to the caller: >+ currentScope.removeTrackingVar(trackingVariable); >+ } > } > this.initStateIndex = > currentScope.methodScope().recordInitializationStates(flowInfo); >@@ -104,6 +114,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > this.expression.bits |= ASTNode.IsReturnedValue; > } > } >+ currentScope.checkUnclosedCloseables(flowInfo, null/*ignore exception exits from flowContext*/, this); > return FlowInfo.DEAD_END; > } > >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java >index e1b10d9..fb056b6 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann - Contribution for bug 335093 - [compiler][null] minimal hook for future null annotation support >+ * Stephan Herrmann - Contributions for >+ * bug 335093 - [compiler][null] minimal hook for future null annotation support >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -70,18 +72,22 @@ public void branchChainTo(BranchLabel label) { > > // Report an error if necessary (if even more unreachable than previously reported > // complaintLevel = 0 if was reachable up until now, 1 if fake reachable (deadcode), 2 if fatal unreachable (error) >-public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int previousComplaintLevel) { >+public int complainIfUnreachable(FlowInfo flowInfo, FlowContext flowContext, BlockScope scope, int previousComplaintLevel, boolean endOfBlock) { > if ((flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0) { > if ((flowInfo.reachMode() & FlowInfo.UNREACHABLE_OR_DEAD) != 0) > this.bits &= ~ASTNode.IsReachable; > if (flowInfo == FlowInfo.DEAD_END) { > if (previousComplaintLevel < COMPLAINED_UNREACHABLE) { > scope.problemReporter().unreachableCode(this); >+ if (endOfBlock) >+ scope.checkUnclosedCloseables(flowInfo, flowContext, null); > } > return COMPLAINED_UNREACHABLE; > } else { > if (previousComplaintLevel < COMPLAINED_FAKE_REACHABLE) { > scope.problemReporter().fakeReachable(this); >+ if (endOfBlock) >+ scope.checkUnclosedCloseables(flowInfo, flowContext, null); > } > return COMPLAINED_FAKE_REACHABLE; > } >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java >index 5b171fc..21c1ca0 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * Stephan Herrmann - Contributions for >+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -99,7 +101,7 @@ public class SwitchStatement extends Statement { > } else { > fallThroughState = FALLTHROUGH; // reset below if needed > } >- if ((complaintLevel = statement.complainIfUnreachable(caseInits, this.scope, complaintLevel)) < Statement.COMPLAINED_UNREACHABLE) { >+ if ((complaintLevel = statement.complainIfUnreachable(caseInits, flowContext, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) { > caseInits = statement.analyseCode(this.scope, switchContext, caseInits); > if (caseInits == FlowInfo.DEAD_END) { > fallThroughState = ESCAPING; >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java >index 5fc3878..056dde0 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann - Contribution for bug 332637 - Dead Code detection removing code that isn't dead >+ * Stephan Herrmann - Contributions for >+ * bug 332637 - Dead Code detection removing code that isn't dead >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -124,8 +126,14 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > for (int i = 0; i < resourcesLength; i++) { > flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy()); > this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(flowInfo); >- this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. >- TypeBinding type = this.resources[i].binding.type; >+ LocalVariableBinding resourceBinding = this.resources[i].binding; >+ resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. >+ if (resourceBinding.closeTracker != null) { >+ // this was false alarm, we don't need to track the resource >+ this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker); >+ resourceBinding.closeTracker = null; >+ } >+ TypeBinding type = resourceBinding.type; > if (type != null && type.isValidBinding()) { > ReferenceBinding binding = (ReferenceBinding) type; > MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter >@@ -250,8 +258,14 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > for (int i = 0; i < resourcesLength; i++) { > flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy()); > this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(flowInfo); >- this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. >- TypeBinding type = this.resources[i].binding.type; >+ LocalVariableBinding resourceBinding = this.resources[i].binding; >+ resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. >+ if (resourceBinding.closeTracker != null) { >+ // this was false alarm, we don't need to track the resource >+ this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker); >+ resourceBinding.closeTracker = null; >+ } >+ TypeBinding type = resourceBinding.type; > if (type != null && type.isValidBinding()) { > ReferenceBinding binding = (ReferenceBinding) type; > MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java >index c51042e..8ead6d4 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * Stephan Herrmann - Contributions for >+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -113,7 +115,7 @@ public class WhileStatement extends Statement { > currentScope.methodScope().recordInitializationStates( > condInfo.initsWhenTrue()); > >- if (this.action.complainIfUnreachable(actionInfo, currentScope, initialComplaintLevel) < Statement.COMPLAINED_UNREACHABLE) { >+ if (this.action.complainIfUnreachable(actionInfo, flowContext, currentScope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) { > actionInfo = this.action.analyseCode(currentScope, loopingContext, actionInfo); > } > >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java >index d5b5a3d..8b992d7 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java >@@ -13,6 +13,7 @@ > * bug 292478 - Report potentially null across variable assignment > * bug 332637 - Dead Code detection removing code that isn't dead > * bug 341499 - [compiler][null] allocate extra bits in all methods of UnconditionalFlowInfo >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.flow; > >@@ -770,7 +771,7 @@ final public boolean isDefinitelyNonNull(LocalVariableBinding local) { > } > int vectorIndex; > if ((vectorIndex = (position / BitCacheSize) - 1) >- >= this.extra[0].length) { >+ >= this.extra[2].length) { > return false; // if not enough room in vector, then not initialized > } > return ((this.extra[2][vectorIndex] & this.extra[4][vectorIndex] >@@ -797,7 +798,7 @@ final public boolean isDefinitelyNull(LocalVariableBinding local) { > } > int vectorIndex; > if ((vectorIndex = (position / BitCacheSize) - 1) >= >- this.extra[0].length) { >+ this.extra[2].length) { > return false; // if not enough room in vector, then not initialized > } > return ((this.extra[2][vectorIndex] & this.extra[3][vectorIndex] >@@ -822,7 +823,7 @@ final public boolean isDefinitelyUnknown(LocalVariableBinding local) { > } > int vectorIndex; > if ((vectorIndex = (position / BitCacheSize) - 1) >= >- this.extra[0].length) { >+ this.extra[2].length) { > return false; // if not enough room in vector, then not initialized > } > return ((this.extra[2][vectorIndex] & this.extra[5][vectorIndex] >@@ -882,7 +883,7 @@ final public boolean isPotentiallyNonNull(LocalVariableBinding local) { > } > int vectorIndex; > if ((vectorIndex = (position / BitCacheSize) - 1) >= >- this.extra[0].length) { >+ this.extra[2].length) { > return false; // if not enough room in vector, then not initialized > } > return ((this.extra[4][vectorIndex] >@@ -908,7 +909,7 @@ final public boolean isPotentiallyNull(LocalVariableBinding local) { > } > int vectorIndex; > if ((vectorIndex = (position / BitCacheSize) - 1) >= >- this.extra[0].length) { >+ this.extra[2].length) { > return false; // if not enough room in vector, then not initialized > } > return ((this.extra[3][vectorIndex] >@@ -934,7 +935,7 @@ final public boolean isPotentiallyUnknown(LocalVariableBinding local) { > } > int vectorIndex; > if ((vectorIndex = (position / BitCacheSize) - 1) >= >- this.extra[0].length) { >+ this.extra[2].length) { > return false; // if not enough room in vector, then not initialized > } > return (this.extra[5][vectorIndex] >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java >index 5d705d6..b269d89 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java >@@ -8,8 +8,10 @@ > * Contributors: > * IBM Corporation - initial API and implementation > * Benjamin Muskalla - Contribution for bug 239066 >- * Stephan Herrmann - Contribution for bug 236385 >- * Stephan Herrmann - Contribution for bug 295551 >+ * Stephan Herrmann - Contributions for >+ * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used >+ * bug 295551 - Add option to automatically promote all warnings to errors >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.impl; > >@@ -137,6 +139,9 @@ public class CompilerOptions { > public static final String OPTION_ReportMethodCanBeStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic"; //$NON-NLS-1$ > public static final String OPTION_ReportMethodCanBePotentiallyStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic"; //$NON-NLS-1$ > public static final String OPTION_ReportRedundantSpecificationOfTypeArguments = "org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments"; //$NON-NLS-1$ >+ public static final String OPTION_ReportUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.unclosedCloseable"; //$NON-NLS-1$ >+ public static final String OPTION_ReportPotentiallyUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable"; //$NON-NLS-1$ >+ public static final String OPTION_ReportExplicitlyClosedAutoCloseable = "org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$ > /** > * Possible values for configurable options > */ >@@ -240,6 +245,10 @@ public class CompilerOptions { > public static final int MethodCanBeStatic = IrritantSet.GROUP2 | ASTNode.Bit5; > public static final int MethodCanBePotentiallyStatic = IrritantSet.GROUP2 | ASTNode.Bit6; > public static final int RedundantSpecificationOfTypeArguments = IrritantSet.GROUP2 | ASTNode.Bit7; >+ // bits 8-10 reserved for https://bugs.eclipse.org/bugs/show_bug.cgi?id=186342 >+ public static final int UnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit11; >+ public static final int PotentiallyUnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit12; >+ public static final int ExplicitlyClosedAutoCloseable = IrritantSet.GROUP2 | ASTNode.Bit13; > > // Severity level for handlers > /** >@@ -376,8 +385,9 @@ public class CompilerOptions { > "javadoc", //$NON-NLS-1$ > "nls", //$NON-NLS-1$ > "null", //$NON-NLS-1$ >- "restriction", //$NON-NLS-1$ > "rawtypes", //$NON-NLS-1$ >+ "resource", //$NON-NLS-1$ >+ "restriction", //$NON-NLS-1$ > "serial", //$NON-NLS-1$ > "static-access", //$NON-NLS-1$ > "static-method", //$NON-NLS-1$ >@@ -551,6 +561,12 @@ public class CompilerOptions { > return OPTION_ReportMethodCanBePotentiallyStatic; > case RedundantSpecificationOfTypeArguments : > return OPTION_ReportRedundantSpecificationOfTypeArguments; >+ case UnclosedCloseable : >+ return OPTION_ReportUnclosedCloseable; >+ case PotentiallyUnclosedCloseable : >+ return OPTION_ReportPotentiallyUnclosedCloseable; >+ case ExplicitlyClosedAutoCloseable : >+ return OPTION_ReportExplicitlyClosedAutoCloseable; > } > return null; > } >@@ -714,6 +730,9 @@ public class CompilerOptions { > OPTION_ReportUnusedTypeArgumentsForMethodInvocation, > OPTION_ReportUnusedWarningToken, > OPTION_ReportVarargsArgumentNeedCast, >+ OPTION_ReportUnclosedCloseable, >+ OPTION_ReportPotentiallyUnclosedCloseable, >+ OPTION_ReportExplicitlyClosedAutoCloseable, > }; > return result; > } >@@ -784,10 +803,14 @@ public class CompilerOptions { > case MethodCanBeStatic : > case MethodCanBePotentiallyStatic : > return "static-method"; //$NON-NLS-1$ >+ case PotentiallyUnclosedCloseable: >+ case UnclosedCloseable: >+ case ExplicitlyClosedAutoCloseable: >+ return "resource"; //$NON-NLS-1$ > case InvalidJavadoc : > case MissingJavadocComments : > case MissingJavadocTags: >- return "javadoc"; //$NON-NLS-1$ >+ return "javadoc"; //$NON-NLS-1$ > } > return null; > } >@@ -841,6 +864,8 @@ public class CompilerOptions { > case 'r' : > if ("rawtypes".equals(warningToken)) //$NON-NLS-1$ > return IrritantSet.RAW; >+ if ("resource".equals(warningToken)) //$NON-NLS-1$ >+ return IrritantSet.RESOURCE; > if ("restriction".equals(warningToken)) //$NON-NLS-1$ > return IrritantSet.RESTRICTION; > break; >@@ -980,6 +1005,9 @@ public class CompilerOptions { > optionsMap.put(OPTION_ReportMethodCanBeStatic, getSeverityString(MethodCanBeStatic)); > optionsMap.put(OPTION_ReportMethodCanBePotentiallyStatic, getSeverityString(MethodCanBePotentiallyStatic)); > optionsMap.put(OPTION_ReportRedundantSpecificationOfTypeArguments, getSeverityString(RedundantSpecificationOfTypeArguments)); >+ optionsMap.put(OPTION_ReportUnclosedCloseable, getSeverityString(UnclosedCloseable)); >+ optionsMap.put(OPTION_ReportPotentiallyUnclosedCloseable, getSeverityString(PotentiallyUnclosedCloseable)); >+ optionsMap.put(OPTION_ReportExplicitlyClosedAutoCloseable, getSeverityString(ExplicitlyClosedAutoCloseable)); > return optionsMap; > } > >@@ -1410,6 +1438,9 @@ public class CompilerOptions { > if ((optionValue = optionsMap.get(OPTION_ReportMethodCanBeStatic)) != null) updateSeverity(MethodCanBeStatic, optionValue); > if ((optionValue = optionsMap.get(OPTION_ReportMethodCanBePotentiallyStatic)) != null) updateSeverity(MethodCanBePotentiallyStatic, optionValue); > if ((optionValue = optionsMap.get(OPTION_ReportRedundantSpecificationOfTypeArguments)) != null) updateSeverity(RedundantSpecificationOfTypeArguments, optionValue); >+ if ((optionValue = optionsMap.get(OPTION_ReportUnclosedCloseable)) != null) updateSeverity(UnclosedCloseable, optionValue); >+ if ((optionValue = optionsMap.get(OPTION_ReportPotentiallyUnclosedCloseable)) != null) updateSeverity(PotentiallyUnclosedCloseable, optionValue); >+ if ((optionValue = optionsMap.get(OPTION_ReportExplicitlyClosedAutoCloseable)) != null) updateSeverity(ExplicitlyClosedAutoCloseable, optionValue); > > // Javadoc options > if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) { >@@ -1625,6 +1656,9 @@ public class CompilerOptions { > buf.append("\n\t- method can be static: ").append(getSeverityString(MethodCanBeStatic)); //$NON-NLS-1$ > buf.append("\n\t- method can be potentially static: ").append(getSeverityString(MethodCanBePotentiallyStatic)); //$NON-NLS-1$ > buf.append("\n\t- redundant specification of type arguments: ").append(getSeverityString(RedundantSpecificationOfTypeArguments)); //$NON-NLS-1$ >+ buf.append("\n\t- resource is not closed: ").append(getSeverityString(UnclosedCloseable)); //$NON-NLS-1$ >+ buf.append("\n\t- resource may not be closed: ").append(getSeverityString(PotentiallyUnclosedCloseable)); //$NON-NLS-1$ >+ buf.append("\n\t- resource should be handled by try-with-resources: ").append(getSeverityString(ExplicitlyClosedAutoCloseable)); //$NON-NLS-1$ > return buf.toString(); > } > >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java >index db1823b..38dd14f 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > > package org.eclipse.jdt.internal.compiler.impl; >@@ -57,6 +58,7 @@ public class IrritantSet { > public static final IrritantSet UNUSED = new IrritantSet(CompilerOptions.UnusedLocalVariable); > public static final IrritantSet UNCHECKED = new IrritantSet(CompilerOptions.UncheckedTypeOperation); > public static final IrritantSet UNQUALIFIED_FIELD_ACCESS = new IrritantSet(CompilerOptions.UnqualifiedFieldAccess); >+ public static final IrritantSet RESOURCE = new IrritantSet(CompilerOptions.UnclosedCloseable); > > public static final IrritantSet JAVADOC = new IrritantSet(CompilerOptions.InvalidJavadoc); > public static final IrritantSet COMPILER_DEFAULT_ERRORS = new IrritantSet(0); // no optional error by default >@@ -99,7 +101,8 @@ public class IrritantSet { > // group-2 warnings enabled by default > .set( > CompilerOptions.DeadCode >- |CompilerOptions.Tasks); >+ |CompilerOptions.Tasks >+ |CompilerOptions.UnclosedCloseable); > > ALL.setAll(); > HIDING >@@ -124,6 +127,9 @@ public class IrritantSet { > .set(CompilerOptions.RedundantSpecificationOfTypeArguments); > STATIC_METHOD > .set(CompilerOptions.MethodCanBePotentiallyStatic); >+ RESOURCE >+ .set(CompilerOptions.PotentiallyUnclosedCloseable) >+ .set(CompilerOptions.ExplicitlyClosedAutoCloseable); > String suppressRawWhenUnchecked = System.getProperty("suppressRawWhenUnchecked"); //$NON-NLS-1$ > if (suppressRawWhenUnchecked != null && "true".equalsIgnoreCase(suppressRawWhenUnchecked)) { //$NON-NLS-1$ > UNCHECKED.set(CompilerOptions.RawTypeReference); >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java >index 9333d95..74dd0eb 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -972,6 +973,12 @@ public TypeVariableBinding getTypeVariable(char[] variableName) { > variable.resolve(); > return variable; > } >+public boolean hasTypeBit(int bit) { >+ // ensure hierarchy is resolved, which will propagate bits down to us >+ superclass(); >+ superInterfaces(); >+ return (this.typeBits & bit) != 0; >+} > private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper, char[][][] missingTypeNames) { > // ParameterSignature = Identifier ':' TypeSignature > // or Identifier ':' TypeSignature(optional) InterfaceBound(s) >@@ -1140,8 +1147,14 @@ public ReferenceBinding superclass() { > // finish resolving the type > this.superclass = (ReferenceBinding) resolveType(this.superclass, this.environment, true /* raw conversion */); > this.tagBits &= ~TagBits.HasUnresolvedSuperclass; >- if (this.superclass.problemId() == ProblemReasons.NotFound) >+ if (this.superclass.problemId() == ProblemReasons.NotFound) { > this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency >+ } else { >+ // make super-type resolving recursive for propagating typeBits downwards >+ this.superclass.superclass(); >+ this.superclass.superInterfaces(); >+ } >+ this.typeBits |= this.superclass.typeBits; > return this.superclass; > } > // NOTE: superInterfaces of binary types are resolved when needed >@@ -1151,8 +1164,14 @@ public ReferenceBinding[] superInterfaces() { > > for (int i = this.superInterfaces.length; --i >= 0;) { > this.superInterfaces[i] = (ReferenceBinding) resolveType(this.superInterfaces[i], this.environment, true /* raw conversion */); >- if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound) >+ if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound) { > this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency >+ } else { >+ // make super-type resolving recursive for propagating typeBits downwards >+ this.superInterfaces[i].superclass(); >+ this.superInterfaces[i].superInterfaces(); >+ } >+ this.typeBits |= this.superInterfaces[i].typeBits; > } > this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces; > return this.superInterfaces; >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java >index b3613a7..e2ea092 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java >@@ -7,13 +7,19 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >+import java.util.ArrayList; >+import java.util.List; >+ > import org.eclipse.jdt.core.compiler.CharOperation; > import org.eclipse.jdt.internal.compiler.ast.*; > import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; > import org.eclipse.jdt.internal.compiler.codegen.CodeStream; >+import org.eclipse.jdt.internal.compiler.flow.FlowContext; >+import org.eclipse.jdt.internal.compiler.flow.FlowInfo; > import org.eclipse.jdt.internal.compiler.impl.Constant; > import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; > >@@ -957,4 +963,145 @@ public void resetEnclosingMethodStaticFlag() { > } > } > } >+ >+private List trackingVariables; // can be null if no resources are tracked >+/** >+ * Register a tracking variable and compute its id. >+ */ >+public int registerTrackingVariable(FakedTrackingVariable fakedTrackingVariable) { >+ if (this.trackingVariables == null) >+ this.trackingVariables = new ArrayList(3); >+ this.trackingVariables.add(fakedTrackingVariable); >+ MethodScope outerMethodScope = outerMostMethodScope(); >+ return outerMethodScope.analysisIndex + (outerMethodScope.trackVarCount++); >+ >+} >+/** When no longer interested in this tracking variable remove it. */ >+public void removeTrackingVar(FakedTrackingVariable trackingVariable) { >+ if (this.trackingVariables != null) >+ if (this.trackingVariables.remove(trackingVariable)) >+ return; >+ if (this.parent instanceof BlockScope) >+ ((BlockScope)this.parent).removeTrackingVar(trackingVariable); >+} >+/** >+ * At the end of a block check the closing-status of all tracked closeables that are declared in this block. >+ * Also invoked when entering unreachable code. >+ */ >+public void checkUnclosedCloseables(FlowInfo flowInfo, FlowContext flowContext, ASTNode location) { >+ if (this.trackingVariables == null) { >+ // at a method return we also consider enclosing scopes >+ if (location != null && this.parent instanceof BlockScope) >+ ((BlockScope) this.parent).checkUnclosedCloseables(flowInfo, flowContext, location); >+ return; >+ } >+ if (location != null && flowInfo.reachMode() != 0) return; >+ for (int i=0; i<this.trackingVariables.size(); i++) { >+ FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i); >+ if (location != null && trackingVar.originalBinding != null && flowInfo.isDefinitelyNull(trackingVar.originalBinding)) >+ continue; // reporting against a specific location, resource is null at this flow, don't complain >+ int status = getNullStatusAggressively(trackingVar.binding, flowInfo); >+ if (status == FlowInfo.NULL) { >+ // definitely unclosed: highest priority >+ reportResourceLeak(trackingVar, location, status); >+ if (location == null) { >+ // definitely done with this trackingVar, remove it >+ this.trackingVariables.remove(trackingVar); >+ i--; // ... but don't disturb the enclosing loop. >+ } >+ continue; >+ } >+ if (location == null) // at end of block and not definitely unclosed >+ { >+ // problems at specific locations: medium priority >+ if (trackingVar.reportRecordedErrors(this)) // ... report previously recorded errors >+ continue; >+ } >+ if (status == FlowInfo.POTENTIALLY_NULL) { >+ // potentially unclosed: lower priority >+ reportResourceLeak(trackingVar, location, status); >+ } else if (status == FlowInfo.NON_NULL) { >+ // properly closed but not managed by t-w-r: lowest priority >+ if (environment().globalOptions.complianceLevel >= ClassFileConstants.JDK1_7) >+ problemReporter().explicitlyClosedAutoCloseable(trackingVar); >+ } >+ } >+} >+private void reportResourceLeak(FakedTrackingVariable trackingVar, ASTNode location, int nullStatus) { >+ if (location != null) >+ trackingVar.recordErrorLocation(location, nullStatus); >+ else >+ trackingVar.reportError(problemReporter(), null, nullStatus); >+} >+ >+/** >+ * If one branch of an if-else closes any AutoCloseable resource, and if the same >+ * resource is known to be null on the other branch mark it as closed, too, >+ * so that merging both branches indicates that the resource is always closed. >+ * Example: >+ * FileReader fr1 = null; >+ * 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 >+ * } >+ * // after this if statement fr1 is definitely not leaked >+ * } >+ */ >+public void correlateTrackingVarsIfElse(FlowInfo thenFlowInfo, FlowInfo elseFlowInfo) { >+ if (this.trackingVariables != null) { >+ for (int i=0; i<this.trackingVariables.size(); i++) { >+ FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i); >+ if ( thenFlowInfo.isDefinitelyNonNull(trackingVar.binding) // closed in then branch >+ && elseFlowInfo.isDefinitelyNull(trackingVar.originalBinding)) // null in else branch >+ { >+ elseFlowInfo.markAsDefinitelyNonNull(trackingVar.binding); // -> always closed >+ } >+ else if ( elseFlowInfo.isDefinitelyNonNull(trackingVar.binding) // closed in else branch >+ && thenFlowInfo.isDefinitelyNull(trackingVar.originalBinding)) // null in then branch >+ { >+ thenFlowInfo.markAsDefinitelyNonNull(trackingVar.binding); // -> always closed >+ } >+ } >+ } >+ if (this.parent instanceof BlockScope) >+ ((BlockScope) this.parent).correlateTrackingVarsIfElse(thenFlowInfo, elseFlowInfo); >+} >+ >+/** >+ * Get the null status looking even into unreachable flows >+ * @param local >+ * @param flowInfo >+ * @return one of the constants FlowInfo.{NULL,POTENTIALLY_NULL,POTENTIALLY_NON_NULL,NON_NULL}. >+ */ >+private int getNullStatusAggressively(LocalVariableBinding local, FlowInfo flowInfo) { >+ int reachMode = flowInfo.reachMode(); >+ int status = 0; >+ try { >+ // unreachable flowInfo is too shy in reporting null-issues, temporarily forget reachability: >+ if (reachMode != FlowInfo.REACHABLE) >+ flowInfo.tagBits &= ~FlowInfo.UNREACHABLE; >+ status = flowInfo.nullStatus(local); >+ } finally { >+ // reset >+ flowInfo.tagBits |= reachMode; >+ } >+ // at this point some combinations are not useful so flatten to a single bit: >+ if ((status & FlowInfo.NULL) != 0) { >+ if ((status & (FlowInfo.NON_NULL | FlowInfo.POTENTIALLY_NON_NULL)) != 0) >+ return FlowInfo.POTENTIALLY_NULL; // null + doubt = pot null >+ return FlowInfo.NULL; >+ } else if ((status & FlowInfo.NON_NULL) != 0) { >+ if ((status & FlowInfo.POTENTIALLY_NULL) != 0) >+ return FlowInfo.POTENTIALLY_NULL; // non-null + doubt = pot null >+ return FlowInfo.NON_NULL; >+ } else if ((status & FlowInfo.POTENTIALLY_NULL) != 0) >+ return FlowInfo.POTENTIALLY_NULL; >+ return status; >+} > } >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java >index eb865be..3eb3cca 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java >@@ -11,6 +11,7 @@ > * Bug 328281 - visibility leaks not detected when analyzing unused field in private class > * Bug 300576 - NPE Computing type hierarchy when compliance doesn't match libraries > * Bug 354536 - compiling package-info.java still depends on the order of compilation units >+ * Bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -908,6 +909,7 @@ public class ClassScope extends Scope { > } else { > // only want to reach here when no errors are reported > sourceType.superclass = superclass; >+ sourceType.typeBits |= superclass.typeBits; > return true; > } > } >@@ -1023,6 +1025,7 @@ public class ClassScope extends Scope { > noProblems &= superInterfaceRef.resolvedType.isValidBinding(); > } > // only want to reach here when no errors are reported >+ sourceType.typeBits |= superInterface.typeBits; > interfaceBindings[count++] = superInterface; > } > // hold onto all correctly resolved superinterfaces >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java >index d0bd849..b163168 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 185682 - Increment/decrement operators mark local variables as read >+ * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for >+ * bug 185682 - Increment/decrement operators mark local variables as read >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -15,6 +17,7 @@ import org.eclipse.jdt.core.compiler.CharOperation; > import org.eclipse.jdt.internal.compiler.ast.ASTNode; > import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; > import org.eclipse.jdt.internal.compiler.ast.Annotation; >+import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable; > import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; > import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; > import org.eclipse.jdt.internal.compiler.impl.Constant; >@@ -35,6 +38,8 @@ public class LocalVariableBinding extends VariableBinding { > public int[] initializationPCs; > public int initializationCount = 0; > >+ public FakedTrackingVariable closeTracker; // track closing of instances of type AutoCloseable, maybe null >+ > // for synthetic local variables > // if declaration slot is not positionned, the variable will not be listed in attribute > // note that the name of a variable should be chosen so as not to conflict with user ones (usually starting with a space char is all needed) >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java >index 642388d..52c7258 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -49,6 +50,9 @@ public class MethodScope extends BlockScope { > // inner-emulation > public SyntheticArgumentBinding[] extraSyntheticArguments; > >+ // count number of tracking variables, see FakedTrackingVariable >+ int trackVarCount = 0; >+ > public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) { > super(METHOD_SCOPE, parent); > this.locals = new LocalVariableBinding[5]; >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java >index 5458a30..06e2a60 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -629,6 +630,13 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi > return this.type.hasMemberTypes(); > } > >+ public boolean hasTypeBit(int bit) { >+ TypeBinding erasure = erasure(); >+ if (erasure instanceof ReferenceBinding) >+ return ((ReferenceBinding) erasure).hasTypeBit(bit); >+ return false; >+ } >+ > /** > * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#implementsMethod(MethodBinding) > */ >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java >index efc1bc2..5d9c344 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -40,6 +41,12 @@ public ReferenceBinding closestReferenceMatch() { > return this.closestMatch; > } > >+public boolean hasTypeBit(int bit) { >+ if (this.closestMatch != null) >+ return this.closestMatch.hasTypeBit(bit); >+ return false; >+} >+ > /* API > * Answer the problem id associated with the receiver. > * NoError if the receiver is a valid binding. >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java >index c26cc15..1769362 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -41,7 +42,11 @@ abstract public class ReferenceBinding extends TypeBinding { > > private SimpleLookupTable compatibleCache; > >- public static final ReferenceBinding LUB_GENERIC = new ReferenceBinding() { /* used for lub computation */}; >+ int typeBits; // additional bits characterizing this type >+ >+ public static final ReferenceBinding LUB_GENERIC = new ReferenceBinding() { /* used for lub computation */ >+ public boolean hasTypeBit(int bit) { return false; } >+ }; > > private static final Comparator FIELD_COMPARATOR = new Comparator() { > public int compare(Object o1, Object o2) { >@@ -392,6 +397,10 @@ public void computeId() { > case 'i' : > if (CharOperation.equals(packageName, TypeConstants.IO)) { > switch (typeName[0]) { >+ case 'C' : >+ if (CharOperation.equals(typeName, TypeConstants.JAVA_IO_CLOSEABLE[2])) >+ this.typeBits |= TypeIds.BitCloseable; // don't assign id, only typeBit (for analysis of resource leaks) >+ return; > case 'E' : > if (CharOperation.equals(typeName, TypeConstants.JAVA_IO_EXTERNALIZABLE[2])) > this.id = TypeIds.T_JavaIoExternalizable; >@@ -438,8 +447,10 @@ public void computeId() { > case 'A' : > switch(typeName.length) { > case 13 : >- if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_AUTOCLOSEABLE[2])) >+ if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_AUTOCLOSEABLE[2])) { > this.id = TypeIds.T_JavaLangAutoCloseable; >+ this.typeBits |= TypeIds.BitAutoCloseable; >+ } > return; > case 14: > if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ASSERTIONERROR[2])) >@@ -937,6 +948,8 @@ public boolean hasMemberTypes() { > public final boolean hasRestrictedAccess() { > return (this.modifiers & ExtraCompilerModifiers.AccRestrictedAccess) != 0; > } >+/** Answer an additional bit characterizing this type, like {@link TypeIds#BitAutoCloseable}. */ >+abstract public boolean hasTypeBit(int bit); > > /** Answer true if the receiver implements anInterface or is identical to anInterface. > * If searchHierarchy is true, then also search the receiver's superclasses. >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java >index aabc37f..b346908 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 328281 - visibility leaks not detected when analyzing unused field in private class >+ * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for >+ * bug 328281 - visibility leaks not detected when analyzing unused field in private class >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -1063,6 +1065,11 @@ public SyntheticMethodBinding getSyntheticBridgeMethod(MethodBinding inheritedMe > return accessors[1]; > } > >+public boolean hasTypeBit(int bit) { >+ // source types initialize type bits during connectSuperclass/interfaces() >+ return (this.typeBits & bit) != 0; >+} >+ > /** > * @see org.eclipse.jdt.internal.compiler.lookup.Binding#initializeDeprecatedAnnotationTagBits() > */ >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java >index 9a62cc0..0bbef47 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -123,6 +124,7 @@ public interface TypeConstants { > char[][] JAVA_LANG_ANNOTATION_ELEMENTTYPE = {JAVA, LANG, ANNOTATION, "ElementType".toCharArray()}; //$NON-NLS-1$ > char[][] JAVA_LANG_REFLECT_FIELD = new char[][] {JAVA, LANG, REFLECT, "Field".toCharArray()}; //$NON-NLS-1$ > char[][] JAVA_LANG_REFLECT_METHOD = new char[][] {JAVA, LANG, REFLECT, "Method".toCharArray()}; //$NON-NLS-1$ >+ char[][] JAVA_IO_CLOSEABLE = new char[][] { JAVA, IO, "Closeable".toCharArray()};//$NON-NLS-1$ > char[][] JAVA_IO_OBJECTSTREAMEXCEPTION = new char[][] { JAVA, IO, "ObjectStreamException".toCharArray()};//$NON-NLS-1$ > char[][] JAVA_IO_EXTERNALIZABLE = {JAVA, IO, "Externalizable".toCharArray()}; //$NON-NLS-1$ > char[][] JAVA_IO_IOEXCEPTION = new char[][] { JAVA, IO, "IOException".toCharArray()};//$NON-NLS-1$ >@@ -151,6 +153,7 @@ public interface TypeConstants { > "MethodHandle$PolymorphicSignature".toCharArray() //$NON-NLS-1$ > }; > char[][] JAVA_LANG_AUTOCLOSEABLE = {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$ >+ char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$ > > // Constraints for generic type argument inference > int CONSTRAINT_EQUAL = 0; // Actual = Formal >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java >index 8e3a647..2bd50bc 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -182,4 +183,15 @@ public interface TypeIds { > final int Object2boolean = T_JavaLangObject + (T_boolean << 4); > final int BOXING = 0x200; > final int UNBOXING = 0x400; >+ >+ /** >+ * Marks all sub-types of java.lang.AutoCloseable. >+ * @see ReferenceBinding#hasTypeBit(int) >+ */ >+ final int BitAutoCloseable = 1; >+ /** >+ * Marks all sub-types of java.io.Closeable. >+ * @see ReferenceBinding#hasTypeBit(int) >+ */ >+ final int BitCloseable = 2; > } >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java >index 7b6c840..e463960 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2010 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 >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac >+ * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for >+ * bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -42,6 +44,7 @@ public class TypeVariableBinding extends ReferenceBinding { > this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; // treat type var as public > this.tagBits |= TagBits.HasTypeVariable; > this.environment = environment; >+ this.typeBits = -1; > } > > /** >@@ -307,6 +310,19 @@ public class TypeVariableBinding extends ReferenceBinding { > return true; > } > >+ public boolean hasTypeBit(int bit) { >+ if (this.typeBits == -1) { >+ // initialize from bounds >+ this.typeBits = 0; >+ if (this.superclass != null) >+ this.typeBits |= this.superclass.typeBits; >+ if (this.superInterfaces != null) >+ for (int i = 0, l = this.superInterfaces.length; i < l; i++) >+ this.typeBits |= this.superInterfaces[i].typeBits; >+ } >+ return (this.typeBits & bit) != 0; >+ } >+ > /** > * Returns true if the type variable is directly bound to a given type > */ >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java >index 0ca15de..3038368 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.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 >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -41,6 +42,10 @@ void addWrapper(TypeBinding wrapper, LookupEnvironment environment) { > public String debugName() { > return toString(); > } >+public boolean hasTypeBit(int bit) { >+ // shouldn't happen since we are not called before analyseCode(), but play safe: >+ return false; >+} > ReferenceBinding resolve(LookupEnvironment environment, boolean convertGenericToRawType) { > ReferenceBinding targetType = this.resolvedType; > if (targetType == null) { >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java >index 0e6e487..375ebec 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2005, 2009 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 >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -54,6 +55,7 @@ public class WildcardBinding extends ReferenceBinding { > if (bound instanceof UnresolvedReferenceBinding) > ((UnresolvedReferenceBinding) bound).addWrapper(this, environment); > this.tagBits |= TagBits.HasUnresolvedTypeVariables; // cleared in resolve() >+ this.typeBits = -1; > } > > public int kind() { >@@ -420,6 +422,19 @@ public class WildcardBinding extends ReferenceBinding { > return this.genericType.hashCode(); > } > >+ public boolean hasTypeBit(int bit) { >+ if (this.typeBits == -1) { >+ // initialize from upper bounds >+ this.typeBits = 0; >+ if (this.superclass != null) >+ this.typeBits |= this.superclass.typeBits; >+ if (this.superInterfaces != null) >+ for (int i = 0, l = this.superInterfaces.length; i < l; i++) >+ this.typeBits |= this.superInterfaces[i].typeBits; >+ } >+ return (this.typeBits & bit) != 0; >+ } >+ > void initialize(ReferenceBinding someGenericType, TypeBinding someBound, TypeBinding[] someOtherBounds) { > this.genericType = someGenericType; > this.bound = someBound; >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java >index a51fde1..c84b83d 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java >@@ -11,6 +11,7 @@ > * Stephan Herrmann - Contributions for > * bug 236385 - > * bug 338303 - Warning about Redundant assignment conflicts with definite assignment >+ * bug 349326 - [1.7] new warning for missing try-with-resources > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.problem; > >@@ -51,6 +52,7 @@ import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; > import org.eclipse.jdt.internal.compiler.ast.EqualExpression; > import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; > import org.eclipse.jdt.internal.compiler.ast.Expression; >+import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable; > import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; > import org.eclipse.jdt.internal.compiler.ast.FieldReference; > import org.eclipse.jdt.internal.compiler.ast.ImportReference; >@@ -426,6 +428,15 @@ public static int getIrritant(int problemID) { > > case IProblem.MethodCanBePotentiallyStatic: > return CompilerOptions.MethodCanBePotentiallyStatic; >+ >+ case IProblem.UnclosedCloseable: >+ case IProblem.UnclosedCloseableAtExit: >+ return CompilerOptions.UnclosedCloseable; >+ case IProblem.PotentiallyUnclosedCloseable: >+ case IProblem.PotentiallyUnclosedCloseableAtExit: >+ return CompilerOptions.PotentiallyUnclosedCloseable; >+ case IProblem.ExplicitlyClosedAutoCloseable: >+ return CompilerOptions.ExplicitlyClosedAutoCloseable; > > case IProblem.RedundantSpecificationOfTypeArguments: > return CompilerOptions.RedundantSpecificationOfTypeArguments; >@@ -461,6 +472,7 @@ public static int getProblemCategory(int severity, int problemID) { > case CompilerOptions.ParameterAssignment : > case CompilerOptions.MethodCanBeStatic : > case CompilerOptions.MethodCanBePotentiallyStatic : >+ case CompilerOptions.ExplicitlyClosedAutoCloseable : > return CategorizedProblem.CAT_CODE_STYLE; > > case CompilerOptions.MaskedCatchBlock : >@@ -482,6 +494,8 @@ public static int getProblemCategory(int severity, int problemID) { > case CompilerOptions.ShouldImplementHashcode : > case CompilerOptions.DeadCode : > case CompilerOptions.UnusedObjectAllocation : >+ case CompilerOptions.UnclosedCloseable : >+ case CompilerOptions.PotentiallyUnclosedCloseable : > return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM; > > case CompilerOptions.OverriddenPackageDefaultMethod : >@@ -7931,4 +7945,49 @@ public void redundantSpecificationOfTypeArguments(ASTNode location, TypeBinding[ > location.sourceEnd); > } > } >+public void potentiallyUnclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) { >+ String[] args = { String.valueOf(trackVar.name) }; >+ if (location == null) { >+ this.handle( >+ IProblem.PotentiallyUnclosedCloseable, >+ args, >+ args, >+ trackVar.sourceStart, >+ trackVar.sourceEnd); >+ } else { >+ this.handle( >+ IProblem.PotentiallyUnclosedCloseableAtExit, >+ args, >+ args, >+ location.sourceStart, >+ location.sourceEnd); >+ } >+} >+public void unclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) { >+ String[] args = { String.valueOf(trackVar.name) }; >+ if (location == null) { >+ this.handle( >+ IProblem.UnclosedCloseable, >+ args, >+ args, >+ trackVar.sourceStart, >+ trackVar.sourceEnd); >+ } else { >+ this.handle( >+ IProblem.UnclosedCloseableAtExit, >+ args, >+ args, >+ location.sourceStart, >+ location.sourceEnd); >+ } >+} >+public void explicitlyClosedAutoCloseable(FakedTrackingVariable trackVar) { >+ String[] args = { String.valueOf(trackVar.name) }; >+ this.handle( >+ IProblem.ExplicitlyClosedAutoCloseable, >+ args, >+ args, >+ trackVar.sourceStart, >+ trackVar.sourceEnd); >+} > } >\ No newline at end of file >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties >index 2193910..7a2e983 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties >@@ -8,7 +8,9 @@ > # Contributors: > # IBM Corporation - initial API and implementation > # Benjamin Muskalla - Contribution for bug 239066 >-# Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 185682 - Increment/decrement operators mark local variables as read >+# Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for >+# bug 185682 - Increment/decrement operators mark local variables as read >+# bug 349326 - [1.7] new warning for missing try-with-resources > ############################################################################### > 0 = {0} > 1 = super cannot be used in java.lang.Object >@@ -644,6 +646,11 @@ > 882 = Unhandled exception type {0} thrown by automatic close() invocation on {1} > 883 = '<>' operator is not allowed for source level below 1.7 > 884 = Redundant specification of type arguments <{0}> >+885 = Potential resource leak: '{0}' may not be closed >+886 = Potential resource leak: '{0}' may not be closed at this location >+887 = Resource leak: '{0}' is never closed >+888 = Resource leak: '{0}' is not closed at this location >+889 = Resource '{0}' should be managed by try-with-resource > > ### ELABORATIONS > ## Access restrictions >diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java >index 7a4a96a..eb37a96 100644 >--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java >+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java >@@ -83,6 +83,10 @@ > * Benjamin Muskalla - added COMPILER_PB_MISSING_SYNCHRONIZED_ON_INHERITED_METHOD > * Stephan Herrmann - added COMPILER_PB_UNUSED_OBJECT_ALLOCATION > * Stephan Herrmann - added COMPILER_PB_SUPPRESS_OPTIONAL_ERRORS >+ * Stephan Herrmann - added the following constants: >+ * COMPILER_PB_UNCLOSED_CLOSEABLE, >+ * COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE >+ * COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE > *******************************************************************************/ > > package org.eclipse.jdt.core; >@@ -1357,6 +1361,52 @@ public final class JavaCore extends Plugin { > */ > public static final String COMPILER_PB_POTENTIALLY_MISSING_STATIC_ON_METHOD = PLUGIN_ID + ".compiler.problem.reportMethodCanBePotentiallyStatic"; //$NON-NLS-1$ > /** >+ * Compiler option ID: Reporting a resource that is not closed properly. >+ * <p>When enabled, that compiler will issue an error or a warning if >+ * a local variable holds a value of type <code>java.lang.AutoCloseable</code> (compliance>=1.7) >+ * or a value of type <code>java.io.Closeable</code> (compliance<=1.6) and if >+ * flow analysis shows that the method <code>close()</code> is not invoked locally on that value. >+ * <dl> >+ * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.reportUnclosedCloseable"</code></dd> >+ * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd> >+ * <dt>Default:</dt><dd><code>"warning"</code></dd> >+ * </dl> >+ * @since 3.8 >+ * @category CompilerOptionID >+ */ >+ public static final String COMPILER_PB_UNCLOSED_CLOSEABLE = PLUGIN_ID + ".compiler.problem.unclosedCloseable"; //$NON-NLS-1$ >+ /** >+ * Compiler option ID: Reporting a resource that may not be closed properly. >+ * <p>When enabled, that compiler will issue an error or a warning if >+ * a local variable holds a value of type <code>java.lang.AutoCloseable</code> (compliance>=1.7) >+ * or a value of type <code>java.io.Closeable</code> (compliance<=1.6) and if >+ * flow analysis shows that the method <code>close()</code> is >+ * not invoked locally on that value for all execution paths. >+ * <dl> >+ * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.reportPotentiallyUnclosedCloseable"</code></dd> >+ * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd> >+ * <dt>Default:</dt><dd><code>"ignore"</code></dd> >+ * </dl> >+ * @since 3.8 >+ * @category CompilerOptionID >+ */ >+ public static final String COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE = PLUGIN_ID + ".compiler.problem.potentiallyUnclosedCloseable"; //$NON-NLS-1$ >+ /** >+ * Compiler option ID: Reporting a resource that is not managed by try-with-resources. >+ * <p>When enabled, that compiler will issue an error or a warning if a local variable >+ * holds a value of type <code>java.lang.AutoCloseable</code>, and if the method >+ * <code>close()</code> is explicitly invoked on that resource, but the resource is >+ * not managed by a try-with-resources block. >+ * <dl> >+ * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.reportPotentiallyUnclosedCloseable"</code></dd> >+ * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd> >+ * <dt>Default:</dt><dd><code>"ignore"</code></dd> >+ * </dl> >+ * @since 3.8 >+ * @category CompilerOptionID >+ */ >+ public static final String COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE = PLUGIN_ID + ".compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$ >+ /** > * Compiler option ID: Setting Source Compatibility Mode. > * <p>Specify whether which source level compatibility is used. From 1.4 on, <code>'assert'</code> is a keyword > * reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 349326
:
198503
|
199192
|
199216
|
199235
|
199358
|
199378
|
199385
|
199402
|
199435
|
199443
|
199812
|
201450
|
202016
|
202189
|
202721
|
203866
|
203961
|
203975
|
204041
|
204066
|
204108