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 209482 Details for
Bug 358903
Filter practically unimportant resource leak warnings
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Tests & fix v1.0
Bug_358903_v1.0.patch (text/plain), 272.39 KB, created by
Stephan Herrmann
on 2012-01-13 16:17:57 EST
(
hide
)
Description:
Tests & fix v1.0
Filename:
MIME Type:
Creator:
Stephan Herrmann
Created:
2012-01-13 16:17:57 EST
Size:
272.39 KB
patch
obsolete
>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 0c9324c..e24388f 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 >@@ -6020,6 +6020,7 @@ public void test0561_try_catch_unchecked_exception() { > public void test0562_try_catch_unchecked_exception() { > Map options = getCompilerOptions(); > options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.WARNING); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING); > this.runNegativeTest( > true, > new String[] { >@@ -6042,7 +6043,7 @@ public void test0562_try_catch_unchecked_exception() { > "1. WARNING in X.java (at line 6)\n" + > " o = new LineNumberReader(new FileReader(\"dummy\"));\n" + > " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Resource leak: 'o' is never closed\n" + >+ "Potential resource leak: \'o\' may not be closed\n" + > "----------\n" + > "2. ERROR in X.java (at line 8)\n" + > " o.toString();\n" + >diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java >new file mode 100644 >index 0000000..51d5e74 >--- /dev/null >+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java >@@ -0,0 +1,2973 @@ >+/******************************************************************************* >+ * Copyright (c) 2011, 2012 GK Software AG and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Stephan Herrmann - initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.jdt.core.tests.compiler.regression; >+ >+import java.io.IOException; >+import java.net.URL; >+import java.util.Map; >+ >+import junit.framework.Test; >+ >+import org.eclipse.core.runtime.FileLocator; >+import org.eclipse.core.runtime.Path; >+import org.eclipse.core.runtime.Platform; >+import org.eclipse.jdt.core.JavaCore; >+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; >+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; >+ >+public class ResourceLeakTests extends AbstractRegressionTest { >+ >+static { >+// TESTS_NAMES = new String[] { "test061a"}; >+// TESTS_NUMBERS = new int[] { 50 }; >+// TESTS_RANGE = new int[] { 11, -1 }; >+} >+public ResourceLeakTests(String name) { >+ super(name); >+} >+public static Test suite() { >+ return buildAllCompliancesTestSuite(ResourceLeakTests.class); >+} >+ >+void runTestsExpectingErrorsOnlyIn17(String[] testFiles, String errorsIn17, Map options) { >+ if (this.complianceLevel >= ClassFileConstants.JDK1_7) >+ runNegativeTest(testFiles, errorsIn17, null, true, options); >+ else >+ runConformTest(testFiles, "", null, true, null, options, null); >+} >+ >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// a method uses an AutoCloseable without ever closing it. >+public void test056() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+// not invoking any methods on FileReader, try to avoid necessary call to superclass() in the compiler >+// " char[] in = new char[50];\n" + >+// " fileReader.read(in);\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 7)\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " ^^^^^^^^^^\n" + >+ "Resource leak: 'fileReader' is never closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// a method uses an AutoCloseable and closes it but not protected by t-w-r nor regular try-finally >+public void test056a() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR); >+ runTestsExpectingErrorsOnlyIn17( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " fileReader.close();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 7)\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " ^^^^^^^^^^\n" + >+ "Resource 'fileReader' should be managed by try-with-resource\n" + >+ "----------\n", >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// a method uses an AutoCloseable and closes it properly in a finally block >+public void test056b() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " try {\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " } finally {\n" + >+ " fileReader.close();\n" + >+ " }\n" + >+ " }\n" + >+ " public static void main(String[] args) {\n" + >+ " try {\n" + >+ " new X().foo();\n" + >+ " } catch (IOException ioex) {\n" + >+ " System.out.println(\"caught\");\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "caught", /*output*/ >+ null/*classLibs*/, >+ true/*shouldFlush*/, >+ null/*vmargs*/, >+ options, >+ null/*requestor*/); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// a method uses an AutoCloseable properly within try-with-resources. >+public void test056c() { >+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // t-w-r used >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " try (FileReader fileReader = new FileReader(file)) {\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " }\n" + >+ " }\n" + >+ " public static void main(String[] args) {\n" + >+ " try {\n" + >+ " new X().foo();\n" + >+ " } catch (IOException ioex) {\n" + >+ " System.out.println(\"caught\");\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "caught", /*output*/ >+ null/*classLibs*/, >+ true/*shouldFlush*/, >+ null/*vmargs*/, >+ options, >+ null/*requestor*/); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// a method uses two AutoCloseables (testing independent analysis) >+//- one closeable may be unclosed at a conditional return >+//- the other is only conditionally closed >+public void test056d() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo(boolean flag1, boolean flag2) throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " char[] in = new char[50];\n" + >+ " FileReader fileReader1 = new FileReader(file);\n" + >+ " fileReader1.read(in);\n" + >+ " FileReader fileReader2 = new FileReader(file);\n" + >+ " fileReader2.read(in);\n" + >+ " if (flag1) {\n" + >+ " fileReader2.close();\n" + >+ " return;\n" + >+ " } else if (flag2) {\n" + >+ " fileReader2.close();\n" + >+ " }\n" + >+ " fileReader1.close();\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo(false, true);\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. WARNING in X.java (at line 10)\n" + >+ " FileReader fileReader2 = new FileReader(file);\n" + >+ " ^^^^^^^^^^^\n" + >+ "Potential resource leak: 'fileReader2' may not be closed\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 14)\n" + >+ " return;\n" + >+ " ^^^^^^^\n" + >+ "Resource leak: 'fileReader1' is not closed at this location\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// a method uses two AutoCloseables (testing independent analysis) >+//- one closeable may be unclosed at a conditional return >+//- the other is only conditionally closed >+public void test056d_suppress() { >+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // annotations used >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING); >+ options.put(CompilerOptions.OPTION_SuppressOptionalErrors, CompilerOptions.ENABLED); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo(boolean flag1, boolean flag2) throws IOException {\n" + >+ " @SuppressWarnings(\"resource\") File file = new File(\"somefile\"); // unnecessary suppress\n" + >+ " char[] in = new char[50];\n" + >+ " FileReader fileReader1 = new FileReader(file);\n" + >+ " fileReader1.read(in);\n" + >+ " @SuppressWarnings(\"resource\") FileReader fileReader2 = new FileReader(file); // useful suppress\n" + >+ " fileReader2.read(in);\n" + >+ " if (flag1) {\n" + >+ " fileReader2.close();\n" + >+ " return; // not suppressed\n" + >+ " } else if (flag2) {\n" + >+ " fileReader2.close();\n" + >+ " }\n" + >+ " fileReader1.close();\n" + >+ " }\n" + >+ " @SuppressWarnings(\"resource\") // useful suppress\n" + >+ " void bar() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo(false, true);\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. WARNING in X.java (at line 6)\n" + >+ " @SuppressWarnings(\"resource\") File file = new File(\"somefile\"); // unnecessary suppress\n" + >+ " ^^^^^^^^^^\n" + >+ "Unnecessary @SuppressWarnings(\"resource\")\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 14)\n" + >+ " return; // not suppressed\n" + >+ " ^^^^^^^\n" + >+ "Resource leak: 'fileReader1' is not closed at this location\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// Bug 362332 - Only report potential leak when closeable not created in the local scope >+// one method returns an AutoCleasble, a second method uses this object without ever closing it. >+public void test056e() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " FileReader getReader(String filename) throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " return fileReader;\n" + // don't complain here, pass responsibility to caller >+ " }\n" + >+ " void foo() throws IOException {\n" + >+ " FileReader reader = getReader(\"somefile\");\n" + >+ " char[] in = new char[50];\n" + >+ " reader.read(in);\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 11)\n" + >+ " FileReader reader = getReader(\"somefile\");\n" + >+ " ^^^^^^\n" + >+ "Potential resource leak: \'reader\' may not be closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// a method explicitly closes its AutoCloseable rather than using t-w-r >+public void test056f() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING); >+ options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR); >+ runTestsExpectingErrorsOnlyIn17( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader fileReader = null;\n" + >+ " try {\n" + >+ " fileReader = new FileReader(file);\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " } finally {\n" + >+ " fileReader.close();\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 7)\n" + >+ " FileReader fileReader = null;\n" + >+ " ^^^^^^^^^^\n" + >+ "Resource 'fileReader' should be managed by try-with-resource\n" + >+ "----------\n", >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// an AutoCloseable local is re-assigned >+public void test056g() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " fileReader = new FileReader(file);\n" + >+ " fileReader.read(in);\n" + >+ " fileReader.close();\n" + >+ " fileReader = null;\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 10)\n" + >+ " fileReader = new FileReader(file);\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: 'fileReader' is not closed at this location\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// an AutoCloseable local is re-assigned after null-assigned >+public void test056g2() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " fileReader = null;\n" + >+ " fileReader = new FileReader(file);\n" + // don't complain again, fileReader is null, so nothing can leak here >+ " fileReader.read(in);\n" + >+ " fileReader.close();\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 10)\n" + >+ " fileReader = null;\n" + >+ " ^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: 'fileReader' is not closed at this location\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// two AutoCloseables at different nesting levels (anonymous local type) >+public void test056h() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " final File file = new File(\"somefile\");\n" + >+ " final FileReader fileReader = new FileReader(file);\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " new Runnable() {\n public void run() {\n" + >+ " try {\n" + >+ " fileReader.close();\n" + >+ " FileReader localReader = new FileReader(file);\n" + >+ " } catch (IOException ex) { /* nop */ }\n" + >+ " }}.run();\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. WARNING in X.java (at line 7)\n" + >+ " final FileReader fileReader = new FileReader(file);\n" + >+ " ^^^^^^^^^^\n" + >+ "Potential resource leak: 'fileReader' may not be closed\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 14)\n" + >+ " FileReader localReader = new FileReader(file);\n" + >+ " ^^^^^^^^^^^\n" + >+ "Resource leak: 'localReader' is never closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// three AutoCloseables in different blocks of the same method >+public void test056i() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo(boolean f1, boolean f2) throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " if (f1) {\n" + >+ " FileReader fileReader = new FileReader(file); // err: not closed\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " while (true) {\n" + >+ " FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" + >+ " loopReader.close();" + >+ " break;\n" + >+ " }\n" + >+ " } else {\n" + >+ " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + >+ " if (f2)\n" + >+ " fileReader.close();\n" + >+ " }\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo(true, true);\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 8)\n" + >+ " FileReader fileReader = new FileReader(file); // err: not closed\n" + >+ " ^^^^^^^^^^\n" + >+ "Resource leak: 'fileReader' is never closed\n" + >+ "----------\n" + >+ "2. WARNING in X.java (at line 16)\n" + >+ " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + >+ " ^^^^^^^^^^\n" + >+ "Potential resource leak: 'fileReader' may not be closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// three AutoCloseables in different blocks of the same method - problems ignored >+public void test056i_ignore() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.IGNORE); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.IGNORE); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo(boolean f1, boolean f2) throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " if (f1) {\n" + >+ " FileReader fileReader = new FileReader(file); // err: not closed\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " while (true) {\n" + >+ " FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" + >+ " loopReader.close();" + >+ " break;\n" + >+ " }\n" + >+ " } else {\n" + >+ " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + >+ " if (f2)\n" + >+ " fileReader.close();\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// three AutoCloseables in different blocks of the same method >+public void test056i2() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo(boolean f1, boolean f2) throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " if (f1) {\n" + >+ " FileReader fileReader = new FileReader(file); // properly closed\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " while (true) {\n" + >+ " fileReader.close();\n" + >+ " FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" + >+ " loopReader.close();\n" + >+ " break;\n" + >+ " }\n" + >+ " } else {\n" + >+ " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + >+ " if (f2)\n" + >+ " fileReader.close();\n" + >+ " }\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo(true, true);\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 18)\n" + >+ " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + >+ " ^^^^^^^^^^\n" + >+ "Potential resource leak: 'fileReader' may not be closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// a method uses an AutoCloseable without closing it locally but passing as arg to another method >+public void test056j() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " read(fileReader);\n" + >+ " }\n" + >+ " void read(FileReader reader) { }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 7)\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " ^^^^^^^^^^\n" + >+ "Potential resource leak: 'fileReader' may not be closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// a method uses an AutoCloseable without closing it locally but passing as arg to another method >+public void test056jconditional() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo(boolean b) throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " synchronized (b ? this : new X()) {\n" + >+ " new ReadDelegator(fileReader);\n" + >+ " }\n" + >+ " }\n" + >+ " class ReadDelegator { ReadDelegator(FileReader reader) { } }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo(true);\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 7)\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " ^^^^^^^^^^\n" + >+ "Potential resource leak: 'fileReader' may not be closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// many locals, some are AutoCloseable. >+// Unfortunately analysis cannot respect how exception exits may affect ra3 and rb3, >+// doing so would create false positives. >+public void test056k() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING); >+ options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR); >+ String expectedProblems = this.complianceLevel < ClassFileConstants.JDK1_7 ? >+ "----------\n" + >+ "1. ERROR in X.java (at line 15)\n" + >+ " ra2 = new FileReader(file);\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: \'ra2\' is never closed\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 28)\n" + >+ " rb2 = new FileReader(file);\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: \'rb2\' is never closed\n" + >+ "----------\n" >+ : >+ "----------\n" + >+ "1. ERROR in X.java (at line 12)\n" + >+ " FileReader ra1 = null, ra2 = null;\n" + >+ " ^^^\n" + >+ "Resource 'ra1' should be managed by try-with-resource\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 15)\n" + >+ " ra2 = new FileReader(file);\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: 'ra2' is never closed\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 16)\n" + >+ " FileReader ra3 = new FileReader(file);\n" + >+ " ^^^\n" + >+ "Resource 'ra3' should be managed by try-with-resource\n" + >+ "----------\n" + >+ "4. ERROR in X.java (at line 25)\n" + >+ " FileReader rb1 = null, rb2 = null;\n" + >+ " ^^^\n" + >+ "Resource 'rb1' should be managed by try-with-resource\n" + >+ "----------\n" + >+ "5. ERROR in X.java (at line 28)\n" + >+ " rb2 = new FileReader(file);\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: 'rb2' is never closed\n" + >+ "----------\n" + >+ "6. ERROR in X.java (at line 29)\n" + >+ " FileReader rb3 = new FileReader(file);\n" + >+ " ^^^\n" + >+ "Resource 'rb3' should be managed by try-with-resource\n" + >+ "----------\n"; >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " int i01, i02, i03, i04, i05, i06, i07, i08, i09,\n" + >+ " i11, i12, i13, i14, i15, i16, i17, i18, i19,\n" + >+ " i21, i22, i23, i24, i25, i26, i27, i28, i29,\n" + >+ " i31, i32, i33, i34, i35, i36, i37, i38, i39,\n" + >+ " i41, i42, i43, i44, i45, i46, i47, i48, i49;\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader ra1 = null, ra2 = null;\n" + >+ " try {\n" + >+ " ra1 = new FileReader(file);\n" + >+ " ra2 = new FileReader(file);\n" + >+ " FileReader ra3 = new FileReader(file);\n" + >+ " char[] in = new char[50];\n" + >+ " ra1.read(in);\n" + >+ " ra2.read(in);\n" + >+ " ra3.close();\n" + >+ " } finally {\n" + >+ " ra1.close();\n" + >+ " }\n" + >+ " int i51, i52, i53, i54, i55, i56, i57, i58, i59, i60;\n" + // beyond this point locals are analyzed using extraBits >+ " FileReader rb1 = null, rb2 = null;\n" + >+ " try {\n" + >+ " rb1 = new FileReader(file);\n" + >+ " rb2 = new FileReader(file);\n" + >+ " FileReader rb3 = new FileReader(file);\n" + >+ " char[] in = new char[50];\n" + >+ " rb1.read(in);\n" + >+ " rb2.read(in);\n" + >+ " rb3.close();\n" + >+ " } finally {\n" + >+ " rb1.close();\n" + >+ " }\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ expectedProblems, >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// various non-problems >+public void test056l() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR); >+ String expectedProblems = this.complianceLevel >= ClassFileConstants.JDK1_7 ? >+ "----------\n" + >+ "1. ERROR in X.java (at line 8)\n" + >+ " FileReader fileReader = getReader();\n" + >+ " ^^^^^^^^^^\n" + >+ "Resource 'fileReader' should be managed by try-with-resource\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 11)\n" + >+ " FileReader r3 = getReader();\n" + >+ " ^^\n" + >+ "Resource 'r3' should be managed by try-with-resource\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 24)\n" + >+ " FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" + >+ " ^^\n" + >+ "Potential resource leak: 'r2' may not be closed\n" + >+ "----------\n" >+ : >+ "----------\n" + >+ "1. ERROR in X.java (at line 24)\n" + >+ " FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" + >+ " ^^\n" + >+ "Potential resource leak: 'r2' may not be closed\n" + >+ "----------\n"; >+ 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" >+ }, >+ expectedProblems, >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// nested try with early exit >+public void test056m() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() {\n" + >+ " File file = new File(\"somefile\");" + >+ " try {\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " try {\n" + >+ " char[] in = new char[50];\n" + >+ " if (fileReader.read(in)==0)\n" + >+ " return;\n" + >+ " } finally {\n" + >+ " fileReader.close();\n" + >+ " }\n" + >+ " } catch (IOException e) {\n" + >+ " System.out.println(\"caught\");\n" + >+ " }\n" + >+ " }\n" + >+ " public static void main(String[] args) {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "caught", /*output*/ >+ null/*classLibs*/, >+ true/*shouldFlush*/, >+ null/*vmargs*/, >+ options, >+ null/*requestor*/); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// nested try should not interfere with earlier analysis. >+public void test056n() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "import java.io.FileNotFoundException;\n" + >+ "public class X {\n" + >+ " void foo(File someFile, char[] buf) throws IOException {\n" + >+ " FileReader fr1 = new FileReader(someFile);\n" + >+ " try {\n" + >+ " fr1.read(buf);\n" + >+ " } finally {\n" + >+ " fr1.close();\n" + >+ " }\n" + >+ " try {\n" + >+ " FileReader fr3 = new FileReader(someFile);\n" + >+ " try {\n" + >+ " } finally {\n" + >+ " fr3.close();\n" + >+ " }\n" + >+ " } catch (IOException e) {\n" + >+ " }\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " try {\n" + >+ " new X().foo(new File(\"missing\"), new char[100]);\n" + >+ " } catch (FileNotFoundException e) {\n" + >+ " System.out.println(\"caught\");\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "caught", /*output*/ >+ null/*classLibs*/, >+ true/*shouldFlush*/, >+ null/*vmargs*/, >+ options, >+ null/*requestor*/); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// if close is guarded by null check this should still be recognized as definitely closed >+public void test056o() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "import java.io.FileNotFoundException;\n" + >+ "public class X {\n" + >+ " void foo(File someFile, char[] buf) throws IOException {\n" + >+ " FileReader fr1 = null;\n" + >+ " try {\n" + >+ " fr1 = new FileReader(someFile);" + >+ " fr1.read(buf);\n" + >+ " } finally {\n" + >+ " if (fr1 != null)\n" + >+ " try {\n" + >+ " fr1.close();\n" + >+ " } catch (IOException e) { /*do nothing*/ }\n" + >+ " }\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " try {\n" + >+ " new X().foo(new File(\"missing\"), new char[100]);\n" + >+ " } catch (FileNotFoundException e) {\n" + >+ " System.out.println(\"caught\");\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "caught", /*output*/ >+ null/*classLibs*/, >+ true/*shouldFlush*/, >+ null/*vmargs*/, >+ options, >+ null/*requestor*/); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// Bug 362332 - Only report potential leak when closeable not created in the local scope >+// a method uses an AutoCloseable without ever closing it, type from a type variable >+public void test056p() { >+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // generics used >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.Reader;\n" + >+ "import java.io.IOException;\n" + >+ "public abstract class X <T extends Reader> {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " T fileReader = newReader(file);\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " }\n" + >+ " abstract T newReader(File file) throws IOException;\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X<FileReader>() {\n" + >+ " FileReader newReader(File f) throws IOException { return new FileReader(f); }\n" + >+ " }.foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 8)\n" + >+ " T fileReader = newReader(file);\n" + >+ " ^^^^^^^^^^\n" + >+ "Potential resource leak: \'fileReader\' may not be closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// closed in dead code >+public void test056q() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " if (2*2 == 4)\n" + >+ " return;\n" + >+ " fileReader.close();\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 7)\n" + >+ " FileReader fileReader = new FileReader(file);\n" + >+ " ^^^^^^^^^^\n" + >+ "Resource leak: 'fileReader' is never closed\n" + >+ "----------\n" + >+ "2. WARNING in X.java (at line 10)\n" + >+ " if (2*2 == 4)\n" + >+ " ^^^^^^^^\n" + >+ "Comparing identical expressions\n" + >+ "----------\n" + >+ "3. WARNING in X.java (at line 12)\n" + >+ " fileReader.close();\n" + >+ " ^^^^^^^^^^^^^^^^^^\n" + >+ "Dead code\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// properly closed, dead code in between >+public void test056r() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileReader fr = new FileReader(file);\n" + >+ " Object b = null;\n" + >+ " fr.close();\n" + >+ " if (b != null) {\n" + >+ " fr = new FileReader(file);\n" + >+ " return;\n" + >+ " } else {\n" + >+ " System.out.print(42);\n" + >+ " }\n" + >+ " return; // Should not complain about fr\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 10)\n" + >+ " if (b != null) {\n" + >+ " fr = new FileReader(file);\n" + >+ " return;\n" + >+ " } else {\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Dead code\n" + >+ "----------\n" + >+ "2. WARNING in X.java (at line 13)\n" + >+ " } else {\n" + >+ " System.out.print(42);\n" + >+ " }\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Statement unnecessarily nested within else clause. The corresponding then clause does not complete normally\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// resource inside t-w-r is re-assigned, shouldn't even record an errorLocation >+public void test056s() { >+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // t-w-r used >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " try (FileReader fileReader = new FileReader(file);) {\n" + >+ " char[] in = new char[50];\n" + >+ " fileReader.read(in);\n" + >+ " fileReader = new FileReader(file); // debug here\n" + >+ " fileReader.read(in);\n" + >+ " }\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 10)\n" + >+ " fileReader = new FileReader(file); // debug here\n" + >+ " ^^^^^^^^^^\n" + >+ "The resource fileReader of a try-with-resources statement cannot be assigned\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// resource is closed, dead code follows >+public void test056t() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo31() throws IOException {\n" + >+ " FileReader reader = new FileReader(\"file\"); //warning\n" + >+ " if (reader != null) {\n" + >+ " reader.close();\n" + >+ " } else {\n" + >+ " // nop\n" + >+ " }\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo31();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 8)\n" + >+ " } else {\n" + >+ " // nop\n" + >+ " }\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Dead code\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// resource is reassigned within t-w-r with different resource >+// was initially broken due to https://bugs.eclipse.org/358827 >+public void test056u() { >+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // t-w-r used >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " void foo() throws Exception {\n" + >+ " FileReader reader1 = new FileReader(\"file1\");\n" + >+ " FileReader reader2 = new FileReader(\"file2\");\n" + >+ " reader2 = reader1;// this disconnects reader 2\n" + >+ " try (FileReader reader3 = new FileReader(\"file3\")) {\n" + >+ " int ch;\n" + >+ " while ((ch = reader2.read()) != -1) {\n" + >+ " System.out.println(ch);\n" + >+ " reader1.read();\n" + >+ " }\n" + >+ " reader2 = reader1; // warning 1 regarding original reader1\n" + // this warning was missing >+ " reader2 = reader1; // warning 2 regarding original reader1\n" + >+ " } finally {\n" + >+ " if (reader2 != null) {\n" + >+ " reader2.close();\n" + >+ " } else {\n" + >+ " System.out.println();\n" + >+ " }\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 5)\n" + >+ " FileReader reader2 = new FileReader(\"file2\");\n" + >+ " ^^^^^^^\n" + >+ "Resource leak: 'reader2' is never closed\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 13)\n" + >+ " reader2 = reader1; // warning 1 regarding original reader1\n" + >+ " ^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: 'reader1' is not closed at this location\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 14)\n" + >+ " reader2 = reader1; // warning 2 regarding original reader1\n" + >+ " ^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: 'reader1' is not closed at this location\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// scope-related pbs reported in https://bugs.eclipse.org/349326#c70 and https://bugs.eclipse.org/349326#c82 >+public void test056v() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ String expectedProblems = this.complianceLevel >= ClassFileConstants.JDK1_7 ? >+ "----------\n" + >+ "1. ERROR in X.java (at line 4)\n" + >+ " FileReader reader = new FileReader(\"file\");\n" + >+ " ^^^^^^\n" + >+ "Resource leak: 'reader' is never closed\n" + >+ "----------\n" + >+ "2. WARNING in X.java (at line 19)\n" + >+ " FileReader reader111 = new FileReader(\"file2\");\n" + >+ " ^^^^^^^^^\n" + >+ "Resource 'reader111' should be managed by try-with-resource\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 42)\n" + >+ " return;\n" + >+ " ^^^^^^^\n" + >+ "Resource leak: 'reader2' is not closed at this location\n" + >+ "----------\n" >+ : >+ "----------\n" + >+ "1. ERROR in X.java (at line 4)\n" + >+ " FileReader reader = new FileReader(\"file\");\n" + >+ " ^^^^^^\n" + >+ "Resource leak: 'reader' is never closed\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 42)\n" + >+ " return;\n" + >+ " ^^^^^^^\n" + >+ "Resource leak: 'reader2' is not closed at this location\n" + >+ "----------\n"; >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " boolean foo1() throws Exception {\n" + >+ " FileReader reader = new FileReader(\"file\");\n" + >+ " try {\n" + >+ " int ch;\n" + >+ " while ((ch = reader.read()) != -1) {\n" + >+ " System.out.println(ch);\n" + >+ " reader.read();\n" + >+ " }\n" + >+ " if (ch > 10) {\n" + >+ " return true;\n" + >+ " }\n" + >+ " return false;\n" + // return while resource from enclosing scope remains unclosed >+ " } finally {\n" + >+ " }\n" + >+ " }\n" + >+ " void foo111() throws Exception {\n" + >+ " FileReader reader111 = new FileReader(\"file2\");\n" + >+ " try {\n" + >+ " int ch;\n" + >+ " while ((ch = reader111.read()) != -1) {\n" + >+ " System.out.println(ch);\n" + >+ " reader111.read();\n" + >+ " }\n" + >+ " return;\n" + // this shouldn't spoil the warning "should be managed with t-w-r" >+ " } finally {\n" + >+ " if (reader111 != null) {\n" + >+ " reader111.close();\n" + >+ " }\n" + >+ " }\n" + >+ " }\n" + >+ " void foo2() throws Exception {\n" + >+ " FileReader reader2 = new FileReader(\"file\");\n" + >+ " try {\n" + >+ " int ch;\n" + >+ " while ((ch = reader2.read()) != -1) {\n" + >+ " System.out.println(ch);\n" + >+ " reader2.read();\n" + >+ " }\n" + >+ " if (ch > 10) {\n" + >+ " return;\n" + // potential leak >+ " }\n" + >+ " } finally {\n" + >+ " }\n" + >+ " reader2.close();\n" + // due to this close we don't say "never closed" >+ " }\n" + >+ "}\n" >+ }, >+ expectedProblems, >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// end of method is dead end, but before we have both a close() and an early return >+public void test056w() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " boolean foo1() throws Exception {\n" + >+ " FileReader reader = new FileReader(\"file\");\n" + >+ " try {\n" + >+ " int ch;\n" + >+ " while ((ch = reader.read()) != -1) {\n" + >+ " System.out.println(ch);\n" + >+ " reader.read();\n" + >+ " }\n" + >+ " if (ch > 10) {\n" + >+ " reader.close();\n" + >+ " return true;\n" + >+ " }\n" + >+ " return false;\n" + >+ " } finally {\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 15)\n" + >+ " return false;\n" + >+ " ^^^^^^^^^^^^^\n" + >+ "Resource leak: 'reader' is not closed at this location\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// different early exits, if no close seen report as definitely unclosed >+public void test056x() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " void foo31(boolean b) throws Exception {\n" + >+ " FileReader reader = new FileReader(\"file\");\n" + >+ " if (b) {\n" + >+ " reader.close();\n" + >+ " } else {\n" + >+ " return; // warning\n" + >+ " }\n" + >+ " }\n" + >+ " void foo32(boolean b) throws Exception {\n" + >+ " FileReader reader = new FileReader(\"file\"); // warn here\n" + >+ " return;\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 8)\n" + >+ " return; // warning\n" + >+ " ^^^^^^^\n" + >+ "Resource leak: 'reader' is not closed at this location\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 12)\n" + >+ " FileReader reader = new FileReader(\"file\"); // warn here\n" + >+ " ^^^^^^\n" + >+ "Resource leak: 'reader' is never closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// nested method passes the resource to outside code >+public void test056y() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " void foo31(boolean b) throws Exception {\n" + >+ " final FileReader reader31 = new FileReader(\"file\");\n" + >+ " new Runnable() {\n" + >+ " public void run() {\n" + >+ " foo18(reader31);\n" + >+ " }\n" + >+ " }.run();\n" + >+ " }\n" + >+ " void foo18(FileReader r18) {\n" + >+ " // could theoretically close r18;\n" + >+ " }\n" + >+ " abstract class ResourceProvider {\n" + >+ " abstract FileReader provide();" + >+ " }\n" + >+ " ResourceProvider provider;" + >+ " void foo23() throws Exception {\n" + >+ " final FileReader reader23 = new FileReader(\"file\");\n" + >+ " provider = new ResourceProvider() {\n" + >+ " public FileReader provide() {\n" + >+ " return reader23;\n" + >+ " }\n" + >+ " };\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. WARNING in X.java (at line 4)\n" + >+ " final FileReader reader31 = new FileReader(\"file\");\n" + >+ " ^^^^^^^^\n" + >+ "Potential resource leak: 'reader31' may not be closed\n" + >+ "----------\n" + >+ "2. WARNING in X.java (at line 17)\n" + >+ " final FileReader reader23 = new FileReader(\"file\");\n" + >+ " ^^^^^^^^\n" + >+ "Potential resource leak: 'reader23' may not be closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// resource assigned to second local and is (potentially) closed on the latter >+public void test056z() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " void foo17() throws Exception {\n" + >+ " FileReader reader17 = new FileReader(\"file\");\n" + >+ " final FileReader readerCopy = reader17;\n" + >+ " readerCopy.close();\n" + >+ " }\n" + >+ " void foo17a() throws Exception {\n" + >+ " FileReader reader17a = new FileReader(\"file\");\n" + >+ " FileReader readerCopya;" + >+ " readerCopya = reader17a;\n" + >+ " bar(readerCopya);\n" + // potentially closes >+ " }\n" + >+ " void bar(FileReader r) {}\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 9)\n" + >+ " FileReader reader17a = new FileReader(\"file\");\n" + >+ " ^^^^^^^^^\n" + >+ "Potential resource leak: 'reader17a' may not be closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// multiple early exists from nested scopes (always closed) >+public void test056zz() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ runTestsExpectingErrorsOnlyIn17( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " void foo16() throws Exception {\n" + >+ " FileReader reader16 = new FileReader(\"file\");\n" + >+ " try {\n" + >+ " reader16.close();\n " + >+ " return;\n" + >+ " } catch (RuntimeException re) {\n" + >+ " return;\n" + >+ " } catch (Error e) {\n" + >+ " return;\n" + >+ " } finally {\n" + >+ " reader16.close();\n " + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 4)\n" + >+ " FileReader reader16 = new FileReader(\"file\");\n" + >+ " ^^^^^^^^\n" + >+ "Resource 'reader16' should be managed by try-with-resource\n" + >+ "----------\n", >+ options); >+} >+// Bug 349326 - [1.7] new warning for missing try-with-resources >+// multiple early exists from nested scopes (never closed) >+public void test056zzz() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " void foo16() throws Exception {\n" + >+ " FileReader reader16 = new FileReader(\"file\");\n" + >+ " try {\n" + >+ " return;\n" + >+ " } catch (RuntimeException re) {\n" + >+ " return;\n" + >+ " } catch (Error e) {\n" + >+ " return;\n" + >+ " } finally {\n" + >+ " System.out.println();\n " + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 4)\n" + >+ " FileReader reader16 = new FileReader(\"file\");\n" + >+ " ^^^^^^^^\n" + >+ "Resource leak: 'reader16' is never closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points >+// explicit throw is a true method exit here >+public void test056throw1() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " void foo2(boolean a, boolean b, boolean c) throws Exception {\n" + >+ " FileReader reader = new FileReader(\"file\");\n" + >+ " if(a)\n" + >+ " throw new Exception(); //warning 1\n" + >+ " else if (b)\n" + >+ " reader.close();\n" + >+ " else if(c)\n" + >+ " throw new Exception(); //warning 2\n" + >+ " reader.close();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 6)\n" + >+ " throw new Exception(); //warning 1\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: 'reader' is not closed at this location\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 10)\n" + >+ " throw new Exception(); //warning 2\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: 'reader' is not closed at this location\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points >+// close() within finally provides protection for throw >+public void test056throw2() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ runTestsExpectingErrorsOnlyIn17( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " void foo1() throws Exception {\n" + >+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >+ " try {\n" + >+ " reader.read();\n" + >+ " return;\n" + >+ " } catch (Exception e) {\n" + >+ " throw new Exception();\n" + >+ " } finally {\n" + >+ " reader.close();\n" + >+ " }\n" + >+ " }\n" + >+ "\n" + >+ " void foo2() throws Exception {\n" + >+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >+ " try {\n" + >+ " reader.read();\n" + >+ " throw new Exception(); // should not warn here\n" + >+ " } catch (Exception e) {\n" + >+ " throw new Exception();\n" + >+ " } finally {\n" + >+ " reader.close();\n" + >+ " }\n" + >+ " }\n" + >+ "\n" + >+ " void foo3() throws Exception {\n" + >+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >+ " try {\n" + >+ " reader.read();\n" + >+ " throw new Exception();\n" + >+ " } finally {\n" + >+ " reader.close();\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 4)\n" + >+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >+ " ^^^^^^\n" + >+ "Resource 'reader' should be managed by try-with-resource\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 16)\n" + >+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >+ " ^^^^^^\n" + >+ "Resource 'reader' should be managed by try-with-resource\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 28)\n" + >+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >+ " ^^^^^^\n" + >+ "Resource 'reader' should be managed by try-with-resource\n" + >+ "----------\n", >+ options); >+} >+// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points >+// close() nested within finally provides protection for throw >+public void test056throw3() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ runTestsExpectingErrorsOnlyIn17( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " void foo2x() throws Exception {\n" + >+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >+ " try {\n" + >+ " reader.read();\n" + >+ " throw new Exception(); // should not warn here\n" + >+ " } catch (Exception e) {\n" + >+ " throw new Exception();\n" + >+ " } finally {\n" + >+ " if (reader != null)\n" + >+ " try {\n" + >+ " reader.close();\n" + >+ " } catch (java.io.IOException io) {}\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 4)\n" + >+ " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >+ " ^^^^^^\n" + >+ "Resource 'reader' should be managed by try-with-resource\n" + >+ "----------\n", >+ options); >+} >+// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points >+// additional boolean should shed doubt on whether we reach the close() call >+public void test056throw4() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " void foo2x(boolean b) throws Exception {\n" + >+ " FileReader reader = new FileReader(\"file\");\n" + >+ " try {\n" + >+ " reader.read();\n" + >+ " throw new Exception(); // should warn here\n" + >+ " } catch (Exception e) {\n" + >+ " throw new Exception(); // should warn here\n" + >+ " } finally {\n" + >+ " if (reader != null && b)\n" + // this condition is too strong to protect reader >+ " try {\n" + >+ " reader.close();\n" + >+ " } catch (java.io.IOException io) {}\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 7)\n" + >+ " throw new Exception(); // should warn here\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Potential resource leak: 'reader' may not be closed at this location\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 9)\n" + >+ " throw new Exception(); // should warn here\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Potential resource leak: 'reader' may not be closed at this location\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points >+// similar to test056throw3() but indirectly calling close(), so doubts remain. >+public void test056throw5() { >+ Map options = getCompilerOptions(); >+ options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >+ options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileReader;\n" + >+ "public class X {\n" + >+ " void foo2x() throws Exception {\n" + >+ " FileReader reader = new FileReader(\"file\");\n" + >+ " try {\n" + >+ " reader.read();\n" + >+ " throw new Exception(); // should warn 'may not' here\n" + >+ " } catch (Exception e) {\n" + >+ " throw new Exception(); // should warn 'may not' here\n" + >+ " } finally {\n" + >+ " doClose(reader);\n" + >+ " }\n" + >+ " }\n" + >+ " void doClose(FileReader r) { try { r.close(); } catch (java.io.IOException ex) {}}\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 7)\n" + >+ " throw new Exception(); // should warn \'may not\' here\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Potential resource leak: 'reader' may not be closed at this location\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 9)\n" + >+ " throw new Exception(); // should warn \'may not\' here\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Potential resource leak: 'reader' may not be closed at this location\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly >+// a resource wrapper is not closed but the underlying resource is >+public void test061a() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileInputStream fileStream = new FileInputStream(file);\n" + >+ " BufferedInputStream bis = new BufferedInputStream(fileStream);\n" + >+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" + >+ " System.out.println(bis.available());\n" + >+ " fileStream.close();\n" + >+ " }\n" + >+ " void inline() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileInputStream fileStream;\n" + >+ " BufferedInputStream bis = new BufferedInputStream(fileStream = new FileInputStream(file));\n" + >+ " System.out.println(bis.available());\n" + >+ " fileStream.close();\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " try {\n" + >+ " new X().foo();\n" + >+ " } catch (IOException ex) {" + >+ " System.out.println(\"Got IO Exception\");\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "Got IO Exception", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// a closeable without OS resource is not closed >+public void test061b() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.StringReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " StringReader string = new StringReader(\"content\");\n" + >+ " System.out.println(string.read());\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "99", // character 'c' >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// a resource wrapper is not closed but the underlying closeable is resource-free >+public void test061c() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.BufferedReader;\n" + >+ "import java.io.StringReader;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " StringReader input = new StringReader(\"content\");\n" + >+ " BufferedReader br = new BufferedReader(input);\n" + >+ " BufferedReader doubleWrap = new BufferedReader(br);\n" + >+ " System.out.println(br.read());\n" + >+ " }\n" + >+ " void inline() throws IOException {\n" + >+ " BufferedReader br = new BufferedReader(new StringReader(\"content\"));\n" + >+ " System.out.println(br.read());\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " new X().foo();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "99", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// a resource wrapper is not closed neither is the underlying resource >+public void test061d() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileInputStream fileStream = new FileInputStream(file);\n" + >+ " BufferedInputStream bis = new BufferedInputStream(fileStream);\n" + >+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" + >+ " System.out.println(bis.available());\n" + >+ " }\n" + >+ " void inline() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(file));\n" + >+ " System.out.println(bis2.available());\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " try {\n" + >+ " new X().foo();\n" + >+ " } catch (IOException ex) {" + >+ " System.out.println(\"Got IO Exception\");\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 10)\n" + >+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" + >+ " ^^^^^^^^^^\n" + >+ "Resource leak: \'doubleWrap\' is never closed\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 15)\n" + >+ " BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(file));\n" + >+ " ^^^^\n" + >+ "Resource leak: \'bis2\' is never closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly >+// a resource wrapper is closed closing also the underlying resource >+public void test061e() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " FileInputStream fis;" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileInputStream fileStream = new FileInputStream(file);\n" + >+ " BufferedInputStream bis = new BufferedInputStream(fileStream);\n" + >+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" + >+ " System.out.println(bis.available());\n" + >+ " bis.close();\n" + >+ " }\n" + >+ " void inline() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " BufferedInputStream bis2 = new BufferedInputStream(fis = new FileInputStream(file));\n" + // field assignment >+ " System.out.println(bis2.available());\n" + >+ " bis2.close();\n" + >+ " FileInputStream fileStream = null;\n" + >+ " BufferedInputStream bis3 = new BufferedInputStream(fileStream = new FileInputStream(file));\n" + >+ " System.out.println(bis3.available());\n" + >+ " bis3.close();\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " try {\n" + >+ " new X().foo();\n" + >+ " } catch (IOException ex) {" + >+ " System.out.println(\"Got IO Exception\");\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "Got IO Exception", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly >+// a resource wrapper is closed closing also the underlying resource - original test case >+public void test061f() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ URL url = FileLocator.toFileURL(FileLocator.find(Platform.getBundle("org.eclipse.jdt.core.tests.compiler"), new Path("META-INF/MANIFEST.MF"), null)); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.InputStream;\n" + >+ "import java.io.InputStreamReader;\n" + >+ "import java.io.BufferedReader;\n" + >+ "import java.io.IOException;\n" + >+ "import java.net.URL;\n" + >+ "public class X {\n" + >+ " boolean loadURL(final URL url) throws IOException {\n" + >+ " InputStream stream = null;\n" + >+ " BufferedReader reader = null;\n" + >+ " try {\n" + >+ " stream = url.openStream();\n" + >+ " reader = new BufferedReader(new InputStreamReader(stream));\n" + >+ " System.out.println(reader.readLine());\n" + >+ " } finally {\n" + >+ " try {\n" + >+ " if (reader != null)\n" + >+ " reader.close();\n" + >+ " } catch (IOException x) {\n" + >+ " }\n" + >+ " }\n" + >+ " return false; // 'stream' may not be closed at this location\n" + >+ " }\n" + >+ " public static void main(String[] args) throws IOException {\n" + >+ " try {\n" + >+ " new X().loadURL(new URL(\""+url.toString()+"\"));\n" + >+ " } catch (IOException ex) {\n" + >+ " System.out.println(\"Got IO Exception\"+ex);\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "Manifest-Version: 1.0", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly >+// a resource wrapper is closed closing also the underlying resource - from a real-world example >+public void test061f2() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.OutputStream;\n" + >+ "import java.io.FileOutputStream;\n" + >+ "import java.io.BufferedOutputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void zork() throws IOException {\n" + >+ " try {\n" + >+ " OutputStream os = null;\n" + >+ " try {\n" + >+ " os = new BufferedOutputStream(new FileOutputStream(\"somefile\"));\n" + >+ " String externalForm = \"externalPath\";\n" + >+ " } finally {\n" + >+ " if (os != null)\n" + >+ " os.close();\n" + >+ " }\n" + >+ " } catch (IOException e) {\n" + >+ " e.printStackTrace();\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly >+// a resource wrapper is sent to another method affecting also the underlying resource - from a real-world example >+public void test061f3() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.FileNotFoundException;\n" + >+ "import java.io.InputStream;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "public class X {\n" + >+ " String loadProfile(File profileFile) {\n" + >+ " try {\n" + >+ " InputStream stream = new BufferedInputStream(new FileInputStream(profileFile));\n" + >+ " return loadProfile(stream);\n" + >+ " } catch (FileNotFoundException e) {\n" + >+ " //null\n" + >+ " }\n" + >+ " return null;\n" + >+ " }\n" + >+ " private String loadProfile(InputStream stream) {\n" + >+ " return null;\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 10)\n" + >+ " return loadProfile(stream);\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Potential resource leak: \'stream\' may not be closed at this location\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly >+// Different points in a resource chain are closed >+public void test061g() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void closeMiddle() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileInputStream fileStream = new FileInputStream(file);\n" + >+ " BufferedInputStream bis = new BufferedInputStream(fileStream);\n" + >+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" + >+ " System.out.println(bis.available());\n" + >+ " bis.close();\n" + >+ " }\n" + >+ " void closeOuter() throws IOException {\n" + >+ " File file2 = new File(\"somefile\");\n" + >+ " FileInputStream fileStream2 = new FileInputStream(file2);\n" + >+ " BufferedInputStream bis2 = new BufferedInputStream(fileStream2);\n" + >+ " BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" + >+ " System.out.println(bis2.available());\n" + >+ " doubleWrap2.close();\n" + >+ " }\n" + >+ " void neverClosed() throws IOException {\n" + >+ " File file3 = new File(\"somefile\");\n" + >+ " FileInputStream fileStream3 = new FileInputStream(file3);\n" + >+ " BufferedInputStream bis3 = new BufferedInputStream(fileStream3);\n" + >+ " BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" + >+ " System.out.println(doubleWrap3.available());\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 26)\n" + >+ " BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" + >+ " ^^^^^^^^^^^\n" + >+ "Resource leak: \'doubleWrap3\' is never closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly >+// Different points in a resource chain are potentially closed >+public void test061h() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void closeMiddle(boolean b) throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " FileInputStream fileStream = new FileInputStream(file);\n" + >+ " BufferedInputStream bis = new BufferedInputStream(fileStream);\n" + >+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" + >+ " System.out.println(bis.available());\n" + >+ " if (b)\n" + >+ " bis.close();\n" + >+ " }\n" + >+ " void closeOuter(boolean b) throws IOException {\n" + >+ " File file2 = new File(\"somefile\");\n" + >+ " FileInputStream fileStream2 = new FileInputStream(file2);\n" + >+ " BufferedInputStream dummy;\n" + >+ " BufferedInputStream bis2 = (dummy = new BufferedInputStream(fileStream2));\n" + >+ " BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" + >+ " System.out.println(bis2.available());\n" + >+ " if (b)\n" + >+ " doubleWrap2.close();\n" + >+ " }\n" + >+ " void potAndDef(boolean b) throws IOException {\n" + >+ " File file3 = new File(\"somefile\");\n" + >+ " FileInputStream fileStream3 = new FileInputStream(file3);\n" + >+ " BufferedInputStream bis3 = new BufferedInputStream(fileStream3);\n" + >+ " BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" + >+ " System.out.println(doubleWrap3.available());\n" + >+ " if (b) bis3.close();\n" + >+ " fileStream3.close();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 10)\n" + >+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" + >+ " ^^^^^^^^^^\n" + >+ "Potential resource leak: \'doubleWrap\' may not be closed\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 20)\n" + >+ " BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" + >+ " ^^^^^^^^^^^\n" + >+ "Potential resource leak: \'doubleWrap2\' may not be closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// local var is re-used for two levels of wrappers >+public void test061i() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.InputStream;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void closeMiddle() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " InputStream stream = new FileInputStream(file);\n" + >+ " stream = new BufferedInputStream(stream);\n" + >+ " InputStream middle;\n" + >+ " stream = new BufferedInputStream(middle = stream);\n" + >+ " System.out.println(stream.available());\n" + >+ " middle.close();\n" + >+ " }\n" + >+ " void closeOuter() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " InputStream stream2 = new FileInputStream(file);\n" + >+ " stream2 = new BufferedInputStream(stream2);\n" + >+ " stream2 = new BufferedInputStream(stream2);\n" + >+ " System.out.println(stream2.available());\n" + >+ " stream2.close();\n" + >+ " }\n" + >+ " void neverClosed() throws IOException {\n" + >+ " File file = new File(\"somefile\");\n" + >+ " InputStream stream3 = new FileInputStream(file);\n" + >+ " stream3 = new BufferedInputStream(stream3);\n" + >+ " stream3 = new BufferedInputStream(stream3);\n" + >+ " System.out.println(stream3.available());\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 26)\n" + >+ " InputStream stream3 = new FileInputStream(file);\n" + >+ " ^^^^^^^\n" + >+ "Resource leak: \'stream3\' is never closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// self-wrapping a method argument (caused NPE UnconditionalFlowInfo.markAsDefinitelyNull(..)). >+public void test061j() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.InputStream;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo(InputStream stream) throws IOException {\n" + >+ " stream = new BufferedInputStream(stream);\n" + >+ " System.out.println(stream.available());\n" + >+ " stream.close();\n" + >+ " }\n" + >+ " void boo(InputStream stream2) throws IOException {\n" + >+ " stream2 = new BufferedInputStream(stream2);\n" + >+ " System.out.println(stream2.available());\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// a wrapper is created in a return statement >+public void test061k() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " BufferedInputStream getReader(File file) throws IOException {\n" + >+ " FileInputStream stream = new FileInputStream(file);\n" + >+ " return new BufferedInputStream(stream);\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// a closeable is assigned to a field >+public void test061l() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " BufferedInputStream stream;\n" + >+ " void foo(File file) throws IOException {\n" + >+ " FileInputStream s = new FileInputStream(file);\n" + >+ " stream = new BufferedInputStream(s);\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// a closeable is passed to another method in a return statement >+// example constructed after org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository#getArtifact(..) >+public void test061m() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.InputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " BufferedInputStream stream;\n" + >+ " BufferedInputStream foo(File file) throws IOException {\n" + >+ " FileInputStream s = new FileInputStream(file);\n" + >+ " return check(new BufferedInputStream(s));\n" + >+ " }\n" + >+ " BufferedInputStream foo2(FileInputStream s, File file) throws IOException {\n" + >+ " s = new FileInputStream(file);\n" + >+ " return check(s);\n" + >+ " }\n" + >+ " BufferedInputStream foo3(InputStream s) throws IOException {\n" + >+ " s = check(s);\n" + >+ " return check(s);\n" + >+ " }\n" + >+ " BufferedInputStream check(InputStream s) { return null; }\n" + >+ "}\n" >+ }, >+ // TODO: also these warnings *might* be avoidable by detecting check(s) as a wrapper creation?? >+ "----------\n" + >+ "1. ERROR in X.java (at line 14)\n" + >+ " return check(s);\n" + >+ " ^^^^^^^^^^^^^^^^\n" + >+ "Potential resource leak: \'s\' may not be closed at this location\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 18)\n" + >+ " return check(s);\n" + >+ " ^^^^^^^^^^^^^^^^\n" + >+ "Potential resource leak: \'s\' may not be closed at this location\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// a resource wrapper does not wrap any provided resource >+public void test061n() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.PrintWriter;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " PrintWriter writer = new PrintWriter(\"filename\");\n" + >+ " writer.write(1);\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 5)\n" + >+ " PrintWriter writer = new PrintWriter(\"filename\");\n" + >+ " ^^^^^^\n" + >+ "Resource leak: \'writer\' is never closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// a resource wrapper is closed only in its local block, underlying resource may leak >+public void test061o() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo(boolean bar) throws IOException {\n" + >+ " File file = new File(\"somefil\");\n" + >+ " FileInputStream fileStream = new FileInputStream(file);\n" + >+ " BufferedInputStream bis = new BufferedInputStream(fileStream); \n" + >+ " if (bar) {\n" + >+ " BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" + >+ " doubleWrap.close();\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 9)\n" + >+ " BufferedInputStream bis = new BufferedInputStream(fileStream); \n" + >+ " ^^^\n" + >+ "Potential resource leak: \'bis\' may not be closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// a resource wrapper is conditionally allocated but not closed - from a real-world example >+public void test061f4() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.FileNotFoundException;\n" + >+ "import java.io.InputStream;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "public class X {\n" + >+ " void foo(File location, String adviceFilePath) throws FileNotFoundException {\n" + >+ " InputStream stream = null;\n" + >+ " if (location.isDirectory()) {\n" + >+ " File adviceFile = new File(location, adviceFilePath);\n" + >+ " stream = new BufferedInputStream(new FileInputStream(adviceFile));\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 11)\n" + >+ " stream = new BufferedInputStream(new FileInputStream(adviceFile));\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Potential resource leak: \'stream\' may not be closed\n" + // message could be stronger, but the enclosing if blurs the picture >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// a t-w-r wraps an existing resource >+public void test061p() { >+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return; >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.PrintWriter;\n" + >+ "import java.io.BufferedWriter;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " PrintWriter writer = new PrintWriter(\"filename\");\n" + >+ " try (BufferedWriter bw = new BufferedWriter(writer)) {\n" + >+ " bw.write(1);\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// a t-w-r potentially wraps an existing resource >+// DISABLED, fails because we currently don't include t-w-r managed resources in the analysis >+public void _test061q() { >+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return; >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.PrintWriter;\n" + >+ "import java.io.BufferedWriter;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo(boolean b) throws IOException {\n" + >+ " PrintWriter writer = new PrintWriter(\"filename\");\n" + >+ " if (b)\n" + >+ " try (BufferedWriter bw = new BufferedWriter(writer)) {\n" + >+ " bw.write(1);\n" + >+ " }\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 6)\n" + >+ " PrintWriter writer = new PrintWriter(\\\"filename\\\");\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Potential resource leak: \'writer\' may not be closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// the inner from a wrapper is returned >+public void test061r() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileInputStream;\n" + >+ "import java.io.File;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " FileInputStream foo() throws IOException {\n" + >+ " File file = new File(\"somefil\");\n" + >+ " FileInputStream fileStream = new FileInputStream(file);\n" + >+ " BufferedInputStream bis = new BufferedInputStream(fileStream); \n" + >+ " return fileStream;\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 358903 - Filter practically unimportant resource leak warnings >+// a wrapper is forgotten, the inner is closed afterwards >+public void test061s() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileInputStream;\n" + >+ "import java.io.File;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " File file = new File(\"somefil\");\n" + >+ " FileInputStream fileStream = new FileInputStream(file);\n" + >+ " BufferedInputStream bis = new BufferedInputStream(fileStream);\n" + >+ " bis = null;\n" + >+ " fileStream.close();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 362331 - Resource leak not detected when closeable not assigned to variable >+// a resource is never assigned >+public void test062a() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileOutputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " new FileOutputStream(new File(\"C:\\temp\\foo.txt\")).write(1);\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 6)\n" + >+ " new FileOutputStream(new File(\"C:\\temp\\foo.txt\")).write(1);\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 362331 - Resource leak not detected when closeable not assigned to variable >+// a freshly allocated resource is immediately closed >+public void test062b() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileOutputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " new FileOutputStream(new File(\"C:\\temp\\foo.txt\")).close();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 362331 - Resource leak not detected when closeable not assigned to variable >+// a resource is directly passed to another method >+public void test062c() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileOutputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " writeIt(new FileOutputStream(new File(\"C:\\temp\\foo.txt\")));\n" + >+ " }\n" + >+ " void writeIt(FileOutputStream fos) throws IOException {\n" + >+ " fos.write(1);\n" + >+ " fos.close();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 362331 - Resource leak not detected when closeable not assigned to variable >+// a resource is not used >+public void test062d() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileOutputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo() throws IOException {\n" + >+ " new FileOutputStream(new File(\"C:\\temp\\foo.txt\"));\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 6)\n" + >+ " new FileOutputStream(new File(\"C:\\temp\\foo.txt\"));\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 362332 - Only report potential leak when closeable not created in the local scope >+// a wrapper is obtained from another method >+public void test063a() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "import java.io.File;\n" + >+ "import java.io.FileInputStream;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void read(File file) throws IOException {\n" + >+ " FileInputStream stream = new FileInputStream(file);\n" + >+ " BufferedInputStream bis = new BufferedInputStream(stream); // never since reassigned\n" + >+ " FileInputStream stream2 = new FileInputStream(file); // unsure since passed to method\n" + >+ " bis = getReader(stream2); // unsure since obtained from method\n" + >+ " bis.available();\n" + >+ " }\n" + >+ " BufferedInputStream getReader(FileInputStream stream) throws IOException {\n" + >+ " return new BufferedInputStream(stream);\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 7)\n" + >+ " FileInputStream stream = new FileInputStream(file);\n" + >+ " ^^^^^^\n" + >+ "Resource leak: \'stream\' is never closed\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 9)\n" + >+ " FileInputStream stream2 = new FileInputStream(file); // unsure since passed to method\n" + >+ " ^^^^^^^\n" + >+ "Potential resource leak: \'stream2\' may not be closed\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 10)\n" + >+ " bis = getReader(stream2); // unsure since obtained from method\n" + >+ " ^^^^^^^^^^^^^^^^^^^^^^^^\n" + >+ "Potential resource leak: \'bis\' may not be closed\n" + >+ "----------\n", >+ null, >+ true, >+ options); >+} >+// Bug 362332 - Only report potential leak when closeable not created in the local scope >+// a wrapper is obtained from a field read >+public void test063b() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileInputStream;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " FileInputStream stream;\n" + >+ " void read() throws IOException {\n" + >+ " FileInputStream s = this.stream;\n" + >+ " BufferedInputStream bis = new BufferedInputStream(s); // don't complain since s is obtained from a field\n" + >+ " bis.available();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 362332 - Only report potential leak when closeable not created in the local scope >+// a wrapper is assigned to a field >+public void test063c() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileInputStream;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " BufferedInputStream stream;\n" + >+ " void read() throws IOException {\n" + >+ " FileInputStream s = new FileInputStream(\"somefile\");\n" + >+ " BufferedInputStream bis = new BufferedInputStream(s);\n" + >+ " this.stream = bis;\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+// Bug 362332 - Only report potential leak when closeable not created in the local scope >+// a resource is obtained as a method argument and/or assigned with a cast >+public void test063d() throws IOException { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR); >+ runTestsExpectingErrorsOnlyIn17( >+ new String[] { >+ "X.java", >+ "import java.io.FileInputStream;\n" + >+ "import java.io.BufferedInputStream;\n" + >+ "import java.io.InputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " void foo( InputStream input) throws IOException {\n" + >+ " FileInputStream input1 = (FileInputStream)input;\n" + >+ " System.out.println(input1.read());\n" + >+ " input.close();\n" + // don't propose t-w-r for argument >+ " }\n" + >+ " void foo() throws IOException {\n" + >+ " InputStream input = new FileInputStream(\"somefile\");\n" + >+ " FileInputStream input1 = (FileInputStream)input;\n" + >+ " System.out.println(input1.read());\n" + >+ " input.close();\n" + // do propose t-w-r, not from a method argument >+ " }\n" + >+ " void foo3( InputStream input, InputStream input2) throws IOException {\n" + >+ " FileInputStream input1 = (FileInputStream)input;\n" + // still don't claim because obtained from outside >+ " System.out.println(input1.read());\n" + >+ " BufferedInputStream bis = new BufferedInputStream(input2);\n" + >+ " System.out.println(bis.read());\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. ERROR in X.java (at line 12)\n" + >+ " InputStream input = new FileInputStream(\"somefile\");\n" + >+ " ^^^^^\n" + >+ "Resource \'input\' should be managed by try-with-resource\n" + >+ "----------\n", >+ options); >+} >+// Bug 362332 - Only report potential leak when closeable not created in the local scope >+// a resource is obtained from a field read, then re-assigned >+public void test063e() { >+ Map options = getCompilerOptions(); >+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >+ this.runConformTest( >+ new String[] { >+ "X.java", >+ "import java.io.FileInputStream;\n" + >+ "import java.io.IOException;\n" + >+ "public class X {\n" + >+ " FileInputStream input1;\n" + >+ " public void foo() throws IOException {\n" + >+ " FileInputStream input = input1;\n" + >+ " input = new FileInputStream(\"adfafd\");\n" + >+ " input.close();\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "", >+ null, >+ true, >+ null, >+ options, >+ null); >+} >+ >+} >diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java >index 4dbf8ba..5f2f3d8 100644 >--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java >+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2011 IBM Corporation and others. >+ * Copyright (c) 2000, 2012 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -7,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking >+ * Stephan Herrmann - Contributions for >+ * bug 186342 - [compiler][null] Using annotations for null checking >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.core.tests.compiler.regression; > >@@ -74,6 +76,7 @@ public static Test suite() { > standardTests.add(ProgrammingProblemsTest.class); > standardTests.add(ManifestAnalyzerTest.class); > standardTests.add(InitializationTests.class); >+ standardTests.add(ResourceLeakTests.class); > > // add all javadoc tests > for (int i=0, l=JavadocTest.ALL_CLASSES.size(); i<l; i++) { >diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java >index f21a57f..65f140b 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 >@@ -16,14 +16,13 @@ package org.eclipse.jdt.core.tests.compiler.regression; > > import java.util.Map; > >-import org.eclipse.jdt.core.JavaCore; >-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; >- > import junit.framework.Test; >+ >+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; > public class TryWithResourcesStatementTest extends AbstractRegressionTest { > > static { >-// TESTS_NAMES = new String[] { "test056throw"}; >+// TESTS_NAMES = new String[] { "test061m"}; > // TESTS_NUMBERS = new int[] { 50 }; > // TESTS_RANGE = new int[] { 11, -1 }; > } >@@ -3454,1907 +3453,176 @@ 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( >+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=361053 >+public void test057() { >+ 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" + >-// 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" + >+ "public class X implements AutoCloseable {\n" + >+ " @Override\n" + >+ " public void close() throws Exception {\n" + >+ " throw new Exception();\n" + >+ " }\n" + >+ " public static void main(String[] args) {\n" + >+ " final boolean foo;\n" + >+ " try (X a = new X(); X b = new X()) {\n" + >+ " foo = true;\n" + >+ " } catch (final Exception exception) {\n" + >+ " return;\n" + >+ " }\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( >+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=364008 >+public void test058() { >+ this.runConformTest( > new String[] { > "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >+ "import java.io.ByteArrayOutputStream;\n" + >+ "import java.io.FileOutputStream;\n" + > "import java.io.IOException;\n" + >+ "\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" + >+ " public static void main(final String[] args) throws IOException {\n" + >+ " byte[] data;\n" + >+ " try (final ByteArrayOutputStream os = new ByteArrayOutputStream();\n" + >+ " final FileOutputStream out = new FileOutputStream(\"test.dat\")) {\n" + >+ " data = os.toByteArray();\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); >+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=367566 - In try-with-resources statement close() method of resource is not called >+public void test059() { > this.runConformTest( > new String[] { > "X.java", >- "import java.io.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" + >+ "public class X implements java.lang.AutoCloseable {\n" + >+ " static boolean isOpen = true;\n" + >+ " public static void main(final String[] args) throws IOException {\n" + >+ " foo();\n" + >+ " System.out.println(isOpen);\n" + >+ " }\n" + >+ " static boolean foo() {\n" + >+ " try (final X x = new X()) {\n" + >+ " return x.num() >= 1;\n" + > " }\n" + >+ " }\n" + >+ " int num() { return 2; }\n" + >+ " public void close() {\n" + >+ " isOpen = false;\n" + >+ " }\n" + > "}\n" >- }, >- "caught", /*output*/ >- null/*classLibs*/, >- true/*shouldFlush*/, >- null/*vmargs*/, >- options, >- null/*requestor*/); >+ }, >+ "false"); > } >-// 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); >+ >+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=367566 - In try-with-resources statement close() method of resource is not called >+public void test060() { > this.runConformTest( > new String[] { > "X.java", >- "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" + >+ "public class X implements AutoCloseable {\n" + >+ " static int num = 10 ;\n" + >+ " public static void main(String [] args) throws Exception { \n" + >+ " System.out.println(foo(1));\n" + >+ " System.out.println(foo(2));\n" + >+ " System.out.println(foo(3));\n" + > " }\n" + >- " public static void main(String[] args) {\n" + >- " try {\n" + >- " new X().foo();\n" + >- " } catch (IOException ioex) {\n" + >- " System.out.println(\"caught\");\n" + >+ " private static boolean foo(int where) throws Exception {\n" + >+ " final boolean getOut = true;\n" + >+ " System.out.println(\"Main\");\n" + >+ " try (X x1 = new X(); X x2 = new X()) {\n" + >+ " if (where == 1) {\n" + >+ " return where == 1;\n" + >+ " }\n" + >+ " System.out.println(\"Outer Try\");\n" + >+ " while (true) {\n" + >+ " try (Y y1 = new Y(); Y y2 = new Y()) { \n" + >+ " if (where == 2) {\n" + >+ " return where == 2;\n" + >+ " } \n" + >+ " System.out.println(\"Middle Try\");\n" + >+ " try (Z z1 = new Z(); Z z2 = new Z()) {\n" + >+ " System.out.println(\"Inner Try\");\n" + >+ " if (getOut) \n" + >+ " return num >= 10;\n" + >+ " else\n" + >+ " break; \n" + >+ " }\n" + >+ " }\n" + >+ " }\n" + >+ " System.out.println(\"Out of while\");\n" + > " }\n" + >+ " return false;\n" + >+ " }\n" + >+ " public X() {\n" + >+ " System.out.println(\"X::X\");\n" + > " }\n" + >- "}\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" + >+ " @Override\n" + >+ " public void close() throws Exception {\n" + >+ " System.out.println(\"X::~X\");\n" + > " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo(false, true);\n" + >+ "}\n" + >+ "class Y implements AutoCloseable {\n" + >+ " public Y() {\n" + >+ " System.out.println(\"Y::Y\");\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" + >+ " @Override\n" + >+ " public void close() throws Exception {\n" + >+ " System.out.println(\"Y::~Y\");\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" + >+ "class Z implements AutoCloseable {\n" + >+ " public Z() {\n" + >+ " System.out.println(\"Z::Z\");\n" + > " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo(false, true);\n" + >+ " @Override\n" + >+ " public void close() throws Exception {\n" + >+ " System.out.println(\"Z::~Z\");\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); >+ }, >+ "Main\n" + >+ "X::X\n" + >+ "X::X\n" + >+ "X::~X\n" + >+ "X::~X\n" + >+ "true\n" + >+ "Main\n" + >+ "X::X\n" + >+ "X::X\n" + >+ "Outer Try\n" + >+ "Y::Y\n" + >+ "Y::Y\n" + >+ "Y::~Y\n" + >+ "Y::~Y\n" + >+ "X::~X\n" + >+ "X::~X\n" + >+ "true\n" + >+ "Main\n" + >+ "X::X\n" + >+ "X::X\n" + >+ "Outer Try\n" + >+ "Y::Y\n" + >+ "Y::Y\n" + >+ "Middle Try\n" + >+ "Z::Z\n" + >+ "Z::Z\n" + >+ "Inner Try\n" + >+ "Z::~Z\n" + >+ "Z::~Z\n" + >+ "Y::~Y\n" + >+ "Y::~Y\n" + >+ "X::~X\n" + >+ "X::~X\n" + >+ "true"); > } >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// one method returns an AutoCleasble, a second method uses this object without ever closing it. >-public void test056e() { >- Map options = getCompilerOptions(); >- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " FileReader getReader(String filename) throws IOException {\n" + >- " File file = new File(\"somefile\");\n" + >- " FileReader fileReader = new FileReader(file);\n" + >- " return fileReader;\n" + // don't complain here, pass responsibility to caller >- " }\n" + >- " void foo() throws IOException {\n" + >- " FileReader reader = getReader(\"somefile\");\n" + >- " char[] in = new char[50];\n" + >- " reader.read(in);\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 11)\n" + >- " FileReader reader = getReader(\"somefile\");\n" + >- " ^^^^^^\n" + >- "Resource leak: 'reader' is never closed\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// a method explicitly closes its AutoCloseable rather than using t-w-r >-public void test056f() { >- Map options = getCompilerOptions(); >- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING); >- options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo() throws IOException {\n" + >- " File file = new File(\"somefile\");\n" + >- " FileReader fileReader = null;\n" + >- " try {\n" + >- " fileReader = new FileReader(file);\n" + >- " char[] in = new char[50];\n" + >- " fileReader.read(in);\n" + >- " } finally {\n" + >- " fileReader.close();\n" + >- " }\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 7)\n" + >- " FileReader fileReader = null;\n" + >- " ^^^^^^^^^^\n" + >- "Resource 'fileReader' should be managed by try-with-resource\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// an AutoCloseable local is re-assigned >-public void test056g() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo() throws IOException {\n" + >- " File file = new File(\"somefile\");\n" + >- " FileReader fileReader = new FileReader(file);\n" + >- " char[] in = new char[50];\n" + >- " fileReader.read(in);\n" + >- " fileReader = new FileReader(file);\n" + >- " fileReader.read(in);\n" + >- " fileReader.close();\n" + >- " fileReader = null;\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 10)\n" + >- " fileReader = new FileReader(file);\n" + >- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Resource leak: 'fileReader' is not closed at this location\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// an AutoCloseable local is re-assigned after null-assigned >-public void test056g2() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo() throws IOException {\n" + >- " File file = new File(\"somefile\");\n" + >- " FileReader fileReader = new FileReader(file);\n" + >- " char[] in = new char[50];\n" + >- " fileReader.read(in);\n" + >- " fileReader = null;\n" + >- " fileReader = new FileReader(file);\n" + // don't complain again, fileReader is null, so nothing can leak here >- " fileReader.read(in);\n" + >- " fileReader.close();\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 10)\n" + >- " fileReader = null;\n" + >- " ^^^^^^^^^^^^^^^^^\n" + >- "Resource leak: 'fileReader' is not closed at this location\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// two AutoCloseables at different nesting levels (anonymous local type) >-public void test056h() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo() throws IOException {\n" + >- " final File file = new File(\"somefile\");\n" + >- " final FileReader fileReader = new FileReader(file);\n" + >- " char[] in = new char[50];\n" + >- " fileReader.read(in);\n" + >- " new Runnable() {\n public void run() {\n" + >- " try {\n" + >- " fileReader.close();\n" + >- " FileReader localReader = new FileReader(file);\n" + >- " } catch (IOException ex) { /* nop */ }\n" + >- " }}.run();\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. WARNING in X.java (at line 7)\n" + >- " final FileReader fileReader = new FileReader(file);\n" + >- " ^^^^^^^^^^\n" + >- "Potential resource leak: 'fileReader' may not be closed\n" + >- "----------\n" + >- "2. ERROR in X.java (at line 14)\n" + >- " FileReader localReader = new FileReader(file);\n" + >- " ^^^^^^^^^^^\n" + >- "Resource leak: 'localReader' is never closed\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// three AutoCloseables in different blocks of the same method >-public void test056i() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo(boolean f1, boolean f2) throws IOException {\n" + >- " File file = new File(\"somefile\");\n" + >- " if (f1) {\n" + >- " FileReader fileReader = new FileReader(file); // err: not closed\n" + >- " char[] in = new char[50];\n" + >- " fileReader.read(in);\n" + >- " while (true) {\n" + >- " FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" + >- " loopReader.close();" + >- " break;\n" + >- " }\n" + >- " } else {\n" + >- " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + >- " if (f2)\n" + >- " fileReader.close();\n" + >- " }\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo(true, true);\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 8)\n" + >- " FileReader fileReader = new FileReader(file); // err: not closed\n" + >- " ^^^^^^^^^^\n" + >- "Resource leak: 'fileReader' is never closed\n" + >- "----------\n" + >- "2. WARNING in X.java (at line 16)\n" + >- " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + >- " ^^^^^^^^^^\n" + >- "Potential resource leak: 'fileReader' may not be closed\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// three AutoCloseables in different blocks of the same method >-public void test056i2() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo(boolean f1, boolean f2) throws IOException {\n" + >- " File file = new File(\"somefile\");\n" + >- " if (f1) {\n" + >- " FileReader fileReader = new FileReader(file); // properly closed\n" + >- " char[] in = new char[50];\n" + >- " fileReader.read(in);\n" + >- " while (true) {\n" + >- " fileReader.close();\n" + >- " FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" + >- " loopReader.close();\n" + >- " break;\n" + >- " }\n" + >- " } else {\n" + >- " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + >- " if (f2)\n" + >- " fileReader.close();\n" + >- " }\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo(true, true);\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 18)\n" + >- " FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + >- " ^^^^^^^^^^\n" + >- "Potential resource leak: 'fileReader' may not be closed\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// a method uses an AutoCloseable without closing it locally but passing as arg to another method >-public void test056j() { >- Map options = getCompilerOptions(); >- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo() throws IOException {\n" + >- " File file = new File(\"somefile\");\n" + >- " FileReader fileReader = new FileReader(file);\n" + >- " read(fileReader);\n" + >- " }\n" + >- " void read(FileReader reader) { }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 7)\n" + >- " FileReader fileReader = new FileReader(file);\n" + >- " ^^^^^^^^^^\n" + >- "Potential resource leak: 'fileReader' may not be closed\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// a method uses an AutoCloseable without closing it locally but passing as arg to another method >-public void test056jconditional() { >- Map options = getCompilerOptions(); >- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo(boolean b) throws IOException {\n" + >- " File file = new File(\"somefile\");\n" + >- " FileReader fileReader = new FileReader(file);\n" + >- " synchronized (b ? this : new X()) {\n" + >- " new ReadDelegator(fileReader);\n" + >- " }\n" + >- " }\n" + >- " class ReadDelegator { ReadDelegator(FileReader reader) { } }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo(true);\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 7)\n" + >- " FileReader fileReader = new FileReader(file);\n" + >- " ^^^^^^^^^^\n" + >- "Potential resource leak: 'fileReader' may not be closed\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// many locals, some are AutoCloseable. >-// Unfortunately analysis cannot respect how exception exits may affect ra3 and rb3, >-// doing so would create false positives. >-public void test056k() { >- Map options = getCompilerOptions(); >- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING); >- options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo() throws IOException {\n" + >- " int i01, i02, i03, i04, i05, i06, i07, i08, i09,\n" + >- " i11, i12, i13, i14, i15, i16, i17, i18, i19,\n" + >- " i21, i22, i23, i24, i25, i26, i27, i28, i29,\n" + >- " i31, i32, i33, i34, i35, i36, i37, i38, i39,\n" + >- " i41, i42, i43, i44, i45, i46, i47, i48, i49;\n" + >- " File file = new File(\"somefile\");\n" + >- " FileReader ra1 = null, ra2 = null;\n" + >- " try {\n" + >- " ra1 = new FileReader(file);\n" + >- " ra2 = new FileReader(file);\n" + >- " FileReader ra3 = new FileReader(file);\n" + >- " char[] in = new char[50];\n" + >- " ra1.read(in);\n" + >- " ra2.read(in);\n" + >- " ra3.close();\n" + >- " } finally {\n" + >- " ra1.close();\n" + >- " }\n" + >- " int i51, i52, i53, i54, i55, i56, i57, i58, i59, i60;\n" + // beyond this point locals are analyzed using extraBits >- " FileReader rb1 = null, rb2 = null;\n" + >- " try {\n" + >- " rb1 = new FileReader(file);\n" + >- " rb2 = new FileReader(file);\n" + >- " FileReader rb3 = new FileReader(file);\n" + >- " char[] in = new char[50];\n" + >- " rb1.read(in);\n" + >- " rb2.read(in);\n" + >- " rb3.close();\n" + >- " } finally {\n" + >- " rb1.close();\n" + >- " }\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 12)\n" + >- " FileReader ra1 = null, ra2 = null;\n" + >- " ^^^\n" + >- "Resource 'ra1' should be managed by try-with-resource\n" + >- "----------\n" + >- "2. ERROR in X.java (at line 15)\n" + >- " ra2 = new FileReader(file);\n" + >- " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Resource leak: 'ra2' is never closed\n" + >- "----------\n" + >- "3. ERROR in X.java (at line 16)\n" + >- " FileReader ra3 = new FileReader(file);\n" + >- " ^^^\n" + >- "Resource 'ra3' should be managed by try-with-resource\n" + >- "----------\n" + >- "4. ERROR in X.java (at line 25)\n" + >- " FileReader rb1 = null, rb2 = null;\n" + >- " ^^^\n" + >- "Resource 'rb1' should be managed by try-with-resource\n" + >- "----------\n" + >- "5. ERROR in X.java (at line 28)\n" + >- " rb2 = new FileReader(file);\n" + >- " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Resource leak: 'rb2' is never closed\n" + >- "----------\n" + >- "6. ERROR in X.java (at line 29)\n" + >- " FileReader rb3 = new FileReader(file);\n" + >- " ^^^\n" + >- "Resource 'rb3' should be managed by try-with-resource\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// various non-problems >-public void test056l() { >- Map options = getCompilerOptions(); >- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >- options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " X(FileReader r0) {}\n" + // don't complain against argument >- " FileReader getReader() { return null; }\n" + >- " void foo(FileReader r1) throws IOException {\n" + >- " FileReader fileReader = getReader();\n" + >- " if (fileReader == null)\n" + >- " return;\n" + // don't complain, resource is actually null >- " FileReader r3 = getReader();\n" + >- " if (r3 == null)\n" + >- " r3 = new FileReader(new File(\"absent\"));\n" + // don't complain, previous resource is actually null >- " try {\n" + >- " char[] in = new char[50];\n" + >- " fileReader.read(in);\n" + >- " r1.read(in);\n" + >- " } finally {\n" + >- " fileReader.close();\n" + >- " r3.close();\n" + // the effect of this close() call might be spoiled by exception in fileReader.close() above, but we ignore exception exits in the analysis >- " }\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" + >- " new X(r2).foo(new FileReader(new File(\"notthere\")));\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 8)\n" + >- " FileReader fileReader = getReader();\n" + >- " ^^^^^^^^^^\n" + >- "Resource 'fileReader' should be managed by try-with-resource\n" + >- "----------\n" + >- "2. ERROR in X.java (at line 11)\n" + >- " FileReader r3 = getReader();\n" + >- " ^^\n" + >- "Resource 'r3' should be managed by try-with-resource\n" + >- "----------\n" + >- "3. ERROR in X.java (at line 24)\n" + >- " FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" + >- " ^^\n" + >- "Potential resource leak: 'r2' may not be closed\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// nested try with early exit >-public void test056m() { >- Map options = getCompilerOptions(); >- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >- this.runConformTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo() {\n" + >- " File file = new File(\"somefile\");" + >- " try {\n" + >- " FileReader fileReader = new FileReader(file);\n" + >- " try {\n" + >- " char[] in = new char[50];\n" + >- " if (fileReader.read(in)==0)\n" + >- " return;\n" + >- " } finally {\n" + >- " fileReader.close();\n" + >- " }\n" + >- " } catch (IOException e) {\n" + >- " System.out.println(\"caught\");\n" + >- " }\n" + >- " }\n" + >- " public static void main(String[] args) {\n" + >- " new X().foo();\n" + >- " }\n" + >- "}\n" >- }, >- "caught", /*output*/ >- null/*classLibs*/, >- true/*shouldFlush*/, >- null/*vmargs*/, >- options, >- null/*requestor*/); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// nested try should not interfere with earlier analysis. >-public void test056n() { >- Map options = getCompilerOptions(); >- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >- this.runConformTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "import java.io.FileNotFoundException;\n" + >- "public class X {\n" + >- " void foo(File someFile, char[] buf) throws IOException {\n" + >- " FileReader fr1 = new FileReader(someFile);\n" + >- " try {\n" + >- " fr1.read(buf);\n" + >- " } finally {\n" + >- " fr1.close();\n" + >- " }\n" + >- " try {\n" + >- " FileReader fr3 = new FileReader(someFile);\n" + >- " try {\n" + >- " } finally {\n" + >- " fr3.close();\n" + >- " }\n" + >- " } catch (IOException e) {\n" + >- " }\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " try {\n" + >- " new X().foo(new File(\"missing\"), new char[100]);\n" + >- " } catch (FileNotFoundException e) {\n" + >- " System.out.println(\"caught\");\n" + >- " }\n" + >- " }\n" + >- "}\n" >- }, >- "caught", /*output*/ >- null/*classLibs*/, >- true/*shouldFlush*/, >- null/*vmargs*/, >- options, >- null/*requestor*/); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// if close is guarded by null check this should still be recognized as definitely closed >-public void test056o() { >- Map options = getCompilerOptions(); >- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); >- this.runConformTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "import java.io.FileNotFoundException;\n" + >- "public class X {\n" + >- " void foo(File someFile, char[] buf) throws IOException {\n" + >- " FileReader fr1 = null;\n" + >- " try {\n" + >- " fr1 = new FileReader(someFile);" + >- " fr1.read(buf);\n" + >- " } finally {\n" + >- " if (fr1 != null)\n" + >- " try {\n" + >- " fr1.close();\n" + >- " } catch (IOException e) { /*do nothing*/ }\n" + >- " }\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " try {\n" + >- " new X().foo(new File(\"missing\"), new char[100]);\n" + >- " } catch (FileNotFoundException e) {\n" + >- " System.out.println(\"caught\");\n" + >- " }\n" + >- " }\n" + >- "}\n" >- }, >- "caught", /*output*/ >- null/*classLibs*/, >- true/*shouldFlush*/, >- null/*vmargs*/, >- options, >- null/*requestor*/); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// a method uses an AutoCloseable without ever closing it, type from a type variable >-public void test056p() { >- Map options = getCompilerOptions(); >- options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); >- options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.Reader;\n" + >- "import java.io.IOException;\n" + >- "public abstract class X <T extends Reader> {\n" + >- " void foo() throws IOException {\n" + >- " File file = new File(\"somefile\");\n" + >- " T fileReader = newReader(file);\n" + >- " char[] in = new char[50];\n" + >- " fileReader.read(in);\n" + >- " }\n" + >- " abstract T newReader(File file) throws IOException;\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X<FileReader>() {\n" + >- " FileReader newReader(File f) throws IOException { return new FileReader(f); }\n" + >- " }.foo();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 8)\n" + >- " T fileReader = newReader(file);\n" + >- " ^^^^^^^^^^\n" + >- "Resource leak: 'fileReader' is never closed\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// closed in dead code >-public void test056q() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo() throws IOException {\n" + >- " File file = new File(\"somefile\");\n" + >- " FileReader fileReader = new FileReader(file);\n" + >- " char[] in = new char[50];\n" + >- " fileReader.read(in);\n" + >- " if (2*2 == 4)\n" + >- " return;\n" + >- " fileReader.close();\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 7)\n" + >- " FileReader fileReader = new FileReader(file);\n" + >- " ^^^^^^^^^^\n" + >- "Resource leak: 'fileReader' is never closed\n" + >- "----------\n" + >- "2. WARNING in X.java (at line 10)\n" + >- " if (2*2 == 4)\n" + >- " ^^^^^^^^\n" + >- "Comparing identical expressions\n" + >- "----------\n" + >- "3. WARNING in X.java (at line 12)\n" + >- " fileReader.close();\n" + >- " ^^^^^^^^^^^^^^^^^^\n" + >- "Dead code\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// closed in dead code >-public void test056r() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo() throws IOException {\n" + >- " File file = new File(\"somefile\");\n" + >- " FileReader fr = new FileReader(file);\n" + >- " Object b = null;\n" + >- " fr.close();\n" + >- " if (b != null) {\n" + >- " fr = new FileReader(file);\n" + >- " return;\n" + >- " } else {\n" + >- " System.out.print(42);\n" + >- " }\n" + >- " return; // Should not complain about fr\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 10)\n" + >- " if (b != null) {\n" + >- " fr = new FileReader(file);\n" + >- " return;\n" + >- " } else {\n" + >- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Dead code\n" + >- "----------\n" + >- "2. WARNING in X.java (at line 13)\n" + >- " } else {\n" + >- " System.out.print(42);\n" + >- " }\n" + >- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Statement unnecessarily nested within else clause. The corresponding then clause does not complete normally\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// resource inside t-w-r is re-assigned, shouldn't even record an errorLocation >-public void test056s() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.File;\n" + >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo() throws IOException {\n" + >- " File file = new File(\"somefile\");\n" + >- " try (FileReader fileReader = new FileReader(file);) {\n" + >- " char[] in = new char[50];\n" + >- " fileReader.read(in);\n" + >- " fileReader = new FileReader(file); // debug here\n" + >- " fileReader.read(in);\n" + >- " }\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 10)\n" + >- " fileReader = new FileReader(file); // debug here\n" + >- " ^^^^^^^^^^\n" + >- "The resource fileReader of a try-with-resources statement cannot be assigned\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// resource is closed, dead code follows >-public void test056t() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "import java.io.IOException;\n" + >- "public class X {\n" + >- " void foo31() throws IOException {\n" + >- " FileReader reader = new FileReader(\"file\"); //warning\n" + >- " if (reader != null) {\n" + >- " reader.close();\n" + >- " } else {\n" + >- " // nop\n" + >- " }\n" + >- " }\n" + >- " public static void main(String[] args) throws IOException {\n" + >- " new X().foo31();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 8)\n" + >- " } else {\n" + >- " // nop\n" + >- " }\n" + >- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Dead code\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// resource is reassigned within t-w-r with different resource >-// was initially broken due to https://bugs.eclipse.org/358827 >-public void test056u() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " void foo() throws Exception {\n" + >- " FileReader reader1 = new FileReader(\"file1\");\n" + >- " FileReader reader2 = new FileReader(\"file2\");\n" + >- " reader2 = reader1;// this disconnects reader 2\n" + >- " try (FileReader reader3 = new FileReader(\"file3\")) {\n" + >- " int ch;\n" + >- " while ((ch = reader2.read()) != -1) {\n" + >- " System.out.println(ch);\n" + >- " reader1.read();\n" + >- " }\n" + >- " reader2 = reader1; // warning 1 regarding original reader1\n" + // this warning was missing >- " reader2 = reader1; // warning 2 regarding original reader1\n" + >- " } finally {\n" + >- " if (reader2 != null) {\n" + >- " reader2.close();\n" + >- " } else {\n" + >- " System.out.println();\n" + >- " }\n" + >- " }\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 5)\n" + >- " FileReader reader2 = new FileReader(\"file2\");\n" + >- " ^^^^^^^\n" + >- "Resource leak: 'reader2' is never closed\n" + >- "----------\n" + >- "2. ERROR in X.java (at line 13)\n" + >- " reader2 = reader1; // warning 1 regarding original reader1\n" + >- " ^^^^^^^^^^^^^^^^^\n" + >- "Resource leak: 'reader1' is not closed at this location\n" + >- "----------\n" + >- "3. ERROR in X.java (at line 14)\n" + >- " reader2 = reader1; // warning 2 regarding original reader1\n" + >- " ^^^^^^^^^^^^^^^^^\n" + >- "Resource leak: 'reader1' is not closed at this location\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// scope-related pbs reported in https://bugs.eclipse.org/349326#c70 and https://bugs.eclipse.org/349326#c82 >-public void test056v() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " boolean foo1() throws Exception {\n" + >- " FileReader reader = new FileReader(\"file\");\n" + >- " try {\n" + >- " int ch;\n" + >- " while ((ch = reader.read()) != -1) {\n" + >- " System.out.println(ch);\n" + >- " reader.read();\n" + >- " }\n" + >- " if (ch > 10) {\n" + >- " return true;\n" + >- " }\n" + >- " return false;\n" + // return while resource from enclosing scope remains unclosed >- " } finally {\n" + >- " }\n" + >- " }\n" + >- " void foo111() throws Exception {\n" + >- " FileReader reader111 = new FileReader(\"file2\");\n" + >- " try {\n" + >- " int ch;\n" + >- " while ((ch = reader111.read()) != -1) {\n" + >- " System.out.println(ch);\n" + >- " reader111.read();\n" + >- " }\n" + >- " return;\n" + // this shouldn't spoil the warning "should be managed with t-w-r" >- " } finally {\n" + >- " if (reader111 != null) {\n" + >- " reader111.close();\n" + >- " }\n" + >- " }\n" + >- " }\n" + >- " void foo2() throws Exception {\n" + >- " FileReader reader2 = new FileReader(\"file\");\n" + >- " try {\n" + >- " int ch;\n" + >- " while ((ch = reader2.read()) != -1) {\n" + >- " System.out.println(ch);\n" + >- " reader2.read();\n" + >- " }\n" + >- " if (ch > 10) {\n" + >- " return;\n" + // potential leak >- " }\n" + >- " } finally {\n" + >- " }\n" + >- " reader2.close();\n" + // due to this close we don't say "never closed" >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 4)\n" + >- " FileReader reader = new FileReader(\"file\");\n" + >- " ^^^^^^\n" + >- "Resource leak: 'reader' is never closed\n" + >- "----------\n" + >- "2. WARNING in X.java (at line 19)\n" + >- " FileReader reader111 = new FileReader(\"file2\");\n" + >- " ^^^^^^^^^\n" + >- "Resource 'reader111' should be managed by try-with-resource\n" + >- "----------\n" + >- "3. ERROR in X.java (at line 42)\n" + >- " return;\n" + >- " ^^^^^^^\n" + >- "Resource leak: 'reader2' is not closed at this location\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// end of method is dead end, but before we have both a close() and an early return >-public void test056w() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " boolean foo1() throws Exception {\n" + >- " FileReader reader = new FileReader(\"file\");\n" + >- " try {\n" + >- " int ch;\n" + >- " while ((ch = reader.read()) != -1) {\n" + >- " System.out.println(ch);\n" + >- " reader.read();\n" + >- " }\n" + >- " if (ch > 10) {\n" + >- " reader.close();\n" + >- " return true;\n" + >- " }\n" + >- " return false;\n" + >- " } finally {\n" + >- " }\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 15)\n" + >- " return false;\n" + >- " ^^^^^^^^^^^^^\n" + >- "Resource leak: 'reader' is not closed at this location\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// different early exits, if no close seen report as definitely unclosed >-public void test056x() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " void foo31(boolean b) throws Exception {\n" + >- " FileReader reader = new FileReader(\"file\");\n" + >- " if (b) {\n" + >- " reader.close();\n" + >- " } else {\n" + >- " return; // warning\n" + >- " }\n" + >- " }\n" + >- " void foo32(boolean b) throws Exception {\n" + >- " FileReader reader = new FileReader(\"file\"); // warn here\n" + >- " return;\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 8)\n" + >- " return; // warning\n" + >- " ^^^^^^^\n" + >- "Resource leak: 'reader' is not closed at this location\n" + >- "----------\n" + >- "2. ERROR in X.java (at line 12)\n" + >- " FileReader reader = new FileReader(\"file\"); // warn here\n" + >- " ^^^^^^\n" + >- "Resource leak: 'reader' is never closed\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// nested method passes the resource to outside code >-public void test056y() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " void foo31(boolean b) throws Exception {\n" + >- " final FileReader reader31 = new FileReader(\"file\");\n" + >- " new Runnable() {\n" + >- " public void run() {\n" + >- " foo18(reader31);\n" + >- " }\n" + >- " }.run();\n" + >- " }\n" + >- " void foo18(FileReader r18) {\n" + >- " // could theoretically close r18;\n" + >- " }\n" + >- " abstract class ResourceProvider {\n" + >- " abstract FileReader provide();" + >- " }\n" + >- " ResourceProvider provider;" + >- " void foo23() throws Exception {\n" + >- " final FileReader reader23 = new FileReader(\"file\");\n" + >- " provider = new ResourceProvider() {\n" + >- " public FileReader provide() {\n" + >- " return reader23;\n" + >- " }\n" + >- " };\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. WARNING in X.java (at line 4)\n" + >- " final FileReader reader31 = new FileReader(\"file\");\n" + >- " ^^^^^^^^\n" + >- "Potential resource leak: 'reader31' may not be closed\n" + >- "----------\n" + >- "2. WARNING in X.java (at line 17)\n" + >- " final FileReader reader23 = new FileReader(\"file\");\n" + >- " ^^^^^^^^\n" + >- "Potential resource leak: 'reader23' may not be closed\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// resource assigned to second local and is (potentially) closed on the latter >-public void test056z() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " void foo17() throws Exception {\n" + >- " FileReader reader17 = new FileReader(\"file\");\n" + >- " final FileReader readerCopy = reader17;\n" + >- " readerCopy.close();\n" + >- " }\n" + >- " void foo17a() throws Exception {\n" + >- " FileReader reader17a = new FileReader(\"file\");\n" + >- " FileReader readerCopya;" + >- " readerCopya = reader17a;\n" + >- " bar(readerCopya);\n" + // potentially closes >- " }\n" + >- " void bar(FileReader r) {}\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 9)\n" + >- " FileReader reader17a = new FileReader(\"file\");\n" + >- " ^^^^^^^^^\n" + >- "Potential resource leak: 'reader17a' may not be closed\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// multiple early exists from nested scopes (always closed) >-public void test056zz() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " void foo16() throws Exception {\n" + >- " FileReader reader16 = new FileReader(\"file\");\n" + >- " try {\n" + >- " reader16.close();\n " + >- " return;\n" + >- " } catch (RuntimeException re) {\n" + >- " return;\n" + >- " } catch (Error e) {\n" + >- " return;\n" + >- " } finally {\n" + >- " reader16.close();\n " + >- " }\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 4)\n" + >- " FileReader reader16 = new FileReader(\"file\");\n" + >- " ^^^^^^^^\n" + >- "Resource 'reader16' should be managed by try-with-resource\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 349326 - [1.7] new warning for missing try-with-resources >-// multiple early exists from nested scopes (never closed) >-public void test056zzz() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " void foo16() throws Exception {\n" + >- " FileReader reader16 = new FileReader(\"file\");\n" + >- " try {\n" + >- " return;\n" + >- " } catch (RuntimeException re) {\n" + >- " return;\n" + >- " } catch (Error e) {\n" + >- " return;\n" + >- " } finally {\n" + >- " System.out.println();\n " + >- " }\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 4)\n" + >- " FileReader reader16 = new FileReader(\"file\");\n" + >- " ^^^^^^^^\n" + >- "Resource leak: 'reader16' is never closed\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points >-// explicit throw is a true method exit here >-public void test056throw1() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " void foo2(boolean a, boolean b, boolean c) throws Exception {\n" + >- " FileReader reader = new FileReader(\"file\");\n" + >- " if(a)\n" + >- " throw new Exception(); //warning 1\n" + >- " else if (b)\n" + >- " reader.close();\n" + >- " else if(c)\n" + >- " throw new Exception(); //warning 2\n" + >- " reader.close();\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 6)\n" + >- " throw new Exception(); //warning 1\n" + >- " ^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Resource leak: 'reader' is not closed at this location\n" + >- "----------\n" + >- "2. ERROR in X.java (at line 10)\n" + >- " throw new Exception(); //warning 2\n" + >- " ^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Resource leak: 'reader' is not closed at this location\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points >-// close() within finally provides protection for throw >-public void test056throw2() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " void foo1() throws Exception {\n" + >- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >- " try {\n" + >- " reader.read();\n" + >- " return;\n" + >- " } catch (Exception e) {\n" + >- " throw new Exception();\n" + >- " } finally {\n" + >- " reader.close();\n" + >- " }\n" + >- " }\n" + >- "\n" + >- " void foo2() throws Exception {\n" + >- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >- " try {\n" + >- " reader.read();\n" + >- " throw new Exception(); // should not warn here\n" + >- " } catch (Exception e) {\n" + >- " throw new Exception();\n" + >- " } finally {\n" + >- " reader.close();\n" + >- " }\n" + >- " }\n" + >- "\n" + >- " void foo3() throws Exception {\n" + >- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >- " try {\n" + >- " reader.read();\n" + >- " throw new Exception();\n" + >- " } finally {\n" + >- " reader.close();\n" + >- " }\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 4)\n" + >- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >- " ^^^^^^\n" + >- "Resource 'reader' should be managed by try-with-resource\n" + >- "----------\n" + >- "2. ERROR in X.java (at line 16)\n" + >- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >- " ^^^^^^\n" + >- "Resource 'reader' should be managed by try-with-resource\n" + >- "----------\n" + >- "3. ERROR in X.java (at line 28)\n" + >- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >- " ^^^^^^\n" + >- "Resource 'reader' should be managed by try-with-resource\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points >-// close() nested within finally provides protection for throw >-public void test056throw3() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " void foo2x() throws Exception {\n" + >- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >- " try {\n" + >- " reader.read();\n" + >- " throw new Exception(); // should not warn here\n" + >- " } catch (Exception e) {\n" + >- " throw new Exception();\n" + >- " } finally {\n" + >- " if (reader != null)\n" + >- " try {\n" + >- " reader.close();\n" + >- " } catch (java.io.IOException io) {}\n" + >- " }\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 4)\n" + >- " FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + >- " ^^^^^^\n" + >- "Resource 'reader' should be managed by try-with-resource\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points >-// additional boolean should shed doubt on whether we reach the close() call >-public void test056throw4() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " void foo2x(boolean b) throws Exception {\n" + >- " FileReader reader = new FileReader(\"file\");\n" + >- " try {\n" + >- " reader.read();\n" + >- " throw new Exception(); // should warn here\n" + >- " } catch (Exception e) {\n" + >- " throw new Exception(); // should warn here\n" + >- " } finally {\n" + >- " if (reader != null && b)\n" + // this condition is too strong to protect reader >- " try {\n" + >- " reader.close();\n" + >- " } catch (java.io.IOException io) {}\n" + >- " }\n" + >- " }\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 7)\n" + >- " throw new Exception(); // should warn here\n" + >- " ^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Potential resource leak: 'reader' may not be closed at this location\n" + >- "----------\n" + >- "2. ERROR in X.java (at line 9)\n" + >- " throw new Exception(); // should warn here\n" + >- " ^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Potential resource leak: 'reader' may not be closed at this location\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points >-// similar to test056throw3() but indirectly calling close(), so doubts remain. >-public void test056throw5() { >- Map options = getCompilerOptions(); >- options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR); >- options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR); >- this.runNegativeTest( >- new String[] { >- "X.java", >- "import java.io.FileReader;\n" + >- "public class X {\n" + >- " void foo2x() throws Exception {\n" + >- " FileReader reader = new FileReader(\"file\");\n" + >- " try {\n" + >- " reader.read();\n" + >- " throw new Exception(); // should warn 'may not' here\n" + >- " } catch (Exception e) {\n" + >- " throw new Exception(); // should warn 'may not' here\n" + >- " } finally {\n" + >- " doClose(reader);\n" + >- " }\n" + >- " }\n" + >- " void doClose(FileReader r) { try { r.close(); } catch (java.io.IOException ex) {}}\n" + >- "}\n" >- }, >- "----------\n" + >- "1. ERROR in X.java (at line 7)\n" + >- " throw new Exception(); // should warn \'may not\' here\n" + >- " ^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Potential resource leak: 'reader' may not be closed at this location\n" + >- "----------\n" + >- "2. ERROR in X.java (at line 9)\n" + >- " throw new Exception(); // should warn \'may not\' here\n" + >- " ^^^^^^^^^^^^^^^^^^^^^^\n" + >- "Potential resource leak: 'reader' may not be closed at this location\n" + >- "----------\n", >- null, >- true, >- options); >-} >-// https://bugs.eclipse.org/bugs/show_bug.cgi?id=361053 >-public void test057() { >- this.runConformTest( >- new String[] { >- "X.java", >- "public class X implements AutoCloseable {\n" + >- " @Override\n" + >- " public void close() throws Exception {\n" + >- " throw new Exception();\n" + >- " }\n" + >- " public static void main(String[] args) {\n" + >- " final boolean foo;\n" + >- " try (X a = new X(); X b = new X()) {\n" + >- " foo = true;\n" + >- " } catch (final Exception exception) {\n" + >- " return;\n" + >- " }\n" + >- " }\n" + >- "}\n" >- }, ""); >-} >-// https://bugs.eclipse.org/bugs/show_bug.cgi?id=364008 >-public void test058() { >- this.runConformTest( >- new String[] { >- "X.java", >- "import java.io.ByteArrayOutputStream;\n" + >- "import java.io.FileOutputStream;\n" + >- "import java.io.IOException;\n" + >- "\n" + >- "public class X {\n" + >- "\n" + >- " public static void main(final String[] args) throws IOException {\n" + >- " byte[] data;\n" + >- " try (final ByteArrayOutputStream os = new ByteArrayOutputStream();\n" + >- " final FileOutputStream out = new FileOutputStream(\"test.dat\")) {\n" + >- " data = os.toByteArray();\n" + >- " }\n" + >- " }\n" + >- "}\n" >- }, ""); >-} >-// https://bugs.eclipse.org/bugs/show_bug.cgi?id=367566 - In try-with-resources statement close() method of resource is not called >-public void test059() { >- this.runConformTest( >- new String[] { >- "X.java", >- "import java.io.IOException;\n" + >- "\n" + >- "public class X implements java.lang.AutoCloseable {\n" + >- " static boolean isOpen = true;\n" + >- " public static void main(final String[] args) throws IOException {\n" + >- " foo();\n" + >- " System.out.println(isOpen);\n" + >- " }\n" + >- " static boolean foo() {\n" + >- " try (final X x = new X()) {\n" + >- " return x.num() >= 1;\n" + >- " }\n" + >- " }\n" + >- " int num() { return 2; }\n" + >- " public void close() {\n" + >- " isOpen = false;\n" + >- " }\n" + >- "}\n" >- }, >- "false"); >-} >- >-// https://bugs.eclipse.org/bugs/show_bug.cgi?id=367566 - In try-with-resources statement close() method of resource is not called >-public void test060() { >- this.runConformTest( >- new String[] { >- "X.java", >- "public class X implements AutoCloseable {\n" + >- " static int num = 10 ;\n" + >- " public static void main(String [] args) throws Exception { \n" + >- " System.out.println(foo(1));\n" + >- " System.out.println(foo(2));\n" + >- " System.out.println(foo(3));\n" + >- " }\n" + >- " private static boolean foo(int where) throws Exception {\n" + >- " final boolean getOut = true;\n" + >- " System.out.println(\"Main\");\n" + >- " try (X x1 = new X(); X x2 = new X()) {\n" + >- " if (where == 1) {\n" + >- " return where == 1;\n" + >- " }\n" + >- " System.out.println(\"Outer Try\");\n" + >- " while (true) {\n" + >- " try (Y y1 = new Y(); Y y2 = new Y()) { \n" + >- " if (where == 2) {\n" + >- " return where == 2;\n" + >- " } \n" + >- " System.out.println(\"Middle Try\");\n" + >- " try (Z z1 = new Z(); Z z2 = new Z()) {\n" + >- " System.out.println(\"Inner Try\");\n" + >- " if (getOut) \n" + >- " return num >= 10;\n" + >- " else\n" + >- " break; \n" + >- " }\n" + >- " }\n" + >- " }\n" + >- " System.out.println(\"Out of while\");\n" + >- " }\n" + >- " return false;\n" + >- " }\n" + >- " public X() {\n" + >- " System.out.println(\"X::X\");\n" + >- " }\n" + >- " @Override\n" + >- " public void close() throws Exception {\n" + >- " System.out.println(\"X::~X\");\n" + >- " }\n" + >- "}\n" + >- "class Y implements AutoCloseable {\n" + >- " public Y() {\n" + >- " System.out.println(\"Y::Y\");\n" + >- " }\n" + >- " @Override\n" + >- " public void close() throws Exception {\n" + >- " System.out.println(\"Y::~Y\");\n" + >- " }\n" + >- "}\n" + >- "class Z implements AutoCloseable {\n" + >- " public Z() {\n" + >- " System.out.println(\"Z::Z\");\n" + >- " }\n" + >- " @Override\n" + >- " public void close() throws Exception {\n" + >- " System.out.println(\"Z::~Z\");\n" + >- " }\n" + >- "}\n" >- }, >- "Main\n" + >- "X::X\n" + >- "X::X\n" + >- "X::~X\n" + >- "X::~X\n" + >- "true\n" + >- "Main\n" + >- "X::X\n" + >- "X::X\n" + >- "Outer Try\n" + >- "Y::Y\n" + >- "Y::Y\n" + >- "Y::~Y\n" + >- "Y::~Y\n" + >- "X::~X\n" + >- "X::~X\n" + >- "true\n" + >- "Main\n" + >- "X::X\n" + >- "X::X\n" + >- "Outer Try\n" + >- "Y::Y\n" + >- "Y::Y\n" + >- "Middle Try\n" + >- "Z::Z\n" + >- "Z::Z\n" + >- "Inner Try\n" + >- "Z::~Z\n" + >- "Z::~Z\n" + >- "Y::~Y\n" + >- "Y::~Y\n" + >- "X::~X\n" + >- "X::~X\n" + >- "true"); >-} >- > public static Class testClass() { > return TryWithResourcesStatementTest.class; > } >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java >index e811ea9..fd64fd9 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 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2011 IBM Corporation and others. >+ * Copyright (c) 2000, 2012 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -12,6 +12,7 @@ > * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE > * bug 349326 - [1.7] new warning for missing try-with-resources > * bug 186342 - [compiler][null] Using annotations for null checking >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -37,25 +38,35 @@ public class AllocationExpression extends Expression implements InvocationSite { > protected TypeBinding typeExpected; // for <> inference > public boolean inferredReturnType; > >+ public FakedTrackingVariable closeTracker; // when allocation a Closeable store a pre-liminary tracking variable here >+ > public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { > // check captured variables are initialized in current context (26134) > checkCapturedLocalInitializationIfNecessary((ReferenceBinding)this.binding.declaringClass.erasure(), currentScope, flowInfo); > > // process arguments > if (this.arguments != null) { >+ boolean hasResourceWrapperType = this.resolvedType instanceof ReferenceBinding >+ && ((ReferenceBinding)this.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable); > 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) > .unconditionalInits(); >+ // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.) >+ if (!hasResourceWrapperType) { // allocation of wrapped closeables is analyzed specially >+ flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, false); >+ } > if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) { > this.arguments[i].checkNPE(currentScope, flowContext, flowInfo); > } > } > analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments); > } >+ >+ if (FakedTrackingVariable.isAnyCloseable(this.resolvedType)) >+ FakedTrackingVariable.analyseCloseableAllocation(currentScope, flowInfo, this); >+ > // record some dependency information for exception types > ReferenceBinding[] thrownExceptions; > if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) { >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 970fc24..ea1af7b 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 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2011 IBM Corporation and others. >+ * Copyright (c) 2000, 2012 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -14,6 +14,7 @@ > * bug 335093 - [compiler][null] minimal hook for future null annotation support > * bug 349326 - [1.7] new warning for missing try-with-resources > * bug 186342 - [compiler][null] Using annotations for null checking >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -46,19 +47,27 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) { > this.expression.checkNPE(currentScope, flowContext, flowInfo); > } >+ >+ FlowInfo preInitInfo = null; >+ boolean shouldAnalyseResource = local != null >+ && flowInfo.reachMode() == FlowInfo.REACHABLE >+ && (FakedTrackingVariable.isAnyCloseable(this.expression.resolvedType) >+ || this.expression.resolvedType == TypeBinding.NULL); >+ if (shouldAnalyseResource) { >+ preInitInfo = flowInfo.unconditionalCopy(); >+ // analysis of resource leaks needs additional context while analyzing the RHS: >+ FakedTrackingVariable.preConnectTrackerAcrossAssignment(this, local, this.expression); >+ } >+ > 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); >- } >+ >+ if (shouldAnalyseResource) >+ FakedTrackingVariable.handleResourceAssignment(currentScope, preInitInfo, flowInfo, this, this.expression, local); >+ else >+ FakedTrackingVariable.cleanUpAfterAssignment(currentScope, this.lhs.bits, this.expression); >+ > 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/FakedTrackingVariable.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java >index ee13047..5ece3b7 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2011 GK Software AG and others. >+ * Copyright (c) 2011, 2012 GK Software AG and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -14,8 +14,8 @@ import java.util.HashMap; > import java.util.Iterator; > import java.util.Map; > import java.util.Map.Entry; >+import java.util.Set; > >-import org.eclipse.jdt.core.compiler.CharOperation; > import org.eclipse.jdt.internal.compiler.codegen.CodeStream; > import org.eclipse.jdt.internal.compiler.flow.FlowContext; > import org.eclipse.jdt.internal.compiler.flow.FlowInfo; >@@ -42,26 +42,42 @@ public class FakedTrackingVariable extends LocalDeclaration { > > // a call to close() was seen at least on one path: > private static final int CLOSE_SEEN = 1; >- // the resource was passed to outside code (arg in method/ctor call or as a return value from this method): >- private static final int PASSED_TO_OUTSIDE = 2; >+ // the resource is shared with outside code either by >+ // - passing as an arg in a method call or >+ // - obtaining this from a method call or array reference >+ // Interpret that we may or may not be responsible for closing >+ private static final int SHARED_WITH_OUTSIDE = 2; >+ // the resource is likely owned by outside code (owner has responsibility to close): >+ // - obtained as argument of the current method, or via a field read >+ // - returned as the result of this method >+ private static final int OWNED_BY_OUTSIDE = 4; > // If close() is invoked from a nested method (inside a local type) report remaining problems only as potential: >- private static final int CLOSED_IN_NESTED_METHOD = 4; >- // a location independent issue has been reported already against this resource: >- private static final int REPORTED = 8; >- >+ private static final int CLOSED_IN_NESTED_METHOD = 8; >+ // explicit closing has been reported already against this resource: >+ private static final int REPORTED_EXPLICIT_CLOSE = 16; >+ // a location independent potential problem has been reported against this resource: >+ private static final int REPORTED_POTENTIAL_LEAK = 32; >+ // a location independent definitive problem has been reported against this resource: >+ private static final int REPORTED_DEFINITIVE_LEAK = 64; >+ > /** >- * Bitset of {@link #CLOSE_SEEN}, {@link #PASSED_TO_OUTSIDE}, {@link #CLOSED_IN_NESTED_METHOD} and {@link #REPORTED}. >+ * Bitset of {@link #CLOSE_SEEN}, {@link #SHARED_WITH_OUTSIDE}, {@link #OWNED_BY_OUTSIDE}, {@link #CLOSED_IN_NESTED_METHOD}, {@link #REPORTED_EXPLICIT_CLOSE}, {@link #REPORTED_POTENTIAL_LEAK} and {@link #REPORTED_DEFINITIVE_LEAK}. > */ > private int globalClosingState = 0; > >- MethodScope methodScope; // designates the method declaring this variable >- >- public LocalVariableBinding originalBinding; // the real local being tracked >+ public LocalVariableBinding originalBinding; // the real local being tracked, can be null for preliminary track vars for allocation expressions > >- HashMap recordedLocations; // initially null, ASTNode -> Integer >+ public FakedTrackingVariable innerTracker; // chained tracking variable of a chained (wrapped) resource >+ public FakedTrackingVariable outerTracker; // inverse of 'innerTracker' >+ >+ MethodScope methodScope; // designates the method declaring this variable >+ >+ private HashMap recordedLocations; // initially null, ASTNode -> Integer > >+ // temporary storage while analyzing "res = new Res();": >+ private ASTNode currentAssignment; // temporarily store the assignment as the location for error reporting > >- public FakedTrackingVariable(LocalVariableBinding original, Statement location) { >+ public FakedTrackingVariable(LocalVariableBinding original, ASTNode location) { > super(original.name, location.sourceStart, location.sourceEnd); > this.type = new SingleTypeReference( > TypeConstants.OBJECT, >@@ -70,6 +86,17 @@ public class FakedTrackingVariable extends LocalDeclaration { > this.originalBinding = original; > resolve(original.declaringScope); > } >+ >+ /* Create an unassigned tracking variable while analyzing an allocation expression: */ >+ private FakedTrackingVariable(BlockScope scope, ASTNode location) { >+ super("<unassigned Closeable value>".toCharArray(), location.sourceStart, location.sourceEnd); //$NON-NLS-1$ >+ this.type = new SingleTypeReference( >+ TypeConstants.OBJECT, >+ ((long)this.sourceStart <<32)+this.sourceEnd); >+ this.methodScope = scope.methodScope(); >+ this.originalBinding = null; >+ resolve(scope); >+ } > > public void generateCode(BlockScope currentScope, CodeStream codeStream) > { /* NOP - this variable is completely dummy, ie. for analysis only. */ } >@@ -81,6 +108,7 @@ public class FakedTrackingVariable extends LocalDeclaration { > scope.getJavaLangObject(), // dummy, just needs to be a reference type > 0, > false); >+ this.binding.declaringScope = scope; > this.binding.setConstant(Constant.NotAConstant); > this.binding.useFlag = LocalVariableBinding.USED; > // use a free slot without assigning it: >@@ -88,86 +116,435 @@ public class FakedTrackingVariable extends LocalDeclaration { > } > > /** >- * If expression resolves to a local variable binding of type AutoCloseable, >- * answer the variable that tracks closing of that local, creating it if needed. >+ * If expression resolves to a value of type AutoCloseable answer the variable that tracks closing of that local. >+ * Covers two cases: >+ * <ul> >+ * <li>value is a local variable reference, create tracking variable it if needed. >+ * <li>value is an allocation expression, return a preliminary tracking variable if set. >+ * </ul> > * @param expression > * @return a new {@link FakedTrackingVariable} or null. > */ > public static FakedTrackingVariable getCloseTrackingVariable(Expression expression) { >+ while (true) { >+ if (expression instanceof CastExpression) >+ expression = ((CastExpression) expression).expression; >+ else if (expression instanceof Assignment) >+ expression = ((Assignment) expression).expression; >+ else >+ break; >+ } > if (expression instanceof SingleNameReference) { > SingleNameReference name = (SingleNameReference) expression; > if (name.binding instanceof LocalVariableBinding) { > LocalVariableBinding local = (LocalVariableBinding)name.binding; > if (local.closeTracker != null) > return local.closeTracker; >- if (local.isParameter() || !isAutoCloseable(expression.resolvedType)) >+ if (!isAnyCloseable(expression.resolvedType)) > return null; > // tracking var doesn't yet exist. This happens in finally block > // which is analyzed before the corresponding try block > Statement location = local.declaration; >- return local.closeTracker = new FakedTrackingVariable(local, location); >+ local.closeTracker = new FakedTrackingVariable(local, location); >+ if (local.isParameter()) { >+ local.closeTracker.globalClosingState |= OWNED_BY_OUTSIDE; >+ // status of this tracker is now UNKNOWN >+ } >+ return local.closeTracker; > } >- } >+ } else if (expression instanceof AllocationExpression) { >+ // return any preliminary tracking variable from analyseCloseableAllocation >+ return ((AllocationExpression) expression).closeTracker; >+ } > return null; > } > >- /** if 'invocationSite' is a call to close() that has a registered tracking variable, answer that variable's binding. */ >- public static LocalVariableBinding getTrackerForCloseCall(ASTNode invocationSite) { >- if (invocationSite instanceof MessageSend) { >- MessageSend send = (MessageSend) invocationSite; >- if (CharOperation.equals(TypeConstants.CLOSE, send.selector) && send.receiver instanceof SingleNameReference) { >- Binding receiverBinding = ((SingleNameReference)send.receiver).binding; >- if (receiverBinding instanceof LocalVariableBinding) { >- FakedTrackingVariable trackingVariable = ((LocalVariableBinding)receiverBinding).closeTracker; >- if (trackingVariable != null) >- return trackingVariable.binding; >+ /** >+ * Before analyzing an assignment of this shape: <code>singleName = new Allocation()</code> >+ * connect any tracking variable of the LHS with the allocation on the RHS. >+ * Also the assignment is temporarily stored in the tracking variable in case we need to >+ * report errors because the assignment leaves the old LHS value unclosed. >+ * In this case the assignment should be used as the error location. >+ * >+ * @param location the assignment/local declaration being analyzed >+ * @param local the local variable being assigned to >+ * @param rhs the rhs of the assignment resp. the initialization of the local variable declaration. >+ * <strong>Precondition:</strong> client has already checked that the resolved type of this expression is either a closeable type or NULL. >+ */ >+ public static void preConnectTrackerAcrossAssignment(ASTNode location, LocalVariableBinding local, Expression rhs) { >+ FakedTrackingVariable closeTracker = null; >+ if (rhs instanceof AllocationExpression) { >+ closeTracker = local.closeTracker; >+ if (closeTracker == null) { >+ if (rhs.resolvedType != TypeBinding.NULL) { // not NULL means valid closeable as per method precondition >+ closeTracker = new FakedTrackingVariable(local, location); >+ if (local.isParameter()) { >+ closeTracker.globalClosingState |= OWNED_BY_OUTSIDE; >+ } >+ } >+ } >+ if (closeTracker != null) { >+ closeTracker.currentAssignment = location; >+ ((AllocationExpression)rhs).closeTracker = closeTracker; >+ } >+ } >+ } >+ >+ /** >+ * Compute/assign a tracking variable for a freshly allocated closeable value, using information from our white lists. >+ * See Bug 358903 - Filter practically unimportant resource leak warnings >+ */ >+ public static void analyseCloseableAllocation(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation) { >+ // client has checked that the resolvedType is an AutoCloseable, hence the following cast is safe: >+ if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitResourceFreeCloseable)) { >+ // remove unnecessary attempts (closeable is not relevant) >+ if (allocation.closeTracker != null) { >+ scope.removeTrackingVar(allocation.closeTracker); >+ allocation.closeTracker = null; >+ } >+ } else if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable)) { >+ boolean isWrapper = true; >+ if (allocation.arguments != null && allocation.arguments.length > 0) { >+ // find the wrapped resource represented by its tracking var: >+ FakedTrackingVariable innerTracker = findCloseTracker(scope, flowInfo, allocation, allocation.arguments[0]); >+ if (innerTracker != null) { >+ if (innerTracker == allocation.closeTracker) >+ return; // self wrap (res = new Res(res)) -> neither change (here) nor remove (below) >+ int newStatus = FlowInfo.NULL; >+ if (allocation.closeTracker == null) { >+ allocation.closeTracker = new FakedTrackingVariable(scope, allocation); // no local available, closeable is unassigned >+ } else { >+ if (scope.finallyInfo != null) { >+ // inject results from analysing a finally block onto the newly connected wrapper >+ int finallyStatus = scope.finallyInfo.nullStatus(allocation.closeTracker.binding); >+ if (finallyStatus != FlowInfo.UNKNOWN) >+ newStatus = finallyStatus; >+ } >+ } >+ allocation.closeTracker.innerTracker = innerTracker; >+ innerTracker.outerTracker = allocation.closeTracker; >+ flowInfo.markNullStatus(allocation.closeTracker.binding, newStatus); >+ if (newStatus != FlowInfo.NULL) { >+ // propagate results from a finally block also into nested resources: >+ FakedTrackingVariable currentTracker = innerTracker; >+ while (currentTracker != null) { >+ flowInfo.markNullStatus(currentTracker.binding, newStatus); >+ currentTracker.globalClosingState |= allocation.closeTracker.globalClosingState; >+ currentTracker = currentTracker.innerTracker; >+ } >+ } >+ return; // keep chaining wrapper (by avoiding to fall through to removeTrackingVar below) >+ } else { >+ if (!isAnyCloseable(allocation.arguments[0].resolvedType)) { >+ isWrapper = false; // argument is not closeable >+ } >+ } >+ } else { >+ isWrapper = false; // no argument >+ } >+ // successful wrapper detection has exited above, let's see why that failed >+ if (isWrapper) { >+ // remove unnecessary attempts (wrapper has no relevant inner) >+ if (allocation.closeTracker != null) { >+ scope.removeTrackingVar(allocation.closeTracker); >+ allocation.closeTracker = null; > } >+ } else { >+ // allocation does not provide a resource as the first argument -> don't treat as a wrapper >+ handleRegularResource(scope, flowInfo, allocation); > } >+ } else { // regular resource >+ handleRegularResource(scope, flowInfo, allocation); > } >- return null; >+ } >+ >+ private static void handleRegularResource(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation) { >+ FakedTrackingVariable presetTracker = allocation.closeTracker; >+ if (presetTracker != null && presetTracker.originalBinding != null) { >+ // the current assignment forgets a previous resource in the LHS, may cause a leak >+ // report now because handleResourceAssignment can't distinguish this from a self-wrap situation >+ int closeStatus = flowInfo.nullStatus(presetTracker.binding); >+ if (closeStatus != FlowInfo.NON_NULL // old resource was not closed >+ && closeStatus != FlowInfo.UNKNOWN // old resource had some flow information >+ && !flowInfo.isDefinitelyNull(presetTracker.originalBinding) // old resource was not null >+ && !(presetTracker.currentAssignment instanceof LocalDeclaration)) // forgetting old val in local decl is syntactically impossible >+ allocation.closeTracker.recordErrorLocation(presetTracker.currentAssignment, closeStatus); >+ } else { >+ allocation.closeTracker = new FakedTrackingVariable(scope, allocation); // no local available, closeable is unassigned >+ } >+ flowInfo.markAsDefinitelyNull(allocation.closeTracker.binding); >+ } >+ >+ /** Find an existing tracking variable for the argument of an allocation for a resource wrapper. */ >+ private static FakedTrackingVariable findCloseTracker(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation, Expression arg) >+ { >+ while (arg instanceof Assignment) { >+ Assignment assign = (Assignment)arg; >+ LocalVariableBinding innerLocal = assign.localVariableBinding(); >+ if (innerLocal != null) { >+ // nested assignment has already been processed >+ return innerLocal.closeTracker; >+ } else { >+ arg = assign.expression; // unwrap assignment and fall through >+ } >+ } >+ if (arg instanceof SingleNameReference) { >+ // is allocation arg a reference to an existing closeable? >+ LocalVariableBinding local = arg.localVariableBinding(); >+ if (local != null) { >+ return local.closeTracker; >+ } >+ } else if (arg instanceof AllocationExpression) { >+ // nested allocation >+ return ((AllocationExpression)arg).closeTracker; >+ } >+ return null; // not a tracked expression > } > > /** > * Check if the rhs of an assignment or local declaration is an (Auto)Closeable. >- * If so create or re-use a tracking variable, and wire and initialize everything. >+ * If so create or re-use a tracking variable, and wire and initialize everything. >+ * @param scope scope containing the assignment >+ * @param upstreamInfo info without analysis of the rhs, use this to determine the status of a resource being disconnected >+ * @param flowInfo info with analysis of the rhs, use this for recording resource status because this will be passed downstream >+ * @param location where to report warnigs/errors against >+ * @param rhs the right hand side of the assignment, this expression is to be analyzed. >+ * The caller has already checked that the rhs is either of a closeable type or null. >+ * @param local the local variable into which the rhs is being assigned > */ >- public static void handleResourceAssignment(FlowInfo flowInfo, Statement location, Expression rhs, LocalVariableBinding local, >- LocalVariableBinding previousTrackerBinding) >+ public static void handleResourceAssignment(BlockScope scope, FlowInfo upstreamInfo, FlowInfo flowInfo, ASTNode location, Expression rhs, LocalVariableBinding local) > { >- if (isAutoCloseable(rhs.resolvedType)) { >+ // does the LHS (local) already have a tracker, indicating we may leak a resource by the assignment? >+ FakedTrackingVariable previousTracker = null; >+ FakedTrackingVariable disconnectedTracker = null; >+ if (local.closeTracker != null) { >+ // assigning to a variable already holding an AutoCloseable, has it been closed before? >+ previousTracker = local.closeTracker; >+ int nullStatus = upstreamInfo.nullStatus(local); >+ if (nullStatus != FlowInfo.NULL && nullStatus != FlowInfo.UNKNOWN) // only if previous value may be relevant >+ disconnectedTracker = previousTracker; // report error below, unless we have a self-wrap assignment >+ } >+ >+ if (rhs.resolvedType != TypeBinding.NULL) { > // new value is AutoCloseable, start tracking, possibly re-using existing tracker var: >- > FakedTrackingVariable rhsTrackVar = getCloseTrackingVariable(rhs); >- if (rhsTrackVar != null) { // 1. share tracking variable with RHS? >- local.closeTracker = rhsTrackVar; >- // keep null-status unchanged across this assignment >- } else if (previousTrackerBinding != null) { // 2. re-use tracking variable from the LHS? >- // re-assigning from a fresh, mark as not-closed again: >- flowInfo.markAsDefinitelyNull(previousTrackerBinding); >+ if (rhsTrackVar != null) { // 1. if RHS has a tracking variable... >+ if (local.closeTracker == null) { >+ // null shouldn't occur but let's play safe >+ if (rhsTrackVar.originalBinding != null) >+ local.closeTracker = rhsTrackVar; // a.: let fresh LHS share it >+ } else { >+ if (rhsTrackVar == disconnectedTracker && rhs instanceof AllocationExpression) >+ return; // b.: self wrapper: res = new Wrap(res); -> done! >+ local.closeTracker = rhsTrackVar; // c.: conflicting LHS and RHS, proceed with recordErrorLocation below >+ } >+ // keep close-status of RHS unchanged across this assignment >+ } else if (previousTracker != null) { // 2. re-use tracking variable from the LHS? >+ // re-assigning from a fresh value, mark as not-closed again: >+ if ((previousTracker.globalClosingState & (SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE)) == 0) >+ flowInfo.markAsDefinitelyNull(previousTracker.binding); >+ local.closeTracker = analyseCloseableExpression(flowInfo, local, location, rhs, previousTracker); > } else { // 3. no re-use, create a fresh tracking variable: >- local.closeTracker = new FakedTrackingVariable(local, location); >- // a fresh resource, mark as not-closed: >- flowInfo.markAsDefinitelyNull(local.closeTracker.binding); >+ rhsTrackVar = analyseCloseableExpression(flowInfo, local, location, rhs, null); >+ if (rhsTrackVar != null) { >+ local.closeTracker = rhsTrackVar; >+ // a fresh resource, mark as not-closed: >+ if ((rhsTrackVar.globalClosingState & (SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE)) == 0) >+ flowInfo.markAsDefinitelyNull(rhsTrackVar.binding); > // TODO(stephan): this might be useful, but I could not find a test case for it: >-// if (flowContext.initsOnFinally != null) >-// flowContext.initsOnFinally.markAsDefinitelyNonNull(trackerBinding); >+// if (flowContext.initsOnFinally != null) >+// flowContext.initsOnFinally.markAsDefinitelyNonNull(trackerBinding); >+ } >+ } >+ } >+ >+ if (disconnectedTracker != null) { >+ if (disconnectedTracker.innerTracker != null && disconnectedTracker.innerTracker.binding.declaringScope == scope) { >+ // discard tracker for the wrapper but keep the inner: >+ disconnectedTracker.innerTracker.outerTracker = null; >+ scope.pruneWrapperTrackingVar(disconnectedTracker); >+ } else { >+ int upstreamStatus = upstreamInfo.nullStatus(disconnectedTracker.binding); >+ if (upstreamStatus != FlowInfo.NON_NULL) >+ disconnectedTracker.recordErrorLocation(location, upstreamStatus); >+ } >+ } >+ } >+ /** >+ * Analyze structure of a closeable expression, matching (chained) resources against our white lists. >+ * @param flowInfo where to record close status >+ * @param local local variable to which the closeable is being assigned >+ * @param location where to flag errors/warnings against >+ * @param expression expression to be analyzed >+ * @param previousTracker when analyzing a re-assignment we may already have a tracking variable for local, >+ * which we should then re-use >+ * @return a tracking variable associated with local or null if no need to track >+ */ >+ private static FakedTrackingVariable analyseCloseableExpression(FlowInfo flowInfo, LocalVariableBinding local, >+ ASTNode location, Expression expression, FakedTrackingVariable previousTracker) >+ { >+ // unwrap uninteresting nodes: >+ while (true) { >+ if (expression instanceof Assignment) >+ expression = ((Assignment)expression).expression; >+ else if (expression instanceof CastExpression) >+ expression = ((CastExpression) expression).expression; >+ else >+ break; >+ } >+ >+ // analyze by node type: >+ if (expression instanceof AllocationExpression) { >+ // allocation expressions already have their tracking variables analyzed by analyseCloseableAllocation(..) >+ FakedTrackingVariable tracker = ((AllocationExpression) expression).closeTracker; >+ if (tracker != null && tracker.originalBinding == null) { >+ // tracker without original binding (unassigned closeable) shouldn't reach here but let's play safe >+ return null; >+ } >+ return tracker; >+ } else if (expression instanceof MessageSend >+ || expression instanceof ArrayReference) >+ { >+ // we *might* be responsible for the resource obtained >+ FakedTrackingVariable tracker = new FakedTrackingVariable(local, location); >+ tracker.globalClosingState |= SHARED_WITH_OUTSIDE; >+ flowInfo.markPotentiallyNullBit(tracker.binding); // shed some doubt >+ return tracker; >+ } else if ((expression.bits & RestrictiveFlagMASK) == Binding.FIELD) >+ { >+ // responsibility for this resource probably lies at a higher level >+ FakedTrackingVariable tracker = new FakedTrackingVariable(local, location); >+ tracker.globalClosingState |= OWNED_BY_OUTSIDE; >+ // leave state as UNKNOWN, the bit OWNED_BY_OUTSIDE will prevent spurious warnings >+ return tracker; >+ } >+ >+ if (expression.resolvedType instanceof ReferenceBinding) { >+ ReferenceBinding resourceType = (ReferenceBinding) expression.resolvedType; >+ if (resourceType.hasTypeBit(TypeIds.BitResourceFreeCloseable)) { >+ // (a) resource-free closeable: -> null >+ return null; > } > } >+ if (local.closeTracker != null) >+ // (c): inner has already been analyzed: -> re-use track var >+ return local.closeTracker; >+ return new FakedTrackingVariable(local, location); >+ } >+ >+ public static void cleanUpAfterAssignment(BlockScope currentScope, int lhsBits, Expression expression) { >+ // remove all remaining track vars with no original binding >+ >+ // unwrap uninteresting nodes: >+ while (true) { >+ if (expression instanceof Assignment) >+ expression = ((Assignment)expression).expression; >+ else if (expression instanceof CastExpression) >+ expression = ((CastExpression) expression).expression; >+ else >+ break; >+ } >+ if (expression instanceof AllocationExpression) { >+ FakedTrackingVariable tracker = ((AllocationExpression) expression).closeTracker; >+ if (tracker != null && tracker.originalBinding == null) { >+ currentScope.removeTrackingVar(tracker); >+ ((AllocationExpression) expression).closeTracker = null; >+ } >+ } else { >+ // assignment passing a local into a field? >+ LocalVariableBinding local = expression.localVariableBinding(); >+ if (local != null && local.closeTracker != null && ((lhsBits & Binding.FIELD) != 0)) >+ currentScope.removeTrackingVar(local.closeTracker); // TODO: may want to use local.closeTracker.markPassedToOutside(..,true) >+ } > } > > /** Answer wither the given type binding is a subtype of java.lang.AutoCloseable. */ >- public static boolean isAutoCloseable(TypeBinding typeBinding) { >+ public static boolean isAnyCloseable(TypeBinding typeBinding) { > return typeBinding instanceof ReferenceBinding > && ((ReferenceBinding)typeBinding).hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable); > } > >+ public int findMostSpecificStatus(FlowInfo flowInfo, BlockScope currentScope, BlockScope locationScope) { >+ int status = FlowInfo.UNKNOWN; >+ FakedTrackingVariable currentTracker = this; >+ // loop as to consider wrappers (per white list) encapsulating an inner resource. >+ while (currentTracker != null) { >+ LocalVariableBinding currentVar = currentTracker.binding; >+ int currentStatus = getNullStatusAggressively(currentVar, flowInfo); >+ if (locationScope != null) // only check at method exit points >+ currentStatus = mergeCloseStatus(locationScope, currentStatus, currentVar, currentScope); >+ if (currentStatus == FlowInfo.NON_NULL) { >+ status = currentStatus; >+ break; // closed -> stop searching >+ } else if (status == FlowInfo.NULL || status == FlowInfo.UNKNOWN) { >+ status = currentStatus; // improved although not yet safe -> keep searching for better >+ } >+ currentTracker = currentTracker.innerTracker; >+ } >+ return status; >+ } >+ >+ /** >+ * 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; >+ } >+ >+ public int mergeCloseStatus(BlockScope currentScope, int status, LocalVariableBinding local, BlockScope outerScope) { >+ // get the most suitable null status representing whether resource 'binding' has been closed >+ // start at 'currentScope' and potentially travel out until 'outerScope' >+ // at each scope consult any recorded 'finallyInfo'. >+ if (status != FlowInfo.NON_NULL) { >+ if (currentScope.finallyInfo != null) { >+ int finallyStatus = currentScope.finallyInfo.nullStatus(local); >+ if (finallyStatus == FlowInfo.NON_NULL) >+ return finallyStatus; >+ if (finallyStatus != FlowInfo.NULL) // neither is NON_NULL, but not both are NULL => call it POTENTIALLY_NULL >+ status = FlowInfo.POTENTIALLY_NULL; >+ } >+ if (currentScope != outerScope && currentScope.parent instanceof BlockScope) >+ return mergeCloseStatus(((BlockScope) currentScope.parent), status, local, outerScope); >+ } >+ return status; >+ } >+ > /** Mark that this resource is closed locally. */ > public void markClose(FlowInfo flowInfo, FlowContext flowContext) { >- flowInfo.markAsDefinitelyNonNull(this.binding); >- this.globalClosingState |= CLOSE_SEEN; >+ FakedTrackingVariable current = this; >+ do { >+ flowInfo.markAsDefinitelyNonNull(current.binding); >+ current.globalClosingState |= CLOSE_SEEN; > //TODO(stephan): this might be useful, but I could not find a test case for it: >-// if (flowContext.initsOnFinally != null) >-// flowContext.initsOnFinally.markAsDefinitelyNonNull(this.binding); >+// if (flowContext.initsOnFinally != null) >+// flowContext.initsOnFinally.markAsDefinitelyNonNull(this.binding); >+ current = current.innerTracker; >+ } while (current != null); > } > > /** Mark that this resource is closed from a nested method (inside a local class). */ >@@ -179,59 +556,165 @@ public class FakedTrackingVariable extends LocalDeclaration { > * Mark that this resource is passed to some outside code > * (as argument to a method/ctor call or as a return value from the current method), > * and thus should be considered as potentially closed. >+ * @param owned should the resource be considered owned by some outside? > */ >- public static FlowInfo markPassedToOutside(BlockScope scope, Expression expression, FlowInfo flowInfo) { >+ public static FlowInfo markPassedToOutside(BlockScope scope, Expression expression, FlowInfo flowInfo, boolean owned) { >+ > FakedTrackingVariable trackVar = getCloseTrackingVariable(expression); > if (trackVar != null) { >- trackVar.globalClosingState |= PASSED_TO_OUTSIDE; >- if (scope.methodScope() != trackVar.methodScope) >- trackVar.globalClosingState |= CLOSED_IN_NESTED_METHOD; >+ if (trackVar.originalBinding == null) { >+ // an allocation that never was assigned to a local variable -> drop it completely as we're not responsible >+ scope.removeTrackingVar(trackVar); >+ return flowInfo; >+ } > // insert info that the tracked resource *may* be closed (by the target method, i.e.) > FlowInfo infoResourceIsClosed = flowInfo.copy(); >- infoResourceIsClosed.markAsDefinitelyNonNull(trackVar.binding); >+ int flag = owned ? OWNED_BY_OUTSIDE : SHARED_WITH_OUTSIDE; >+ do { >+ trackVar.globalClosingState |= flag; >+ if (scope.methodScope() != trackVar.methodScope) >+ trackVar.globalClosingState |= CLOSED_IN_NESTED_METHOD; >+ infoResourceIsClosed.markAsDefinitelyNonNull(trackVar.binding); >+ } while ((trackVar = trackVar.innerTracker) != null); > return FlowInfo.conditional(flowInfo, infoResourceIsClosed); > } > return flowInfo; > } >- >+ >+ /** >+ * Pick tracking variables from 'varsOfScope' to establish a proper order of processing: >+ * As much as possible pick wrapper resources before their inner resources. >+ * Also consider cases of wrappers and their inners being declared at different scopes. >+ */ >+ public static FakedTrackingVariable pickVarForReporting(Set varsOfScope, BlockScope scope, boolean atExit) { >+ if (varsOfScope.isEmpty()) return null; >+ FakedTrackingVariable trackingVar = (FakedTrackingVariable) varsOfScope.iterator().next(); >+ while (trackingVar.outerTracker != null) { >+ // resource is wrapped, is wrapper defined in this scope? >+ if (varsOfScope.contains(trackingVar.outerTracker)) { >+ // resource from same scope, travel up the wrapper chain >+ trackingVar = trackingVar.outerTracker; >+ } else if (atExit) { >+ // at an exit point we report against inner despite a wrapper that may/may not be closed later >+ break; >+ } else { >+ BlockScope outerTrackerScope = trackingVar.outerTracker.binding.declaringScope; >+ if (outerTrackerScope == scope) { >+ // outerTracker is from same scope and already processed -> pick trackingVar now >+ break; >+ } else { >+ // outer resource is from other (outer?) scope >+ Scope currentScope = scope; >+ while ((currentScope = currentScope.parent) instanceof BlockScope) { >+ if (outerTrackerScope == currentScope) { >+ // at end of block pass responsibility for inner resource to outer scope holding a wrapper >+ varsOfScope.remove(trackingVar); // drop this one >+ // pick a next candidate: >+ return pickVarForReporting(varsOfScope, scope, atExit); >+ } >+ } >+ break; // not parent owned -> pick this var >+ } >+ } >+ } >+ varsOfScope.remove(trackingVar); >+ return trackingVar; >+ } >+ >+ /** >+ * If current is the same as 'returnedResource' or a wrapper thereof, >+ * mark as reported and return true, otherwise false. >+ */ >+ public boolean isResourceBeingReturned(FakedTrackingVariable returnedResource) { >+ FakedTrackingVariable current = this; >+ do { >+ if (current == returnedResource) { >+ this.globalClosingState |= REPORTED_DEFINITIVE_LEAK; >+ return true; >+ } >+ current = current.innerTracker; >+ } while (current != null); >+ return false; >+ } >+ > public void recordErrorLocation(ASTNode location, int nullStatus) { > if (this.recordedLocations == null) > this.recordedLocations = new HashMap(); > this.recordedLocations.put(location, new Integer(nullStatus)); > } > >- public boolean reportRecordedErrors(Scope scope) { >- if (this.globalClosingState == 0) { >- reportError(scope.problemReporter(), null, FlowInfo.NULL); >- return true; >+ public boolean reportRecordedErrors(Scope scope, int mergedStatus) { >+ FakedTrackingVariable current = this; >+ while (current.globalClosingState == 0) { >+ current = current.innerTracker; >+ if (current == null) { >+ // no relevant state found -> report: >+ reportError(scope.problemReporter(), null, mergedStatus); >+ return true; >+ } > } > boolean hasReported = false; > if (this.recordedLocations != null) { > Iterator locations = this.recordedLocations.entrySet().iterator(); >+ int reportFlags = 0; > while (locations.hasNext()) { > Map.Entry entry = (Entry) locations.next(); >- reportError(scope.problemReporter(), (ASTNode)entry.getKey(), ((Integer)entry.getValue()).intValue()); >+ reportFlags |= reportError(scope.problemReporter(), (ASTNode)entry.getKey(), ((Integer)entry.getValue()).intValue()); > hasReported = true; > } >+ if (reportFlags != 0) { >+ // after all locations have been reported, mark as reported to prevent duplicate report via an outer wrapper >+ current = this; >+ do { >+ current.globalClosingState |= reportFlags; >+ } while ((current = current.innerTracker) != null); >+ } > } > return hasReported; > } > >- public void reportError(ProblemReporter problemReporter, ASTNode location, int nullStatus) { >+ public int reportError(ProblemReporter problemReporter, ASTNode location, int nullStatus) { >+ // which degree of problem? >+ boolean isPotentialProblem = false; > if (nullStatus == FlowInfo.NULL) { > if ((this.globalClosingState & CLOSED_IN_NESTED_METHOD) != 0) >- problemReporter.potentiallyUnclosedCloseable(this, location); >- else >- problemReporter.unclosedCloseable(this, location); >+ isPotentialProblem = true; > } else if (nullStatus == FlowInfo.POTENTIALLY_NULL) { >- problemReporter.potentiallyUnclosedCloseable(this, location); >- } >+ isPotentialProblem = true; >+ } >+ // report: >+ if (isPotentialProblem) { >+ if ((this.globalClosingState & (REPORTED_POTENTIAL_LEAK|REPORTED_DEFINITIVE_LEAK)) != 0) >+ return 0; >+ problemReporter.potentiallyUnclosedCloseable(this, location); >+ } else { >+ if ((this.globalClosingState & (REPORTED_DEFINITIVE_LEAK)) != 0) >+ return 0; >+ problemReporter.unclosedCloseable(this, location); >+ } >+ // propagate flag to inners: >+ int reportFlag = isPotentialProblem ? REPORTED_POTENTIAL_LEAK : REPORTED_DEFINITIVE_LEAK; >+ if (location == null) { // if location != null flags will be set after the loop over locations >+ FakedTrackingVariable current = this; >+ do { >+ current.globalClosingState |= reportFlag; >+ } while ((current = current.innerTracker) != null); >+ } >+ return reportFlag; > } > > public void reportExplicitClosing(ProblemReporter problemReporter) { >- if ((this.globalClosingState & REPORTED) == 0) { >- this.globalClosingState |= REPORTED; >+ if ((this.globalClosingState & (OWNED_BY_OUTSIDE|REPORTED_EXPLICIT_CLOSE)) == 0) { // can't use t-w-r for OWNED_BY_OUTSIDE >+ this.globalClosingState |= REPORTED_EXPLICIT_CLOSE; > problemReporter.explicitlyClosedAutoCloseable(this); > } > } >+ >+ public void resetReportingBits() { >+ FakedTrackingVariable current = this; >+ do { >+ current.globalClosingState &= ~(REPORTED_POTENTIAL_LEAK|REPORTED_DEFINITIVE_LEAK); >+ current = current.innerTracker; >+ } while (current != null); >+ } > } >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 dac029c..91808db 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 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2011 IBM Corporation and others. >+ * Copyright (c) 2000, 2012 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -13,6 +13,7 @@ > * bug 335093 - [compiler][null] minimal hook for future null annotation support > * bug 349326 - [1.7] new warning for missing try-with-resources > * bug 186342 - [compiler][null] Using annotations for null checking >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -74,11 +75,26 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > this.initialization.checkNPE(currentScope, flowContext, flowInfo); > } > >+ FlowInfo preInitInfo = null; >+ boolean shouldAnalyseResource = this.binding != null >+ && flowInfo.reachMode() == FlowInfo.REACHABLE >+ && FakedTrackingVariable.isAnyCloseable(this.initialization.resolvedType); >+ if (shouldAnalyseResource) { >+ preInitInfo = flowInfo.unconditionalCopy(); >+ // analysis of resource leaks needs additional context while analyzing the RHS: >+ FakedTrackingVariable.preConnectTrackerAcrossAssignment(this, this.binding, this.initialization); >+ } >+ > flowInfo = > this.initialization > .analyseCode(currentScope, flowContext, flowInfo) > .unconditionalInits(); >- FakedTrackingVariable.handleResourceAssignment(flowInfo, this, this.initialization, this.binding, null); >+ >+ if (shouldAnalyseResource) >+ FakedTrackingVariable.handleResourceAssignment(currentScope, preInitInfo, flowInfo, this, this.initialization, this.binding); >+ else >+ FakedTrackingVariable.cleanUpAfterAssignment(currentScope, Binding.LOCAL, this.initialization); >+ > 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 46d4540..0dda53f 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 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2011 IBM Corporation and others. >+ * Copyright (c) 2000, 2012 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -12,6 +12,7 @@ > * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE > * bug 349326 - [1.7] new warning for missing try-with-resources > * bug 186342 - [compiler][null] Using annotations for null checking >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -96,9 +97,9 @@ 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(); >+ // 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, false); > } > analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments); > } >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 3a2a0ed..6739bbc 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 >@@ -81,7 +81,7 @@ public class QualifiedAllocationExpression extends AllocationExpression { > 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 = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, false); > 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 18a1bc1..610f55b 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 >@@ -13,6 +13,7 @@ > * bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop) > * bug 186342 - [compiler][null] Using annotations for null checking > * bug 365835 - [compiler][null] inconsistent error reporting. >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -52,9 +53,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > if (trackingVariable != null) { > if (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); >+ // by returning the method passes the responsibility to the caller: >+ flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.expression, flowInfo, true); > } > } > this.initStateIndex = >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 9fae009..0534970 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 >@@ -12,6 +12,7 @@ > * bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis > * bug 349326 - [1.7] new warning for missing try-with-resources > * bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >@@ -134,7 +135,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > 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; >+ // keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block > } > TypeBinding type = resourceBinding.type; > if (type != null && type.isValidBinding()) { >@@ -276,7 +277,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl > 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; >+ // keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block > } > TypeBinding type = resourceBinding.type; > if (type != null && type.isValidBinding()) { >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 9294726..de17c07 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 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2011 IBM Corporation and others. >+ * Copyright (c) 2000, 2012 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -11,6 +11,7 @@ > * bug 349326 - [1.7] new warning for missing try-with-resources > * bug 186342 - [compiler][null] Using annotations for null checking > * bug 364890 - BinaryTypeBinding should use char constants from Util >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -1275,7 +1276,9 @@ public ReferenceBinding superclass() { > this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations; > } > } >- this.typeBits |= this.superclass.typeBits; >+ this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits); >+ if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) // avoid the side-effects of hasTypeBit()! >+ this.typeBits |= applyCloseableWhitelists(); > return this.superclass; > } > // NOTE: superInterfaces of binary types are resolved when needed >@@ -1298,7 +1301,7 @@ public ReferenceBinding[] superInterfaces() { > this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations; > } > } >- this.typeBits |= this.superInterfaces[i].typeBits; >+ this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits); > } > 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 c93c9d9..33c3b6f 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 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2011 IBM Corporation and others. >+ * Copyright (c) 2000, 2012 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -10,11 +10,14 @@ > * Stephan Herrmann - Contributions for > * bug 349326 - [1.7] new warning for missing try-with-resources > * bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > > import java.util.ArrayList; >+import java.util.HashSet; > import java.util.List; >+import java.util.Set; > > import org.eclipse.jdt.core.compiler.CharOperation; > import org.eclipse.jdt.internal.compiler.ast.*; >@@ -976,17 +979,24 @@ public int registerTrackingVariable(FakedTrackingVariable fakedTrackingVariable) > this.trackingVariables = new ArrayList(3); > this.trackingVariables.add(fakedTrackingVariable); > MethodScope outerMethodScope = outerMostMethodScope(); >- return outerMethodScope.analysisIndex + (outerMethodScope.trackVarCount++); >- >+ return outerMethodScope.analysisIndex++; > } > /** When are no longer interested in this tracking variable - remove it. */ > public void removeTrackingVar(FakedTrackingVariable trackingVariable) { >+ if (trackingVariable.innerTracker != null) { >+ removeTrackingVar(trackingVariable.innerTracker); >+ trackingVariable.innerTracker = null; >+ } > if (this.trackingVariables != null) > if (this.trackingVariables.remove(trackingVariable)) > return; > if (this.parent instanceof BlockScope) > ((BlockScope)this.parent).removeTrackingVar(trackingVariable); > } >+/** Unregister a wrapper resource without affecting its inner. */ >+public void pruneWrapperTrackingVar(FakedTrackingVariable trackingVariable) { >+ this.trackingVariables.remove(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. >@@ -999,14 +1009,25 @@ public void checkUnclosedCloseables(FlowInfo flowInfo, ASTNode location, BlockSc > return; > } > if (location != null && flowInfo.reachMode() != 0) return; >- for (int i=0; i<this.trackingVariables.size(); i++) { >- FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i); >+ >+ FakedTrackingVariable returnVar = (location instanceof ReturnStatement) ? >+ FakedTrackingVariable.getCloseTrackingVariable(((ReturnStatement)location).expression) : null; >+ >+ Set varSet = new HashSet(this.trackingVariables); >+ FakedTrackingVariable trackingVar; >+ // pick one outer-most variable from the set at a time >+ while ((trackingVar = FakedTrackingVariable.pickVarForReporting(varSet, this, location != null)) != null) { >+ >+ if (returnVar != null && trackingVar.isResourceBeingReturned(returnVar)) { >+ continue; >+ } >+ > 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); >- // try to improve info if a close() inside finally was observed: >- if (locationScope != null) // only check at method exit points >- status = locationScope.mergeCloseStatus(status, trackingVar.binding, this); >+ >+ // compute the most specific null status for this resource, >+ int status = trackingVar.findMostSpecificStatus(flowInfo, this, locationScope); >+ > if (status == FlowInfo.NULL) { > // definitely unclosed: highest priority > reportResourceLeak(trackingVar, location, status); >@@ -1015,7 +1036,7 @@ public void checkUnclosedCloseables(FlowInfo flowInfo, ASTNode location, BlockSc > 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 >+ if (trackingVar.reportRecordedErrors(this, status)) // ... report previously recorded errors > continue; > } > if (status == FlowInfo.POTENTIALLY_NULL) { >@@ -1032,25 +1053,13 @@ public void checkUnclosedCloseables(FlowInfo flowInfo, ASTNode location, BlockSc > for (int i=0; i<this.localIndex; i++) > this.locals[i].closeTracker = null; > this.trackingVariables = null; >- } >-} >- >-private int mergeCloseStatus(int status, LocalVariableBinding binding, BlockScope outerScope) { >- // get the most suitable null status representing whether resource 'binding' has been closed >- // start at this scope and potentially travel out until 'outerScope' >- // at each scope consult any recorded 'finallyInfo'. >- if (status != FlowInfo.NON_NULL) { >- if (this.finallyInfo != null) { >- int finallyStatus = this.finallyInfo.nullStatus(binding); >- if (finallyStatus == FlowInfo.NON_NULL) >- return finallyStatus; >- if (finallyStatus != FlowInfo.NULL) // neither is NON_NULL, but not both are NULL => call it POTENTIALLY_NULL >- status = FlowInfo.POTENTIALLY_NULL; >+ } else { >+ int size = this.trackingVariables.size(); >+ for (int i=0; i<size; i++) { >+ FakedTrackingVariable tracker = (FakedTrackingVariable) this.trackingVariables.get(0); >+ tracker.resetReportingBits(); > } >- if (this != outerScope && this.parent instanceof BlockScope) >- return ((BlockScope) this.parent).mergeCloseStatus(status, binding, outerScope); > } >- return status; > } > > private void reportResourceLeak(FakedTrackingVariable trackingVar, ASTNode location, int nullStatus) { >@@ -1083,6 +1092,8 @@ public void correlateTrackingVarsIfElse(FlowInfo thenFlowInfo, FlowInfo elseFlow > if (this.trackingVariables != null) { > for (int i=0; i<this.trackingVariables.size(); i++) { > FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i); >+ if (trackingVar.originalBinding == null) >+ continue; > if ( thenFlowInfo.isDefinitelyNonNull(trackingVar.binding) // closed in then branch > && elseFlowInfo.isDefinitelyNull(trackingVar.originalBinding)) // null in else branch > { >@@ -1098,36 +1109,4 @@ public void correlateTrackingVarsIfElse(FlowInfo thenFlowInfo, FlowInfo elseFlow > 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 3eb3cca..8778c6b 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 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2011 IBM Corporation and others. >+ * Copyright (c) 2000, 2012 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -12,6 +12,7 @@ > * 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 >+ * Bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -909,7 +910,10 @@ public class ClassScope extends Scope { > } else { > // only want to reach here when no errors are reported > sourceType.superclass = superclass; >- sourceType.typeBits |= superclass.typeBits; >+ sourceType.typeBits |= (superclass.typeBits & TypeIds.InheritableBits); >+ // further analysis against white lists for the unlikely case we are compiling java.io.*: >+ if ((sourceType.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) >+ sourceType.typeBits |= sourceType.applyCloseableWhitelists(); > return true; > } > } >@@ -1025,7 +1029,7 @@ public class ClassScope extends Scope { > noProblems &= superInterfaceRef.resolvedType.isValidBinding(); > } > // only want to reach here when no errors are reported >- sourceType.typeBits |= superInterface.typeBits; >+ sourceType.typeBits |= (superInterface.typeBits & TypeIds.InheritableBits); > interfaceBindings[count++] = superInterface; > } > // hold onto all correctly resolved superinterfaces >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 52c7258..bfb4f2b 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 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2011 IBM Corporation and others. >+ * Copyright (c) 2000, 2012 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -50,9 +50,6 @@ 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/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java >index 8e57afb..93e347f 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 >@@ -10,6 +10,7 @@ > * Stephan Herrmann - Contributions for > * bug 349326 - [1.7] new warning for missing try-with-resources > * bug 186342 - [compiler][null] Using annotations for null checking >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -1455,4 +1456,50 @@ MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't re > public FieldBinding[] unResolvedFields() { > return Binding.NO_FIELDS; > } >+ >+/* >+ * If a type - known to be a Closeable - is mentioned in one of our white lists >+ * answer the typeBit for the white list (BitWrapperCloseable or BitResourceFreeCloseable). >+ */ >+protected int applyCloseableWhitelists() { >+ switch (this.compoundName.length) { >+ case 3: >+ if (CharOperation.equals(TypeConstants.JAVA, this.compoundName[0])) { >+ if (CharOperation.equals(TypeConstants.IO, this.compoundName[1])) { >+ char[] simpleName = this.compoundName[2]; >+ int l = TypeConstants.JAVA_IO_WRAPPER_CLOSEABLES.length; >+ for (int i = 0; i < l; i++) { >+ if (CharOperation.equals(simpleName, TypeConstants.JAVA_IO_WRAPPER_CLOSEABLES[i])) >+ return TypeIds.BitWrapperCloseable; >+ } >+ l = TypeConstants.JAVA_IO_RESOURCE_FREE_CLOSEABLES.length; >+ for (int i = 0; i < l; i++) { >+ if (CharOperation.equals(simpleName, TypeConstants.JAVA_IO_RESOURCE_FREE_CLOSEABLES[i])) >+ return TypeIds.BitResourceFreeCloseable; >+ } >+ } >+ } >+ break; >+ case 4: >+ if (CharOperation.equals(TypeConstants.JAVA, this.compoundName[0])) { >+ if (CharOperation.equals(TypeConstants.UTIL, this.compoundName[1])) { >+ if (CharOperation.equals(TypeConstants.ZIP, this.compoundName[2])) { >+ char[] simpleName = this.compoundName[3]; >+ int l = TypeConstants.JAVA_UTIL_ZIP_WRAPPER_CLOSEABLES.length; >+ for (int i = 0; i < l; i++) { >+ if (CharOperation.equals(simpleName, TypeConstants.JAVA_UTIL_ZIP_WRAPPER_CLOSEABLES[i])) >+ return TypeIds.BitWrapperCloseable; >+ } >+ } >+ } >+ } >+ break; >+ } >+ int l = TypeConstants.OTHER_WRAPPER_CLOSEABLES.length; >+ for (int i = 0; i < l; i++) { >+ if (CharOperation.equals(this.compoundName, TypeConstants.OTHER_WRAPPER_CLOSEABLES[i])) >+ return TypeIds.BitWrapperCloseable; >+ } >+ return 0; >+} > } >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 7098d37..e607732 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,7 +7,9 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources >+ * Stephan Herrmann - Contributions for >+ * bug 349326 - [1.7] new warning for missing try-with-resources >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -19,6 +21,7 @@ public interface TypeConstants { > char[] LANG = "lang".toCharArray(); //$NON-NLS-1$ > char[] IO = "io".toCharArray(); //$NON-NLS-1$ > char[] UTIL = "util".toCharArray(); //$NON-NLS-1$ >+ char[] ZIP = "zip".toCharArray(); //$NON-NLS-1$ > char[] ANNOTATION = "annotation".toCharArray(); //$NON-NLS-1$ > char[] REFLECT = "reflect".toCharArray(); //$NON-NLS-1$ > char[] LENGTH = "length".toCharArray(); //$NON-NLS-1$ >@@ -154,6 +157,59 @@ public interface TypeConstants { > }; > char[][] JAVA_LANG_AUTOCLOSEABLE = {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$ > char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$ >+ // white lists of closeables: >+ char[][] JAVA_IO_WRAPPER_CLOSEABLES = new char[][] { >+ "BufferedInputStream".toCharArray(), //$NON-NLS-1$ >+ "BufferedOutputStream".toCharArray(), //$NON-NLS-1$ >+ "BufferedReader".toCharArray(), //$NON-NLS-1$ >+ "BufferedWriter".toCharArray(), //$NON-NLS-1$ >+ "InputStreamReader".toCharArray(), //$NON-NLS-1$ >+ "PrintWriter".toCharArray(), //$NON-NLS-1$ >+ "LineNumberReader".toCharArray(), //$NON-NLS-1$ >+ "DataInputStream".toCharArray(), //$NON-NLS-1$ >+ "DataOutputStream".toCharArray(), //$NON-NLS-1$ >+ "ObjectInputStream".toCharArray(), //$NON-NLS-1$ >+ "ObjectOutputStream".toCharArray(), //$NON-NLS-1$ >+ "FilterInputStream".toCharArray(), //$NON-NLS-1$ >+ "FilterOutputStream".toCharArray(), //$NON-NLS-1$ >+ "DataInputStream".toCharArray(), //$NON-NLS-1$ >+ "DataOutputStream".toCharArray(), //$NON-NLS-1$ >+ "PushbackInputStream".toCharArray(), //$NON-NLS-1$ >+ "SequenceInputStream".toCharArray(), //$NON-NLS-1$ >+ "PrintStream".toCharArray(), //$NON-NLS-1$ >+ "PushbackReader".toCharArray(), //$NON-NLS-1$ >+ "OutputStreamWriter".toCharArray(), //$NON-NLS-1$ >+ }; >+ char[][] JAVA_UTIL_ZIP_WRAPPER_CLOSEABLES = new char[][] { >+ "GZIPInputStream".toCharArray(), //$NON-NLS-1$ >+ "InflaterInputStream".toCharArray(), //$NON-NLS-1$ >+ "DeflaterInputStream".toCharArray(), //$NON-NLS-1$ >+ "CheckedInputStream".toCharArray(), //$NON-NLS-1$ >+ "ZipInputStream".toCharArray(), //$NON-NLS-1$ >+ "JarInputStream".toCharArray(), //$NON-NLS-1$ >+ "GZIPOutputStream".toCharArray(), //$NON-NLS-1$ >+ "InflaterOutputStream".toCharArray(), //$NON-NLS-1$ >+ "DeflaterOutputStream".toCharArray(), //$NON-NLS-1$ >+ "CheckedOutputStream".toCharArray(), //$NON-NLS-1$ >+ "ZipOutputStream".toCharArray(), //$NON-NLS-1$ >+ "JarOutputStream".toCharArray(), //$NON-NLS-1$ >+ }; >+ char[][][] OTHER_WRAPPER_CLOSEABLES = new char[][][] { >+ {JAVA, "security".toCharArray(), "DigestInputStream".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$ >+ {JAVA, "security".toCharArray(), "DigestOutputStream".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$ >+ {JAVA, "beans".toCharArray(), "XMLEncoder".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$ >+ {JAVA, "beans".toCharArray(), "XMLDecoder".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$ >+ {JAVAX, "sound".toCharArray(), "sampled".toCharArray(), "AudioInputStream".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ >+ }; >+ char[][] JAVA_IO_RESOURCE_FREE_CLOSEABLES = new char[][] { >+ "StringReader".toCharArray(), //$NON-NLS-1$ >+ "StringWriter".toCharArray(), //$NON-NLS-1$ >+ "ByteArrayInputStream".toCharArray(), //$NON-NLS-1$ >+ "ByteArrayOutputStream".toCharArray(), //$NON-NLS-1$ >+ "CharArrayReader".toCharArray(), //$NON-NLS-1$ >+ "CharArrayWriter".toCharArray(), //$NON-NLS-1$ >+ "StringBufferInputStream".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 5156a44..439b49e 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 >@@ -11,6 +11,7 @@ > * bug 349326 - [1.7] new warning for missing try-with-resources > * bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource > * bug 186342 - [compiler][null] Using annotations for null checking >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -202,4 +203,19 @@ public interface TypeIds { > * @see ReferenceBinding#hasTypeBit(int) > */ > final int BitCloseable = 2; >+ /** >+ * Bit for members of a white list: >+ * Subtypes of Closeable that wrap another resource without directly holding any OS resources. >+ */ >+ final int BitWrapperCloseable = 4; >+ /** >+ * Bit for members of a white list: >+ * Subtypes of Closeable that do not hold an OS resource that needs to be released. >+ */ >+ final int BitResourceFreeCloseable = 8; >+ >+ /** >+ * Set of type bits that should be inherited by any sub types. >+ */ >+ final int InheritableBits = BitAutoCloseable | BitCloseable; > } >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 995f30e..91a7065 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, 2011 IBM Corporation and others. >+ * Copyright (c) 2000, 2012 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -11,6 +11,7 @@ > * 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 > * bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -316,11 +317,11 @@ public class TypeVariableBinding extends ReferenceBinding { > // initialize from bounds > this.typeBits = 0; > if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized)) >- this.typeBits |= this.superclass.typeBits; >+ this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits); > if (this.superInterfaces != null) > for (int i = 0, l = this.superInterfaces.length; i < l; i++) > if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized)) >- this.typeBits |= this.superInterfaces[i].typeBits; >+ this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits); > } > return (this.typeBits & bit) != 0; > } >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 01f369e..93dffe1 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, 2011 IBM Corporation and others. >+ * Copyright (c) 2005, 2012 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -10,6 +10,7 @@ > * Stephan Herrmann - Contribution for > * bug 349326 - [1.7] new warning for missing try-with-resources > * bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource >+ * bug 358903 - Filter practically unimportant resource leak warnings > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.lookup; > >@@ -429,11 +430,11 @@ public class WildcardBinding extends ReferenceBinding { > // initialize from upper bounds > this.typeBits = 0; > if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized)) >- this.typeBits |= this.superclass.typeBits; >+ this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits); > if (this.superInterfaces != null) > for (int i = 0, l = this.superInterfaces.length; i < l; i++) > if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized)) >- this.typeBits |= this.superInterfaces[i].typeBits; >+ this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits); > } > return (this.typeBits & bit) != 0; > }
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 358903
:
208899
|
209082
|
209107
|
209169
|
209179
|
209232
|
209234
|
209276
|
209373
|
209374
|
209384
|
209409
|
209457
|
209460
|
209464
|
209472
| 209482