diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/core/compiler/IProblem.java index e62c48e2d25..c46c7e063dd 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/core/compiler/IProblem.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/core/compiler/IProblem.java @@ -2068,6 +2068,8 @@ public interface IProblem { int OverrideReducingParamterOwning = Internal + 1266; /** @since 3.37 */ int OverrideAddingReturnOwning = Internal + 1267; + /** @since 3.38 */ + int StaticResourceField = Internal + 1268; // terminally /** @since 3.14 */ diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java index eced6c64e5c..3349e817939 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java @@ -242,6 +242,8 @@ private static FakedTrackingVariable getRiskyCloseTrackerAt(LocalVariableBinding * @return a new {@link FakedTrackingVariable} or null. */ public static FakedTrackingVariable getCloseTrackingVariable(Expression expression, FlowInfo flowInfo, FlowContext flowContext, boolean useAnnotations) { + if (flowInfo.reachMode() != FlowInfo.REACHABLE) + return null; while (true) { if (expression instanceof CastExpression) expression = ((CastExpression) expression).expression; @@ -425,6 +427,8 @@ private static void preConnectTrackerAcrossAssignment(ASTNode location, LocalVar * See Bug 358903 - Filter practically unimportant resource leak warnings */ public static void analyseCloseableAllocation(BlockScope scope, FlowInfo flowInfo, FlowContext flowContext, AllocationExpression allocation) { + if (flowInfo.reachMode() != FlowInfo.REACHABLE) + return; // 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) @@ -842,8 +846,8 @@ public static void handleResourceFieldAssignment(BlockScope scope, FlowInfo flow if (fieldReference.receiver.isThis()) field = fieldReference.binding; } - if (field != null) { - if (!field.isStatic() && (field.tagBits & TagBits.AnnotationOwning) != 0) { + if (field != null&& (field.tagBits & TagBits.AnnotationNotOwning) == 0) { // assignment to @NotOwned has no meaning + if ((field.tagBits & TagBits.AnnotationOwning) != 0) { rhsTrackVar.markNullStatus(flowInfo, flowContext, FlowInfo.NON_NULL); } else { rhsTrackVar.markAsShared(); @@ -1008,6 +1012,11 @@ protected static int getNullStatusFromMessageSend(Expression expression) { public static void cleanUpAfterAssignment(BlockScope currentScope, int lhsBits, Expression expression) { // remove all remaining track vars with no original binding + boolean useAnnotations = currentScope.compilerOptions().isAnnotationBasedResourceAnalysisEnabled; + if (useAnnotations && (lhsBits & Binding.FIELD) != 0) { + return; + } + // unwrap uninteresting nodes: while (true) { if (expression instanceof Assignment) @@ -1034,7 +1043,7 @@ else if (expression instanceof CastExpression) LocalVariableBinding local = expression.localVariableBinding(); if (local != null && ((lhsBits & Binding.FIELD) != 0) - && !currentScope.compilerOptions().isAnnotationBasedResourceAnalysisEnabled + && !useAnnotations && local.closeTracker != null) { local.closeTracker.withdraw(); // TODO: may want to use local.closeTracker.markPassedToOutside(..,true) } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java index eff6702c2df..d69c87c5ff1 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java @@ -109,9 +109,11 @@ public FlowInfo analyseCode(MethodScope initializationScope, FlowContext flowCon } if (options.isAnnotationBasedResourceAnalysisEnabled && this.binding != null - && this.binding.type.hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) + && FakedTrackingVariable.isCloseableNotWhiteListed(this.binding.type)) { - if ((this.binding.tagBits & TagBits.AnnotationOwning) == 0) { + if (this.binding.isStatic()) { + initializationScope.problemReporter().staticResourceField(this); + } else if ((this.binding.tagBits & TagBits.AnnotationOwning) == 0) { initializationScope.problemReporter().shouldMarkFieldAsOwning(this); } else if (!this.binding.declaringClass.hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) { initializationScope.problemReporter().shouldImplementAutoCloseable(this); diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java index fffec21347d..8135e3167e7 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java @@ -159,7 +159,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl yieldQualifiedCheck(currentScope); // recording the closing of AutoCloseable resources: CompilerOptions compilerOptions = currentScope.compilerOptions(); - boolean analyseResources = compilerOptions.analyseResourceLeaks; + boolean analyseResources = compilerOptions.analyseResourceLeaks && flowInfo.reachMode() == FlowInfo.REACHABLE; if (analyseResources) { if (nonStatic) { // closeable.close() diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java index c07532688dd..5f22ad875bc 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java @@ -182,8 +182,10 @@ public class IrritantSet { STATIC_METHOD .set(CompilerOptions.MethodCanBePotentiallyStatic); RESOURCE - .set(CompilerOptions.PotentiallyUnclosedCloseable) - .set(CompilerOptions.ExplicitlyClosedAutoCloseable); + .set(CompilerOptions.PotentiallyUnclosedCloseable + |CompilerOptions.ExplicitlyClosedAutoCloseable) + .set(CompilerOptions.InsufficientResourceManagement + |CompilerOptions.IncompatibleOwningContract); INCOMPLETE_SWITCH.set(CompilerOptions.MissingDefaultCase); String suppressRawWhenUnchecked = System.getProperty("suppressRawWhenUnchecked"); //$NON-NLS-1$ if (suppressRawWhenUnchecked != null && "true".equalsIgnoreCase(suppressRawWhenUnchecked)) { //$NON-NLS-1$ diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java index 5790d7415ee..48afa6a46b4 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java @@ -699,6 +699,7 @@ public static int getIrritant(int problemID) { case IProblem.NotOwningResourceField: case IProblem.OwningFieldInNonResourceClass: case IProblem.OwningFieldShouldImplementClose: + case IProblem.StaticResourceField: return CompilerOptions.InsufficientResourceManagement; case IProblem.OverrideReducingParamterOwning: case IProblem.OverrideAddingReturnOwning: @@ -10324,6 +10325,14 @@ public void shouldMarkFieldAsOwning(ASTNode location) { location.sourceStart, location.sourceEnd); } +public void staticResourceField(FieldDeclaration fieldDeclaration) { + this.handle( + IProblem.StaticResourceField, + NoArgument, + NoArgument, + fieldDeclaration.sourceStart, + fieldDeclaration.sourceEnd); +} public void shouldImplementAutoCloseable(ASTNode location) { char[] name = this.options.owningAnnotationName[this.options.owningAnnotationName.length-1]; String[] args = { String.valueOf(name) }; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/messages.properties index 38910ba0e50..3a1d15dd9c7 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/messages.properties +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/messages.properties @@ -920,6 +920,7 @@ 1265 = Class with resource fields tagged as ''@{0}'' should implement ''close()'' 1266 = Unsafe redefinition, super method tagged this parameter as ''@{0}'' 1267 = Unsafe redefinition, super method is not tagged as ''@{0}'' +1268 = It is not recommended to hold a resource in a static field # Java9 - Module declaration related 1300 = {0} cannot be resolved to a module diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java index c419d06773f..80eb376d774 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java @@ -1037,6 +1037,7 @@ class ProblemAttributes { expectedProblemAttributes.put("StaticMemberOfParameterizedType", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); expectedProblemAttributes.put("StaticMethodRequested", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); expectedProblemAttributes.put("StaticMethodShouldBeAccessedStatically", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); + expectedProblemAttributes.put("StaticResourceField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); expectedProblemAttributes.put("StringConstantIsExceedingUtf8Limit", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL)); expectedProblemAttributes.put("SuperAccessCannotBypassDirectSuper", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); expectedProblemAttributes.put("SuperCallCannotBypassOverride", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); @@ -2156,6 +2157,7 @@ class ProblemAttributes { expectedProblemAttributes.put("StaticMemberOfParameterizedType", SKIP); expectedProblemAttributes.put("StaticMethodRequested", SKIP); expectedProblemAttributes.put("StaticMethodShouldBeAccessedStatically", SKIP); + expectedProblemAttributes.put("StaticResourceField", new ProblemAttributes(JavaCore.COMPILER_PB_RECOMMENDED_RESOURCE_MANAGEMENT)); expectedProblemAttributes.put("StringConstantIsExceedingUtf8Limit", SKIP); expectedProblemAttributes.put("SuperAccessCannotBypassDirectSuper", SKIP); expectedProblemAttributes.put("SuperCallCannotBypassOverride", SKIP); diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakAnnotatedTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakAnnotatedTests.java index 597fc2f796f..ec95894afe5 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakAnnotatedTests.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakAnnotatedTests.java @@ -147,7 +147,21 @@ protected String potentialLeakOrCloseNotShownAtExit(String resourceName) { protected String potentialOrDefiniteLeak(String string) { return "Resource leak: '"+string+"' is never closed\n"; } - +protected String fieldDeclPrefix() { + return "@org.eclipse.jdt.annotation.Owning "; // intentionally no linebreak +} +/** Override to add annotation to some tests from the super class. */ +@Override +protected void runConformTest(String[] testFiles, String expectedOutput, Map customOptions) { + testFiles = addAnnotationSources(testFiles); + super.runConformTest(testFiles, expectedOutput, customOptions); +} +/** Override to add annotation to some tests from the super class. */ +@Override +protected void runLeakTest(String[] testFiles, String expectedCompileError, Map options) { + testFiles = addAnnotationSources(testFiles); + super.runLeakTest(testFiles, expectedCompileError, options); +} private void runLeakTestWithAnnotations(String[] testFiles, String expectedProblems, Map options) { runLeakTestWithAnnotations(testFiles, expectedProblems, options, true); } @@ -160,14 +174,18 @@ private void runLeakTestWithAnnotations(String[] testFiles, String expectedProbl options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.INFO); if (options.get(CompilerOptions.OPTION_ReportInsufficientResourceManagement).equals(CompilerOptions.IGNORE)) options.put(CompilerOptions.OPTION_ReportInsufficientResourceManagement, CompilerOptions.INFO); - int length = testFiles.length; - System.arraycopy(testFiles, 0, testFiles = new String[length+4], 4, length); - testFiles[0] = OWNING_JAVA; - testFiles[1] = OWNING_CONTENT; - testFiles[2] = NOTOWNING_JAVA; - testFiles[3] = NOTOWNING_CONTENT; + testFiles = addAnnotationSources(testFiles); runLeakTest(testFiles, expectedProblems, options, shouldFlushOutputDirectory); } +private String[] addAnnotationSources(String[] testFiles) { + int length = testFiles.length; + System.arraycopy(testFiles, 0, testFiles = new String[length+4], 0, length); + testFiles[length+0] = OWNING_JAVA; + testFiles[length+1] = OWNING_CONTENT; + testFiles[length+2] = NOTOWNING_JAVA; + testFiles[length+3] = NOTOWNING_CONTENT; + return testFiles; +} @Override protected String getTest056e_log() { @@ -1587,4 +1605,112 @@ void consumer(ResourceProducer producer) { """, options); } +public void testGH2161_staticBlock() { + Map options = getCompilerOptions(); + options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); + options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); + options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR); + runLeakTestWithAnnotations( + new String[] { + "ClassWithStatics.java", + """ + import org.eclipse.jdt.annotation.*; + class RC implements AutoCloseable { + public void close() {} + } + public class ClassWithStatics { + + private static AutoCloseable f1; + protected static @Owning AutoCloseable f2; + public static @NotOwning AutoCloseable f3; + static @SuppressWarnings("resource") @Owning AutoCloseable fSilent; + + static { + f1 = new RC(); + System.out.print(f1); // avoid unused warning + f2 = new RC(); + f3 = new RC(); + fSilent = new RC(); + } + } + """ + }, + """ + ---------- + 1. INFO in ClassWithStatics.java (at line 7) + private static AutoCloseable f1; + ^^ + It is not recommended to hold a resource in a static field + ---------- + 2. INFO in ClassWithStatics.java (at line 8) + protected static @Owning AutoCloseable f2; + ^^ + It is not recommended to hold a resource in a static field + ---------- + 3. INFO in ClassWithStatics.java (at line 9) + public static @NotOwning AutoCloseable f3; + ^^ + It is not recommended to hold a resource in a static field + ---------- + 4. ERROR in ClassWithStatics.java (at line 13) + f1 = new RC(); + ^^^^^^^^ + Mandatory close of resource \'\' has not been shown + ---------- + 5. ERROR in ClassWithStatics.java (at line 16) + f3 = new RC(); + ^^^^^^^^ + Resource leak: \'\' is never closed + ---------- + """, + options); +} +public void testGH2161_initializers() { + Map options = getCompilerOptions(); + options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR); + options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR); + options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR); + runLeakTestWithAnnotations( + new String[] { + "ClassWithStatics.java", + """ + import org.eclipse.jdt.annotation.*; + import java.io.StringWriter; + class RC implements AutoCloseable { + public void close() {} + } + public class ClassWithStatics { + + private static AutoCloseable f1 = new RC(); + protected static @Owning AutoCloseable f2 = new RC(); + public static @NotOwning AutoCloseable f3 = new RC(); + static @SuppressWarnings("resource") @Owning AutoCloseable fSilent = new RC(); + static StringWriter sw = new StringWriter(); // no reason to complain: white listed + + static { + System.out.print(f1); // avoid unused warning :) + } + } + """ + }, + """ + ---------- + 1. INFO in ClassWithStatics.java (at line 8) + private static AutoCloseable f1 = new RC(); + ^^ + It is not recommended to hold a resource in a static field + ---------- + 2. INFO in ClassWithStatics.java (at line 9) + protected static @Owning AutoCloseable f2 = new RC(); + ^^ + It is not recommended to hold a resource in a static field + ---------- + 3. INFO in ClassWithStatics.java (at line 10) + public static @NotOwning AutoCloseable f3 = new RC(); + ^^ + It is not recommended to hold a resource in a static field + ---------- + """, + options); +} } 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 index c55e78a8fd3..ba482460738 100644 --- 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 @@ -119,6 +119,10 @@ protected String potentialLeakOrCloseNotShownAtExit(String resourceName) { protected String potentialOrDefiniteLeak(String string) { return "Potential resource leak: '"+string+"' may not be closed\n"; } +/** prefix for a field declaration that should be seen as a resource owner */ +protected String fieldDeclPrefix() { + return ""; +} // Bug 349326 - [1.7] new warning for missing try-with-resources // a method uses an AutoCloseable without ever closing it. @@ -2047,6 +2051,7 @@ public void test061e() { "import java.io.FileInputStream;\n" + "import java.io.IOException;\n" + "public class X {\n" + + fieldDeclPrefix() + " FileInputStream fis;" + " void foo() throws IOException {\n" + " File file = new File(\"somefile\");\n" + @@ -2076,11 +2081,7 @@ public void test061e() { "}\n" }, "Got IO Exception", - null, - true, - null, - options, - null); + options); } // Bug 358903 - Filter practically unimportant resource leak warnings // Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly @@ -2434,6 +2435,7 @@ public void test061l() throws IOException { "import java.io.BufferedInputStream;\n" + "import java.io.IOException;\n" + "public class X {\n" + + fieldDeclPrefix() + " BufferedInputStream stream;\n" + " void foo(File file) throws IOException {\n" + " FileInputStream s = new FileInputStream(file);\n" + @@ -2442,11 +2444,7 @@ public void test061l() throws IOException { "}\n" }, "", - null, - true, - null, - options, - null); + options); } // Bug 361407 - Resource leak warning when resource is assigned to a field outside of constructor // a closeable is assigned to a field - constructor vs. method @@ -4224,6 +4222,7 @@ public void testBug395977() { "\n" + "public class WriterTest implements Runnable\n" + "{\n" + + fieldDeclPrefix() + " private BufferedWriter m_Writer;\n" + " \n" + " public void run()\n" + @@ -4266,11 +4265,7 @@ public void testBug395977() { "}" }, "", - null, - true, - null, - options, - null); + options); } //Bug 395977 - Resource leak warning behavior possibly incorrect for anonymous inner class @@ -4286,6 +4281,7 @@ public void testBug395977_1() { "\n" + "public class WriterTest implements Runnable\n" + "{\n" + + fieldDeclPrefix() + " private BufferedWriter m_Writer;\n" + " \n" + " public void run()\n" + @@ -4345,6 +4341,7 @@ public void testBug395977_1a() { "\n" + "public class WriterTest implements Runnable\n" + "{\n" + + fieldDeclPrefix() + " private BufferedWriter m_Writer;\n" + " \n" + " public void run()\n" + @@ -4411,6 +4408,7 @@ public void testBug395977_2() { "\n" + "public class WriterTest implements Runnable\n" + "{\n" + + fieldDeclPrefix() + " private BufferedWriter m_Writer;\n" + " \n" + " public void run()\n" + @@ -6170,22 +6168,12 @@ public void testBug552521() { " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + "Resource leak: \'\' is never closed\n" + "----------\n" + - "5. ERROR in EclipseBug552521getChannel.java (at line 60)\n" + + "5. ERROR in EclipseBug552521getChannel.java (at line 82)\n" + " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + "Resource leak: \'\' is never closed\n" + "----------\n" + - "6. ERROR in EclipseBug552521getChannel.java (at line 72)\n" + - " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" + - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + - "Resource leak: \'\' is never closed\n" + - "----------\n" + - "7. ERROR in EclipseBug552521getChannel.java (at line 82)\n" + - " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" + - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + - "Resource leak: \'\' is never closed\n" + - "----------\n" + - "8. ERROR in EclipseBug552521getChannel.java (at line 94)\n" + + "6. ERROR in EclipseBug552521getChannel.java (at line 94)\n" + " final FileChannel srcChannel = new FileInputStream (srcFile) .getChannel();\n" + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + "Resource leak: \'\' is never closed\n" + @@ -7185,38 +7173,37 @@ public void testGH2129() { runLeakTest( new String[] { "ExampleResourceLeakWarningInternalResource.java", - """ - import java.io.IOException; - import java.net.InetSocketAddress; - import java.net.SocketAddress; - - import javax.net.ssl.SSLContext; - import javax.net.ssl.SSLServerSocket; - import javax.net.ssl.SSLServerSocketFactory; - - public class ExampleResourceLeakWarningInternalResource implements AutoCloseable { - - private SSLServerSocket sslServerSocket; - - public ExampleResourceLeakWarningInternalResource(int aSecurePort, SSLContext aSSLContext) throws IOException { - sslServerSocket = initialise(aSSLContext, aSecurePort); - } - - private SSLServerSocket initialise(SSLContext aSSLContext, int aPort) throws IOException { - SSLServerSocketFactory secure_server_socket_factory = aSSLContext.getServerSocketFactory(); - // No warning here for Eclipse 2019.06 but warnings for Eclipse 2020.03 and later - SSLServerSocket server_secure_socket = (SSLServerSocket) secure_server_socket_factory.createServerSocket(); - SocketAddress endpoint = new InetSocketAddress(aPort); - server_secure_socket.bind(endpoint, 1); - - return server_secure_socket; - } - @Override - public void close() throws IOException { - sslServerSocket.close(); - } - } - """ + "import java.io.IOException;\n" + + "import java.net.InetSocketAddress;\n" + + "import java.net.SocketAddress;\n" + + "\n" + + "import javax.net.ssl.SSLContext;\n" + + "import javax.net.ssl.SSLServerSocket;\n" + + "import javax.net.ssl.SSLServerSocketFactory;\n" + + "\n" + + "public class ExampleResourceLeakWarningInternalResource implements AutoCloseable {\n" + + "\n" + + fieldDeclPrefix() + + " private SSLServerSocket sslServerSocket;\n" + + "\n" + + " public ExampleResourceLeakWarningInternalResource(int aSecurePort, SSLContext aSSLContext) throws IOException {\n" + + " sslServerSocket = initialise(aSSLContext, aSecurePort);\n" + + " }\n" + + "\n" + + " private SSLServerSocket initialise(SSLContext aSSLContext, int aPort) throws IOException {\n" + + " SSLServerSocketFactory secure_server_socket_factory = aSSLContext.getServerSocketFactory();\n" + + " // No warning here for Eclipse 2019.06 but warnings for Eclipse 2020.03 and later\n" + + " SSLServerSocket server_secure_socket = (SSLServerSocket) secure_server_socket_factory.createServerSocket();\n" + + " SocketAddress endpoint = new InetSocketAddress(aPort);\n" + + " server_secure_socket.bind(endpoint, 1);\n" + + "\n" + + " return server_secure_socket;\n" + + " }\n" + + " @Override\n" + + " public void close() throws IOException {\n" + + " sslServerSocket.close();\n" + + " }\n" + + "}\n" }, "", options);