View | Details | Raw Unified | Return to bug 358903 | Differences between
and this patch

Collapse All | Expand All

(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java (-1 / +2 lines)
Lines 6020-6025 public void test0561_try_catch_unchecked_exception() { Link Here
6020
public void test0562_try_catch_unchecked_exception() {
6020
public void test0562_try_catch_unchecked_exception() {
6021
	Map options = getCompilerOptions();
6021
	Map options = getCompilerOptions();
6022
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.WARNING);
6022
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.WARNING);
6023
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
6023
	this.runNegativeTest(
6024
	this.runNegativeTest(
6024
		true,
6025
		true,
6025
		new String[] {
6026
		new String[] {
Lines 6042-6048 public void test0562_try_catch_unchecked_exception() { Link Here
6042
			"1. WARNING in X.java (at line 6)\n" +
6043
			"1. WARNING in X.java (at line 6)\n" +
6043
			"	o = new LineNumberReader(new FileReader(\"dummy\"));\n" +
6044
			"	o = new LineNumberReader(new FileReader(\"dummy\"));\n" +
6044
			"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
6045
			"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
6045
			"Resource leak: 'o' is never closed\n" +
6046
			"Potential resource leak: \'o\' may not be closed\n" +
6046
			"----------\n" +
6047
			"----------\n" +
6047
			"2. ERROR in X.java (at line 8)\n" +
6048
			"2. ERROR in X.java (at line 8)\n" +
6048
			"	o.toString();\n" +
6049
			"	o.toString();\n" +
(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java (+2973 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2011, 2012 GK Software AG and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Stephan Herrmann - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.core.tests.compiler.regression;
12
13
import java.io.IOException;
14
import java.net.URL;
15
import java.util.Map;
16
17
import junit.framework.Test;
18
19
import org.eclipse.core.runtime.FileLocator;
20
import org.eclipse.core.runtime.Path;
21
import org.eclipse.core.runtime.Platform;
22
import org.eclipse.jdt.core.JavaCore;
23
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
24
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
25
26
public class ResourceLeakTests extends AbstractRegressionTest {
27
28
static {
29
//	TESTS_NAMES = new String[] { "test061a"};
30
//	TESTS_NUMBERS = new int[] { 50 };
31
//	TESTS_RANGE = new int[] { 11, -1 };
32
}
33
public ResourceLeakTests(String name) {
34
	super(name);
35
}
36
public static Test suite() {
37
	return buildAllCompliancesTestSuite(ResourceLeakTests.class);
38
}
39
40
void runTestsExpectingErrorsOnlyIn17(String[] testFiles, String errorsIn17, Map options) {
41
	if (this.complianceLevel >= ClassFileConstants.JDK1_7)
42
		runNegativeTest(testFiles, errorsIn17, null, true, options);
43
	else
44
		runConformTest(testFiles, "", null, true, null, options, null);
45
}
46
47
// Bug 349326 - [1.7] new warning for missing try-with-resources
48
// a method uses an AutoCloseable without ever closing it.
49
public void test056() {
50
	Map options = getCompilerOptions();
51
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
52
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
53
	this.runNegativeTest(
54
		new String[] {
55
			"X.java",
56
			"import java.io.File;\n" +
57
			"import java.io.FileReader;\n" +
58
			"import java.io.IOException;\n" +
59
			"public class X {\n" +
60
			"    void foo() throws IOException {\n" +
61
			"        File file = new File(\"somefile\");\n" +
62
			"        FileReader fileReader = new FileReader(file);\n" +
63
// not invoking any methods on FileReader, try to avoid necessary call to superclass() in the compiler
64
//			"        char[] in = new char[50];\n" +
65
//			"        fileReader.read(in);\n" +
66
			"    }\n" +
67
			"    public static void main(String[] args) throws IOException {\n" +
68
			"        new X().foo();\n" +
69
			"    }\n" +
70
			"}\n"
71
		},
72
		"----------\n" +
73
		"1. ERROR in X.java (at line 7)\n" +
74
		"	FileReader fileReader = new FileReader(file);\n" +
75
		"	           ^^^^^^^^^^\n" +
76
		"Resource leak: 'fileReader' is never closed\n" +
77
		"----------\n",
78
		null,
79
		true,
80
		options);
81
}
82
// Bug 349326 - [1.7] new warning for missing try-with-resources
83
// a method uses an AutoCloseable and closes it but not protected by t-w-r nor regular try-finally
84
public void test056a() {
85
	Map options = getCompilerOptions();
86
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
87
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
88
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
89
	runTestsExpectingErrorsOnlyIn17(
90
		new String[] {
91
			"X.java",
92
			"import java.io.File;\n" +
93
			"import java.io.FileReader;\n" +
94
			"import java.io.IOException;\n" +
95
			"public class X {\n" +
96
			"    void foo() throws IOException {\n" +
97
			"        File file = new File(\"somefile\");\n" +
98
			"        FileReader fileReader = new FileReader(file);\n" +
99
			"        char[] in = new char[50];\n" +
100
			"        fileReader.read(in);\n" +
101
			"		 fileReader.close();\n" +
102
			"    }\n" +
103
			"}\n"
104
		},
105
		"----------\n" +
106
		"1. ERROR in X.java (at line 7)\n" +
107
		"	FileReader fileReader = new FileReader(file);\n" +
108
		"	           ^^^^^^^^^^\n" +
109
		"Resource 'fileReader' should be managed by try-with-resource\n" +
110
		"----------\n",
111
		options);
112
}
113
// Bug 349326 - [1.7] new warning for missing try-with-resources
114
// a method uses an AutoCloseable and closes it properly in a finally block
115
public void test056b() {
116
	Map options = getCompilerOptions();
117
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
118
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
119
	this.runConformTest(
120
		new String[] {
121
			"X.java",
122
			"import java.io.File;\n" +
123
			"import java.io.FileReader;\n" +
124
			"import java.io.IOException;\n" +
125
			"public class X {\n" +
126
			"    void foo() throws IOException {\n" +
127
			"        File file = new File(\"somefile\");\n" +
128
			"        FileReader fileReader = new FileReader(file);\n" +
129
			"        try {\n" +
130
			"            char[] in = new char[50];\n" +
131
			"            fileReader.read(in);\n" +
132
			"        } finally {\n" +
133
			"		     fileReader.close();\n" +
134
			"        }\n" +
135
			"    }\n" +
136
			"    public static void main(String[] args) {\n" +
137
			"        try {\n" +
138
			"            new X().foo();\n" +
139
			"        } catch (IOException ioex) {\n" +
140
			"            System.out.println(\"caught\");\n" +
141
			"        }\n" +
142
			"    }\n" +
143
			"}\n"
144
		},
145
		"caught", /*output*/
146
		null/*classLibs*/,
147
		true/*shouldFlush*/,
148
		null/*vmargs*/,
149
		options,
150
		null/*requestor*/);
151
}
152
// Bug 349326 - [1.7] new warning for missing try-with-resources
153
// a method uses an AutoCloseable properly within try-with-resources.
154
public void test056c() {
155
	if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // t-w-r used
156
	Map options = getCompilerOptions();
157
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
158
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
159
	this.runConformTest(
160
		new String[] {
161
			"X.java",
162
			"import java.io.File;\n" +
163
			"import java.io.FileReader;\n" +
164
			"import java.io.IOException;\n" +
165
			"public class X {\n" +
166
			"    void foo() throws IOException {\n" +
167
			"        File file = new File(\"somefile\");\n" +
168
			"        try (FileReader fileReader = new FileReader(file)) {\n" +
169
			"            char[] in = new char[50];\n" +
170
			"            fileReader.read(in);\n" +
171
			"		 }\n" +
172
			"    }\n" +
173
			"    public static void main(String[] args) {\n" +
174
			"        try {\n" +
175
			"            new X().foo();\n" +
176
			"        } catch (IOException ioex) {\n" +
177
			"            System.out.println(\"caught\");\n" +
178
			"        }\n" +
179
			"    }\n" +
180
			"}\n"
181
		},
182
		"caught", /*output*/
183
		null/*classLibs*/,
184
		true/*shouldFlush*/,
185
		null/*vmargs*/,
186
		options,
187
		null/*requestor*/);
188
}
189
// Bug 349326 - [1.7] new warning for missing try-with-resources
190
// a method uses two AutoCloseables (testing independent analysis)
191
//- one closeable may be unclosed at a conditional return
192
//- the other is only conditionally closed
193
public void test056d() {
194
	Map options = getCompilerOptions();
195
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
196
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
197
	this.runNegativeTest(
198
		new String[] {
199
			"X.java",
200
			"import java.io.File;\n" +
201
			"import java.io.FileReader;\n" +
202
			"import java.io.IOException;\n" +
203
			"public class X {\n" +
204
			"    void foo(boolean flag1, boolean flag2) throws IOException {\n" +
205
			"        File file = new File(\"somefile\");\n" +
206
			"        char[] in = new char[50];\n" +
207
			"        FileReader fileReader1 = new FileReader(file);\n" +
208
			"        fileReader1.read(in);\n" +
209
			"        FileReader fileReader2 = new FileReader(file);\n" +
210
			"        fileReader2.read(in);\n" +
211
			"        if (flag1) {\n" +
212
			"            fileReader2.close();\n" +
213
			"            return;\n" +
214
			"        } else if (flag2) {\n" +
215
			"            fileReader2.close();\n" +
216
			"        }\n" +
217
			"        fileReader1.close();\n" +
218
			"    }\n" +
219
			"    public static void main(String[] args) throws IOException {\n" +
220
			"        new X().foo(false, true);\n" +
221
			"    }\n" +
222
			"}\n"
223
		},
224
		"----------\n" +
225
		"1. WARNING in X.java (at line 10)\n" +
226
		"	FileReader fileReader2 = new FileReader(file);\n" +
227
		"	           ^^^^^^^^^^^\n" +
228
		"Potential resource leak: 'fileReader2' may not be closed\n" +
229
		"----------\n" +
230
		"2. ERROR in X.java (at line 14)\n" +
231
		"	return;\n" +
232
		"	^^^^^^^\n" +
233
		"Resource leak: 'fileReader1' is not closed at this location\n" +
234
		"----------\n",
235
		null,
236
		true,
237
		options);
238
}
239
// Bug 349326 - [1.7] new warning for missing try-with-resources
240
// a method uses two AutoCloseables (testing independent analysis)
241
//- one closeable may be unclosed at a conditional return
242
//- the other is only conditionally closed
243
public void test056d_suppress() {
244
	if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // annotations used
245
	Map options = getCompilerOptions();
246
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
247
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
248
	options.put(CompilerOptions.OPTION_SuppressOptionalErrors, CompilerOptions.ENABLED);
249
	this.runNegativeTest(
250
		new String[] {
251
			"X.java",
252
			"import java.io.File;\n" +
253
			"import java.io.FileReader;\n" +
254
			"import java.io.IOException;\n" +
255
			"public class X {\n" +
256
			"    void foo(boolean flag1, boolean flag2) throws IOException {\n" +
257
			"        @SuppressWarnings(\"resource\") File file = new File(\"somefile\"); // unnecessary suppress\n" +
258
			"        char[] in = new char[50];\n" +
259
			"        FileReader fileReader1 = new FileReader(file);\n" +
260
			"        fileReader1.read(in);\n" +
261
			"        @SuppressWarnings(\"resource\") FileReader fileReader2 = new FileReader(file); // useful suppress\n" +
262
			"        fileReader2.read(in);\n" +
263
			"        if (flag1) {\n" +
264
			"            fileReader2.close();\n" +
265
			"            return; // not suppressed\n" +
266
			"        } else if (flag2) {\n" +
267
			"            fileReader2.close();\n" +
268
			"        }\n" +
269
			"        fileReader1.close();\n" +
270
			"    }\n" +
271
			"    @SuppressWarnings(\"resource\") // useful suppress\n" +
272
			"    void bar() throws IOException {\n" +
273
			"        File file = new File(\"somefile\");\n" +
274
			"        FileReader fileReader = new FileReader(file);\n" +
275
			"        char[] in = new char[50];\n" +
276
			"        fileReader.read(in);\n" +
277
			"    }\n" +
278
			"    public static void main(String[] args) throws IOException {\n" +
279
			"        new X().foo(false, true);\n" +
280
			"    }\n" +
281
			"}\n"
282
		},
283
		"----------\n" +
284
		"1. WARNING in X.java (at line 6)\n" +
285
		"	@SuppressWarnings(\"resource\") File file = new File(\"somefile\"); // unnecessary suppress\n" +
286
		"	                  ^^^^^^^^^^\n" +
287
		"Unnecessary @SuppressWarnings(\"resource\")\n" +
288
		"----------\n" +
289
		"2. ERROR in X.java (at line 14)\n" +
290
		"	return; // not suppressed\n" +
291
		"	^^^^^^^\n" +
292
		"Resource leak: 'fileReader1' is not closed at this location\n" +
293
		"----------\n",
294
		null,
295
		true,
296
		options);
297
}
298
// Bug 349326 - [1.7] new warning for missing try-with-resources
299
// Bug 362332 - Only report potential leak when closeable not created in the local scope
300
// one method returns an AutoCleasble, a second method uses this object without ever closing it.
301
public void test056e() {
302
	Map options = getCompilerOptions();
303
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
304
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
305
	this.runNegativeTest(
306
		new String[] {
307
			"X.java",
308
			"import java.io.File;\n" +
309
			"import java.io.FileReader;\n" +
310
			"import java.io.IOException;\n" +
311
			"public class X {\n" +
312
			"    FileReader getReader(String filename) throws IOException {\n" +
313
			"        File file = new File(\"somefile\");\n" +
314
			"        FileReader fileReader = new FileReader(file);\n" +
315
			"        return fileReader;\n" + 		// don't complain here, pass responsibility to caller
316
			"    }\n" +
317
			"    void foo() throws IOException {\n" +
318
			"        FileReader reader = getReader(\"somefile\");\n" +
319
			"        char[] in = new char[50];\n" +
320
			"        reader.read(in);\n" +
321
			"    }\n" +
322
			"    public static void main(String[] args) throws IOException {\n" +
323
			"        new X().foo();\n" +
324
			"    }\n" +
325
			"}\n"
326
		},
327
		"----------\n" +
328
		"1. ERROR in X.java (at line 11)\n" +
329
		"	FileReader reader = getReader(\"somefile\");\n" +
330
		"	           ^^^^^^\n" +
331
		"Potential resource leak: \'reader\' may not be closed\n" +
332
		"----------\n",
333
		null,
334
		true,
335
		options);
336
}
337
// Bug 349326 - [1.7] new warning for missing try-with-resources
338
// a method explicitly closes its AutoCloseable rather than using t-w-r
339
public void test056f() {
340
	Map options = getCompilerOptions();
341
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
342
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
343
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
344
	runTestsExpectingErrorsOnlyIn17(
345
		new String[] {
346
			"X.java",
347
			"import java.io.File;\n" +
348
			"import java.io.FileReader;\n" +
349
			"import java.io.IOException;\n" +
350
			"public class X {\n" +
351
			"    void foo() throws IOException {\n" +
352
			"        File file = new File(\"somefile\");\n" +
353
			"        FileReader fileReader = null;\n" +
354
			"        try {\n" +
355
			"            fileReader = new FileReader(file);\n" +
356
			"            char[] in = new char[50];\n" +
357
			"            fileReader.read(in);\n" +
358
			"        } finally {\n" +
359
			"            fileReader.close();\n" +
360
			"        }\n" +
361
			"    }\n" +
362
			"}\n"
363
		},
364
		"----------\n" +
365
		"1. ERROR in X.java (at line 7)\n" +
366
		"	FileReader fileReader = null;\n" +
367
		"	           ^^^^^^^^^^\n" +
368
		"Resource 'fileReader' should be managed by try-with-resource\n" +
369
		"----------\n",
370
		options);
371
}
372
// Bug 349326 - [1.7] new warning for missing try-with-resources
373
// an AutoCloseable local is re-assigned
374
public void test056g() {
375
	Map options = getCompilerOptions();
376
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
377
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
378
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
379
	this.runNegativeTest(
380
		new String[] {
381
			"X.java",
382
			"import java.io.File;\n" +
383
			"import java.io.FileReader;\n" +
384
			"import java.io.IOException;\n" +
385
			"public class X {\n" +
386
			"    void foo() throws IOException {\n" +
387
			"        File file = new File(\"somefile\");\n" +
388
			"        FileReader fileReader = new FileReader(file);\n" +
389
			"        char[] in = new char[50];\n" +
390
			"        fileReader.read(in);\n" +
391
			"        fileReader = new FileReader(file);\n" +
392
			"        fileReader.read(in);\n" +
393
			"        fileReader.close();\n" +
394
			"        fileReader = null;\n" +
395
			"    }\n" +
396
			"    public static void main(String[] args) throws IOException {\n" +
397
			"        new X().foo();\n" +
398
			"    }\n" +
399
			"}\n"
400
		},
401
		"----------\n" +
402
		"1. ERROR in X.java (at line 10)\n" +
403
		"	fileReader = new FileReader(file);\n" +
404
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
405
		"Resource leak: 'fileReader' is not closed at this location\n" +
406
		"----------\n",
407
		null,
408
		true,
409
		options);
410
}
411
// Bug 349326 - [1.7] new warning for missing try-with-resources
412
// an AutoCloseable local is re-assigned after null-assigned
413
public void test056g2() {
414
	Map options = getCompilerOptions();
415
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
416
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
417
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
418
	this.runNegativeTest(
419
		new String[] {
420
			"X.java",
421
			"import java.io.File;\n" +
422
			"import java.io.FileReader;\n" +
423
			"import java.io.IOException;\n" +
424
			"public class X {\n" +
425
			"    void foo() throws IOException {\n" +
426
			"        File file = new File(\"somefile\");\n" +
427
			"        FileReader fileReader = new FileReader(file);\n" +
428
			"        char[] in = new char[50];\n" +
429
			"        fileReader.read(in);\n" +
430
			"        fileReader = null;\n" +
431
			"        fileReader = new FileReader(file);\n" + // don't complain again, fileReader is null, so nothing can leak here
432
			"        fileReader.read(in);\n" +
433
			"        fileReader.close();\n" +
434
			"    }\n" +
435
			"    public static void main(String[] args) throws IOException {\n" +
436
			"        new X().foo();\n" +
437
			"    }\n" +
438
			"}\n"
439
		},
440
		"----------\n" +
441
		"1. ERROR in X.java (at line 10)\n" +
442
		"	fileReader = null;\n" +
443
		"	^^^^^^^^^^^^^^^^^\n" +
444
		"Resource leak: 'fileReader' is not closed at this location\n" +
445
		"----------\n",
446
		null,
447
		true,
448
		options);
449
}
450
// Bug 349326 - [1.7] new warning for missing try-with-resources
451
// two AutoCloseables at different nesting levels (anonymous local type)
452
public void test056h() {
453
	Map options = getCompilerOptions();
454
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
455
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
456
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
457
	this.runNegativeTest(
458
		new String[] {
459
			"X.java",
460
			"import java.io.File;\n" +
461
			"import java.io.FileReader;\n" +
462
			"import java.io.IOException;\n" +
463
			"public class X {\n" +
464
			"    void foo() throws IOException {\n" +
465
			"        final File file = new File(\"somefile\");\n" +
466
			"        final FileReader fileReader = new FileReader(file);\n" +
467
			"        char[] in = new char[50];\n" +
468
			"        fileReader.read(in);\n" +
469
			"        new Runnable() {\n public void run() {\n" +
470
			"            try {\n" +
471
			"                fileReader.close();\n" +
472
			"                FileReader localReader = new FileReader(file);\n" +
473
			"            } catch (IOException ex) { /* nop */ }\n" +
474
			"        }}.run();\n" +
475
			"    }\n" +
476
			"    public static void main(String[] args) throws IOException {\n" +
477
			"        new X().foo();\n" +
478
			"    }\n" +
479
			"}\n"
480
		},
481
		"----------\n" +
482
		"1. WARNING in X.java (at line 7)\n" +
483
		"	final FileReader fileReader = new FileReader(file);\n" +
484
		"	                 ^^^^^^^^^^\n" +
485
		"Potential resource leak: 'fileReader' may not be closed\n" +
486
		"----------\n" +
487
		"2. ERROR in X.java (at line 14)\n" +
488
		"	FileReader localReader = new FileReader(file);\n" +
489
		"	           ^^^^^^^^^^^\n" +
490
		"Resource leak: 'localReader' is never closed\n" +
491
		"----------\n",
492
		null,
493
		true,
494
		options);
495
}
496
// Bug 349326 - [1.7] new warning for missing try-with-resources
497
// three AutoCloseables in different blocks of the same method
498
public void test056i() {
499
	Map options = getCompilerOptions();
500
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
501
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
502
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
503
	this.runNegativeTest(
504
		new String[] {
505
			"X.java",
506
			"import java.io.File;\n" +
507
			"import java.io.FileReader;\n" +
508
			"import java.io.IOException;\n" +
509
			"public class X {\n" +
510
			"    void foo(boolean f1, boolean f2) throws IOException {\n" +
511
			"        File file = new File(\"somefile\");\n" +
512
			"        if (f1) {\n" +
513
			"            FileReader fileReader = new FileReader(file); // err: not closed\n" +
514
			"            char[] in = new char[50];\n" +
515
			"            fileReader.read(in);\n" +
516
			"            while (true) {\n" +
517
			"                 FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" +
518
			"                 loopReader.close();" +
519
			"                 break;\n" +
520
			"            }\n" +
521
			"        } else {\n" +
522
			"            FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
523
			"            if (f2)\n" +
524
			"                fileReader.close();\n" +
525
			"        }\n" +
526
			"    }\n" +
527
			"    public static void main(String[] args) throws IOException {\n" +
528
			"        new X().foo(true, true);\n" +
529
			"    }\n" +
530
			"}\n"
531
		},
532
		"----------\n" +
533
		"1. ERROR in X.java (at line 8)\n" +
534
		"	FileReader fileReader = new FileReader(file); // err: not closed\n" +
535
		"	           ^^^^^^^^^^\n" +
536
		"Resource leak: 'fileReader' is never closed\n" +
537
		"----------\n" +
538
		"2. WARNING in X.java (at line 16)\n" +
539
		"	FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
540
		"	           ^^^^^^^^^^\n" +
541
		"Potential resource leak: 'fileReader' may not be closed\n" +
542
		"----------\n",
543
		null,
544
		true,
545
		options);
546
}
547
// Bug 349326 - [1.7] new warning for missing try-with-resources
548
// three AutoCloseables in different blocks of the same method - problems ignored
549
public void test056i_ignore() {
550
	Map options = getCompilerOptions();
551
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.IGNORE);
552
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.IGNORE);
553
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
554
	this.runConformTest(
555
		new String[] {
556
			"X.java",
557
			"import java.io.File;\n" +
558
			"import java.io.FileReader;\n" +
559
			"import java.io.IOException;\n" +
560
			"public class X {\n" +
561
			"    void foo(boolean f1, boolean f2) throws IOException {\n" +
562
			"        File file = new File(\"somefile\");\n" +
563
			"        if (f1) {\n" +
564
			"            FileReader fileReader = new FileReader(file); // err: not closed\n" +
565
			"            char[] in = new char[50];\n" +
566
			"            fileReader.read(in);\n" +
567
			"            while (true) {\n" +
568
			"                 FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" +
569
			"                 loopReader.close();" +
570
			"                 break;\n" +
571
			"            }\n" +
572
			"        } else {\n" +
573
			"            FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
574
			"            if (f2)\n" +
575
			"                fileReader.close();\n" +
576
			"        }\n" +
577
			"    }\n" +
578
			"}\n"
579
		},
580
		"",
581
		null,
582
		true,
583
		null,
584
		options,
585
		null);
586
}
587
// Bug 349326 - [1.7] new warning for missing try-with-resources
588
// three AutoCloseables in different blocks of the same method
589
public void test056i2() {
590
	Map options = getCompilerOptions();
591
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
592
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
593
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
594
	this.runNegativeTest(
595
		new String[] {
596
			"X.java",
597
			"import java.io.File;\n" +
598
			"import java.io.FileReader;\n" +
599
			"import java.io.IOException;\n" +
600
			"public class X {\n" +
601
			"    void foo(boolean f1, boolean f2) throws IOException {\n" +
602
			"        File file = new File(\"somefile\");\n" +
603
			"        if (f1) {\n" +
604
			"            FileReader fileReader = new FileReader(file); // properly closed\n" +
605
			"            char[] in = new char[50];\n" +
606
			"            fileReader.read(in);\n" +
607
			"            while (true) {\n" +
608
			"                  fileReader.close();\n" +
609
			"                  FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" +
610
			"                  loopReader.close();\n" +
611
			"                  break;\n" +
612
			"            }\n" +
613
			"        } else {\n" +
614
			"            FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
615
			"            if (f2)\n" +
616
			"                fileReader.close();\n" +
617
			"        }\n" +
618
			"    }\n" +
619
			"    public static void main(String[] args) throws IOException {\n" +
620
			"        new X().foo(true, true);\n" +
621
			"    }\n" +
622
			"}\n"
623
		},
624
		"----------\n" +
625
		"1. ERROR in X.java (at line 18)\n" +
626
		"	FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
627
		"	           ^^^^^^^^^^\n" +
628
		"Potential resource leak: 'fileReader' may not be closed\n" +
629
		"----------\n",
630
		null,
631
		true,
632
		options);
633
}
634
// Bug 349326 - [1.7] new warning for missing try-with-resources
635
// a method uses an AutoCloseable without closing it locally but passing as arg to another method
636
public void test056j() {
637
	Map options = getCompilerOptions();
638
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
639
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
640
	this.runNegativeTest(
641
		new String[] {
642
			"X.java",
643
			"import java.io.File;\n" +
644
			"import java.io.FileReader;\n" +
645
			"import java.io.IOException;\n" +
646
			"public class X {\n" +
647
			"    void foo() throws IOException {\n" +
648
			"        File file = new File(\"somefile\");\n" +
649
			"        FileReader fileReader = new FileReader(file);\n" +
650
			"        read(fileReader);\n" +
651
			"    }\n" +
652
			"    void read(FileReader reader) { }\n" +
653
			"    public static void main(String[] args) throws IOException {\n" +
654
			"        new X().foo();\n" +
655
			"    }\n" +
656
			"}\n"
657
		},
658
		"----------\n" +
659
		"1. ERROR in X.java (at line 7)\n" +
660
		"	FileReader fileReader = new FileReader(file);\n" +
661
		"	           ^^^^^^^^^^\n" +
662
		"Potential resource leak: 'fileReader' may not be closed\n" +
663
		"----------\n",
664
		null,
665
		true,
666
		options);
667
}
668
// Bug 349326 - [1.7] new warning for missing try-with-resources
669
// a method uses an AutoCloseable without closing it locally but passing as arg to another method
670
public void test056jconditional() {
671
	Map options = getCompilerOptions();
672
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
673
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
674
	this.runNegativeTest(
675
		new String[] {
676
			"X.java",
677
			"import java.io.File;\n" +
678
			"import java.io.FileReader;\n" +
679
			"import java.io.IOException;\n" +
680
			"public class X {\n" +
681
			"    void foo(boolean b) throws IOException {\n" +
682
			"        File file = new File(\"somefile\");\n" +
683
			"        FileReader fileReader = new FileReader(file);\n" +
684
			"        synchronized (b ? this : new X()) {\n" +
685
			"            new ReadDelegator(fileReader);\n" +
686
			"        }\n" +
687
			"    }\n" +
688
			"    class ReadDelegator { ReadDelegator(FileReader reader) { } }\n" +
689
			"    public static void main(String[] args) throws IOException {\n" +
690
			"        new X().foo(true);\n" +
691
			"    }\n" +
692
			"}\n"
693
		},
694
		"----------\n" +
695
		"1. ERROR in X.java (at line 7)\n" +
696
		"	FileReader fileReader = new FileReader(file);\n" +
697
		"	           ^^^^^^^^^^\n" +
698
		"Potential resource leak: 'fileReader' may not be closed\n" +
699
		"----------\n",
700
		null,
701
		true,
702
		options);
703
}
704
// Bug 349326 - [1.7] new warning for missing try-with-resources
705
// many locals, some are AutoCloseable.
706
// Unfortunately analysis cannot respect how exception exits may affect ra3 and rb3,
707
// doing so would create false positives.
708
public void test056k() {
709
	Map options = getCompilerOptions();
710
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
711
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
712
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
713
	String expectedProblems = this.complianceLevel < ClassFileConstants.JDK1_7 ?
714
				"----------\n" +
715
				"1. ERROR in X.java (at line 15)\n" +
716
				"	ra2 = new FileReader(file);\n" +
717
				"	^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
718
				"Resource leak: \'ra2\' is never closed\n" +
719
				"----------\n" +
720
				"2. ERROR in X.java (at line 28)\n" +
721
				"	rb2 = new FileReader(file);\n" +
722
				"	^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
723
				"Resource leak: \'rb2\' is never closed\n" +
724
				"----------\n"
725
			:
726
				"----------\n" +
727
				"1. ERROR in X.java (at line 12)\n" +
728
				"	FileReader ra1 = null, ra2 = null;\n" +
729
				"	           ^^^\n" +
730
				"Resource 'ra1' should be managed by try-with-resource\n" +
731
				"----------\n" +
732
				"2. ERROR in X.java (at line 15)\n" +
733
				"	ra2 = new FileReader(file);\n" +
734
				"	^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
735
				"Resource leak: 'ra2' is never closed\n" +
736
				"----------\n" +
737
				"3. ERROR in X.java (at line 16)\n" +
738
				"	FileReader ra3 = new FileReader(file);\n" +
739
				"	           ^^^\n" +
740
				"Resource 'ra3' should be managed by try-with-resource\n" +
741
				"----------\n" +
742
				"4. ERROR in X.java (at line 25)\n" +
743
				"	FileReader rb1 = null, rb2 = null;\n" +
744
				"	           ^^^\n" +
745
				"Resource 'rb1' should be managed by try-with-resource\n" +
746
				"----------\n" +
747
				"5. ERROR in X.java (at line 28)\n" +
748
				"	rb2 = new FileReader(file);\n" +
749
				"	^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
750
				"Resource leak: 'rb2' is never closed\n" +
751
				"----------\n" +
752
				"6. ERROR in X.java (at line 29)\n" +
753
				"	FileReader rb3 = new FileReader(file);\n" +
754
				"	           ^^^\n" +
755
				"Resource 'rb3' should be managed by try-with-resource\n" +
756
				"----------\n";
757
	this.runNegativeTest(
758
		new String[] {
759
			"X.java",
760
			"import java.io.File;\n" +
761
			"import java.io.FileReader;\n" +
762
			"import java.io.IOException;\n" +
763
			"public class X {\n" +
764
			"    void foo() throws IOException {\n" +
765
			"        int i01, i02, i03, i04, i05, i06, i07, i08, i09,\n" +
766
			"            i11, i12, i13, i14, i15, i16, i17, i18, i19,\n" +
767
			"            i21, i22, i23, i24, i25, i26, i27, i28, i29,\n" +
768
			"            i31, i32, i33, i34, i35, i36, i37, i38, i39,\n" +
769
			"            i41, i42, i43, i44, i45, i46, i47, i48, i49;\n" +
770
			"        File file = new File(\"somefile\");\n" +
771
			"        FileReader ra1 = null, ra2 = null;\n" +
772
			"        try {\n" +
773
			"            ra1 = new FileReader(file);\n" +
774
			"            ra2 = new FileReader(file);\n" +
775
			"            FileReader ra3 = new FileReader(file);\n" +
776
			"            char[] in = new char[50];\n" +
777
			"            ra1.read(in);\n" +
778
			"            ra2.read(in);\n" +
779
			"            ra3.close();\n" +
780
			"        } finally {\n" +
781
			"            ra1.close();\n" +
782
			"        }\n" +
783
			"        int i51, i52, i53, i54, i55, i56, i57, i58, i59, i60;\n" + // beyond this point locals are analyzed using extraBits
784
			"        FileReader rb1 = null, rb2 = null;\n" +
785
			"        try {\n" +
786
			"            rb1 = new FileReader(file);\n" +
787
			"            rb2 = new FileReader(file);\n" +
788
			"            FileReader rb3 = new FileReader(file);\n" +
789
			"            char[] in = new char[50];\n" +
790
			"            rb1.read(in);\n" +
791
			"            rb2.read(in);\n" +
792
			"            rb3.close();\n" +
793
			"        } finally {\n" +
794
			"            rb1.close();\n" +
795
			"        }\n" +
796
			"    }\n" +
797
			"    public static void main(String[] args) throws IOException {\n" +
798
			"        new X().foo();\n" +
799
			"    }\n" +
800
			"}\n"
801
		},
802
		expectedProblems,
803
		null,
804
		true,
805
		options);
806
}
807
// Bug 349326 - [1.7] new warning for missing try-with-resources
808
// various non-problems
809
public void test056l() {
810
	Map options = getCompilerOptions();
811
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
812
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
813
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
814
	String expectedProblems = this.complianceLevel >= ClassFileConstants.JDK1_7 ?
815
				"----------\n" +
816
				"1. ERROR in X.java (at line 8)\n" +
817
				"	FileReader fileReader = getReader();\n" +
818
				"	           ^^^^^^^^^^\n" +
819
				"Resource 'fileReader' should be managed by try-with-resource\n" +
820
				"----------\n" +
821
				"2. ERROR in X.java (at line 11)\n" +
822
				"	FileReader r3 = getReader();\n" +
823
				"	           ^^\n" +
824
				"Resource 'r3' should be managed by try-with-resource\n" +
825
				"----------\n" +
826
				"3. ERROR in X.java (at line 24)\n" +
827
				"	FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" +
828
				"	           ^^\n" +
829
				"Potential resource leak: 'r2' may not be closed\n" +
830
				"----------\n"
831
			:
832
				"----------\n" +
833
				"1. ERROR in X.java (at line 24)\n" +
834
				"	FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" +
835
				"	           ^^\n" +
836
				"Potential resource leak: 'r2' may not be closed\n" +
837
				"----------\n";
838
	this.runNegativeTest(
839
		new String[] {
840
			"X.java",
841
			"import java.io.File;\n" +
842
			"import java.io.FileReader;\n" +
843
			"import java.io.IOException;\n" +
844
			"public class X {\n" +
845
			"    X(FileReader r0) {}\n" + // don't complain against argument
846
			"    FileReader getReader() { return null; }\n" +
847
			"    void foo(FileReader r1) throws IOException {\n" +
848
			"        FileReader fileReader = getReader();\n" +
849
			"        if (fileReader == null)\n" +
850
			"            return;\n" + // don't complain, resource is actually null
851
			"        FileReader r3 = getReader();\n" +
852
			"        if (r3 == null)\n" +
853
			"            r3 = new FileReader(new File(\"absent\"));\n" + // don't complain, previous resource is actually null
854
			"        try {\n" +
855
			"            char[] in = new char[50];\n" +
856
			"            fileReader.read(in);\n" +
857
			"            r1.read(in);\n" +
858
			"        } finally {\n" +
859
			"            fileReader.close();\n" +
860
			"            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
861
			"        }\n" +
862
			"    }\n" +
863
			"    public static void main(String[] args) throws IOException {\n" +
864
			"        FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" +
865
			"        new X(r2).foo(new FileReader(new File(\"notthere\")));\n" +
866
			"    }\n" +
867
			"}\n"
868
		},
869
		expectedProblems,
870
		null,
871
		true,
872
		options);
873
}
874
// Bug 349326 - [1.7] new warning for missing try-with-resources
875
// nested try with early exit
876
public void test056m() {
877
	Map options = getCompilerOptions();
878
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
879
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
880
	this.runConformTest(
881
		new String[] {
882
			"X.java",
883
			"import java.io.File;\n" +
884
			"import java.io.FileReader;\n" +
885
			"import java.io.IOException;\n" +
886
			"public class X {\n" +
887
			"    void foo() {\n" +
888
			"        File file = new File(\"somefile\");" +
889
			"        try {\n" +
890
			"            FileReader fileReader = new FileReader(file);\n" +
891
			"            try {\n" +
892
			"                char[] in = new char[50];\n" +
893
			"                if (fileReader.read(in)==0)\n" +
894
			"                    return;\n" +
895
			"            } finally {\n" +
896
			"		         fileReader.close();\n" +
897
			"            }\n" +
898
			"        } catch (IOException e) {\n" +
899
			"            System.out.println(\"caught\");\n" +
900
			"        }\n" +
901
			"    }\n" +
902
			"    public static void main(String[] args) {\n" +
903
			"        new X().foo();\n" +
904
			"    }\n" +
905
			"}\n"
906
		},
907
		"caught", /*output*/
908
		null/*classLibs*/,
909
		true/*shouldFlush*/,
910
		null/*vmargs*/,
911
		options,
912
		null/*requestor*/);
913
}
914
// Bug 349326 - [1.7] new warning for missing try-with-resources
915
// nested try should not interfere with earlier analysis.
916
public void test056n() {
917
	Map options = getCompilerOptions();
918
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
919
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
920
	this.runConformTest(
921
		new String[] {
922
			"X.java",
923
			"import java.io.File;\n" +
924
			"import java.io.FileReader;\n" +
925
			"import java.io.IOException;\n" +
926
			"import java.io.FileNotFoundException;\n" +
927
			"public class X {\n" +
928
			"    void foo(File someFile, char[] buf) throws IOException {\n" +
929
			"		FileReader fr1 = new FileReader(someFile);\n" +
930
			"		try {\n" +
931
			"			fr1.read(buf);\n" +
932
			"		} finally {\n" +
933
			"			fr1.close();\n" +
934
			"		}\n" +
935
			"		try {\n" +
936
			"			FileReader fr3 = new FileReader(someFile);\n" +
937
			"			try {\n" +
938
			"			} finally {\n" +
939
			"				fr3.close();\n" +
940
			"			}\n" +
941
			"		} catch (IOException e) {\n" +
942
			"		}\n" +
943
			"	 }\n" +
944
			"    public static void main(String[] args) throws IOException {\n" +
945
			"        try {\n" +
946
			"            new X().foo(new File(\"missing\"), new char[100]);\n" +
947
			"        } catch (FileNotFoundException e) {\n" +
948
			"            System.out.println(\"caught\");\n" +
949
			"        }\n" +
950
			"    }\n" +
951
			"}\n"
952
		},
953
		"caught", /*output*/
954
		null/*classLibs*/,
955
		true/*shouldFlush*/,
956
		null/*vmargs*/,
957
		options,
958
		null/*requestor*/);
959
}
960
// Bug 349326 - [1.7] new warning for missing try-with-resources
961
// if close is guarded by null check this should still be recognized as definitely closed
962
public void test056o() {
963
	Map options = getCompilerOptions();
964
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
965
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
966
	this.runConformTest(
967
		new String[] {
968
			"X.java",
969
			"import java.io.File;\n" +
970
			"import java.io.FileReader;\n" +
971
			"import java.io.IOException;\n" +
972
			"import java.io.FileNotFoundException;\n" +
973
			"public class X {\n" +
974
			"    void foo(File someFile, char[] buf) throws IOException {\n" +
975
			"		FileReader fr1 = null;\n" +
976
			"		try {\n" +
977
			"           fr1 = new FileReader(someFile);" +
978
			"			fr1.read(buf);\n" +
979
			"		} finally {\n" +
980
			"			if (fr1 != null)\n" +
981
			"               try {\n" +
982
			"                   fr1.close();\n" +
983
			"               } catch (IOException e) { /*do nothing*/ }\n" +
984
			"		}\n" +
985
			"	 }\n" +
986
			"    public static void main(String[] args) throws IOException {\n" +
987
			"        try {\n" +
988
			"            new X().foo(new File(\"missing\"), new char[100]);\n" +
989
			"        } catch (FileNotFoundException e) {\n" +
990
			"            System.out.println(\"caught\");\n" +
991
			"        }\n" +
992
			"    }\n" +
993
			"}\n"
994
		},
995
		"caught", /*output*/
996
		null/*classLibs*/,
997
		true/*shouldFlush*/,
998
		null/*vmargs*/,
999
		options,
1000
		null/*requestor*/);
1001
}
1002
// Bug 349326 - [1.7] new warning for missing try-with-resources
1003
// Bug 362332 - Only report potential leak when closeable not created in the local scope
1004
// a method uses an AutoCloseable without ever closing it, type from a type variable
1005
public void test056p() {
1006
	if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // generics used
1007
	Map options = getCompilerOptions();
1008
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
1009
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
1010
	this.runNegativeTest(
1011
		new String[] {
1012
			"X.java",
1013
			"import java.io.File;\n" +
1014
			"import java.io.FileReader;\n" +
1015
			"import java.io.Reader;\n" +
1016
			"import java.io.IOException;\n" +
1017
			"public abstract class X <T extends Reader> {\n" +
1018
			"    void foo() throws IOException {\n" +
1019
			"        File file = new File(\"somefile\");\n" +
1020
			"        T fileReader = newReader(file);\n" +
1021
			"        char[] in = new char[50];\n" +
1022
			"        fileReader.read(in);\n" +
1023
			"    }\n" +
1024
			"    abstract T newReader(File file) throws IOException;\n" +
1025
			"    public static void main(String[] args) throws IOException {\n" +
1026
			"        new X<FileReader>() {\n" +
1027
			"            FileReader newReader(File f) throws IOException { return new FileReader(f); }\n" +
1028
			"        }.foo();\n" +
1029
			"    }\n" +
1030
			"}\n"
1031
		},
1032
		"----------\n" +
1033
		"1. ERROR in X.java (at line 8)\n" +
1034
		"	T fileReader = newReader(file);\n" +
1035
		"	  ^^^^^^^^^^\n" +
1036
		"Potential resource leak: \'fileReader\' may not be closed\n" +
1037
		"----------\n",
1038
		null,
1039
		true,
1040
		options);
1041
}
1042
// Bug 349326 - [1.7] new warning for missing try-with-resources
1043
// closed in dead code
1044
public void test056q() {
1045
	Map options = getCompilerOptions();
1046
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1047
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
1048
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
1049
	this.runNegativeTest(
1050
		new String[] {
1051
			"X.java",
1052
			"import java.io.File;\n" +
1053
			"import java.io.FileReader;\n" +
1054
			"import java.io.IOException;\n" +
1055
			"public class X {\n" +
1056
			"    void foo() throws IOException {\n" +
1057
			"        File file = new File(\"somefile\");\n" +
1058
			"        FileReader fileReader = new FileReader(file);\n" +
1059
			"        char[] in = new char[50];\n" +
1060
			"        fileReader.read(in);\n" +
1061
			"        if (2*2 == 4)\n" +
1062
			"        	return;\n" +
1063
			"        fileReader.close();\n" +
1064
			"    }\n" +
1065
			"    public static void main(String[] args) throws IOException {\n" +
1066
			"        new X().foo();\n" +
1067
			"    }\n" +
1068
			"}\n"
1069
		},
1070
		"----------\n" +
1071
		"1. ERROR in X.java (at line 7)\n" +
1072
		"	FileReader fileReader = new FileReader(file);\n" +
1073
		"	           ^^^^^^^^^^\n" +
1074
		"Resource leak: 'fileReader' is never closed\n" +
1075
		"----------\n" +
1076
		"2. WARNING in X.java (at line 10)\n" +
1077
		"	if (2*2 == 4)\n" +
1078
		"	    ^^^^^^^^\n" +
1079
		"Comparing identical expressions\n" +
1080
		"----------\n" +
1081
		"3. WARNING in X.java (at line 12)\n" +
1082
		"	fileReader.close();\n" +
1083
		"	^^^^^^^^^^^^^^^^^^\n" +
1084
		"Dead code\n" +
1085
		"----------\n",
1086
		null,
1087
		true,
1088
		options);
1089
}
1090
// Bug 349326 - [1.7] new warning for missing try-with-resources
1091
// properly closed, dead code in between
1092
public void test056r() {
1093
	Map options = getCompilerOptions();
1094
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1095
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
1096
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
1097
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1098
	this.runNegativeTest(
1099
		new String[] {
1100
			"X.java",
1101
			"import java.io.File;\n" +
1102
			"import java.io.FileReader;\n" +
1103
			"import java.io.IOException;\n" +
1104
			"public class X {\n" +
1105
			"    void foo() throws IOException {\n" +
1106
			"        File file = new File(\"somefile\");\n" +
1107
			"        FileReader fr = new FileReader(file);\n" +
1108
			"  		 Object b = null;\n" +
1109
			"        fr.close();\n" +
1110
			"        if (b != null) {\n" +
1111
			"            fr = new FileReader(file);\n" +
1112
			"            return;\n" +
1113
			"        } else {\n" +
1114
			"            System.out.print(42);\n" +
1115
			"        }\n" +
1116
			"        return;     // Should not complain about fr\n" +
1117
			"    }\n" +
1118
			"    public static void main(String[] args) throws IOException {\n" +
1119
			"        new X().foo();\n" +
1120
			"    }\n" +
1121
			"}\n"
1122
		},
1123
		"----------\n" +
1124
		"1. ERROR in X.java (at line 10)\n" +
1125
		"	if (b != null) {\n" +
1126
		"            fr = new FileReader(file);\n" +
1127
		"            return;\n" +
1128
		"        } else {\n" +
1129
		"	               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
1130
		"Dead code\n" +
1131
		"----------\n" +
1132
		"2. WARNING in X.java (at line 13)\n" +
1133
		"	} else {\n" +
1134
		"            System.out.print(42);\n" +
1135
		"        }\n" +
1136
		"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
1137
		"Statement unnecessarily nested within else clause. The corresponding then clause does not complete normally\n" +
1138
		"----------\n",
1139
		null,
1140
		true,
1141
		options);
1142
}
1143
// Bug 349326 - [1.7] new warning for missing try-with-resources
1144
// resource inside t-w-r is re-assigned, shouldn't even record an errorLocation
1145
public void test056s() {
1146
	if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // t-w-r used
1147
	Map options = getCompilerOptions();
1148
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1149
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
1150
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
1151
	this.runNegativeTest(
1152
		new String[] {
1153
			"X.java",
1154
			"import java.io.File;\n" +
1155
			"import java.io.FileReader;\n" +
1156
			"import java.io.IOException;\n" +
1157
			"public class X {\n" +
1158
			"    void foo() throws IOException {\n" +
1159
			"        File file = new File(\"somefile\");\n" +
1160
			"        try (FileReader fileReader = new FileReader(file);) {\n" +
1161
			"            char[] in = new char[50];\n" +
1162
			"            fileReader.read(in);\n" +
1163
			"            fileReader = new FileReader(file);  // debug here\n" +
1164
			"            fileReader.read(in);\n" +
1165
			"        }\n" +
1166
			"    }\n" +
1167
			"    public static void main(String[] args) throws IOException {\n" +
1168
			"        new X().foo();\n" +
1169
			"    }\n" +
1170
			"}\n"
1171
		},
1172
		"----------\n" +
1173
		"1. ERROR in X.java (at line 10)\n" +
1174
		"	fileReader = new FileReader(file);  // debug here\n" +
1175
		"	^^^^^^^^^^\n" +
1176
		"The resource fileReader of a try-with-resources statement cannot be assigned\n" +
1177
		"----------\n",
1178
		null,
1179
		true,
1180
		options);
1181
}
1182
// Bug 349326 - [1.7] new warning for missing try-with-resources
1183
// resource is closed, dead code follows
1184
public void test056t() {
1185
	Map options = getCompilerOptions();
1186
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1187
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
1188
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1189
	this.runNegativeTest(
1190
		new String[] {
1191
			"X.java",
1192
			"import java.io.FileReader;\n" +
1193
			"import java.io.IOException;\n" +
1194
			"public class X {\n" +
1195
			"    void foo31() throws IOException {\n" +
1196
			"        FileReader reader = new FileReader(\"file\"); //warning\n" +
1197
			"        if (reader != null) {\n" +
1198
			"            reader.close();\n" +
1199
			"        } else {\n" +
1200
			"            // nop\n" +
1201
			"        }\n" +
1202
			"    }\n" +
1203
			"    public static void main(String[] args) throws IOException {\n" +
1204
			"        new X().foo31();\n" +
1205
			"    }\n" +
1206
			"}\n"
1207
		},
1208
		"----------\n" +
1209
		"1. ERROR in X.java (at line 8)\n" +
1210
		"	} else {\n" +
1211
		"            // nop\n" +
1212
		"        }\n" +
1213
		"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
1214
		"Dead code\n" +
1215
		"----------\n",
1216
		null,
1217
		true,
1218
		options);
1219
}
1220
// Bug 349326 - [1.7] new warning for missing try-with-resources
1221
// resource is reassigned within t-w-r with different resource
1222
// was initially broken due to https://bugs.eclipse.org/358827
1223
public void test056u() {
1224
	if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // t-w-r used
1225
	Map options = getCompilerOptions();
1226
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1227
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
1228
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1229
	this.runNegativeTest(
1230
		new String[] {
1231
			"X.java",
1232
			"import java.io.FileReader;\n" +
1233
			"public class X {\n" +
1234
			"    void foo() throws Exception {\n" +
1235
			"        FileReader reader1 = new FileReader(\"file1\");\n" +
1236
			"        FileReader reader2 = new FileReader(\"file2\");\n" +
1237
			"        reader2 = reader1;// this disconnects reader 2\n" +
1238
			"        try (FileReader reader3 = new FileReader(\"file3\")) {\n" +
1239
			"            int ch;\n" +
1240
			"            while ((ch = reader2.read()) != -1) {\n" +
1241
			"                System.out.println(ch);\n" +
1242
			"                reader1.read();\n" +
1243
			"            }\n" +
1244
			"            reader2 = reader1; // warning 1 regarding original reader1\n" + // this warning was missing
1245
			"            reader2 = reader1; // warning 2 regarding original reader1\n" +
1246
			"        } finally {\n" +
1247
			"            if (reader2 != null) {\n" +
1248
			"                reader2.close();\n" +
1249
			"            } else {\n" +
1250
			"                System.out.println();\n" +
1251
			"            }\n" +
1252
			"        }\n" +
1253
			"    }\n" +
1254
			"}\n"
1255
		},
1256
		"----------\n" +
1257
		"1. ERROR in X.java (at line 5)\n" +
1258
		"	FileReader reader2 = new FileReader(\"file2\");\n" +
1259
		"	           ^^^^^^^\n" +
1260
		"Resource leak: 'reader2' is never closed\n" +
1261
		"----------\n" +
1262
		"2. ERROR in X.java (at line 13)\n" +
1263
		"	reader2 = reader1; // warning 1 regarding original reader1\n" +
1264
		"	^^^^^^^^^^^^^^^^^\n" +
1265
		"Resource leak: 'reader1' is not closed at this location\n" +
1266
		"----------\n" +
1267
		"3. ERROR in X.java (at line 14)\n" +
1268
		"	reader2 = reader1; // warning 2 regarding original reader1\n" +
1269
		"	^^^^^^^^^^^^^^^^^\n" +
1270
		"Resource leak: 'reader1' is not closed at this location\n" +
1271
		"----------\n",
1272
		null,
1273
		true,
1274
		options);
1275
}
1276
// Bug 349326 - [1.7] new warning for missing try-with-resources
1277
// scope-related pbs reported in https://bugs.eclipse.org/349326#c70 and https://bugs.eclipse.org/349326#c82
1278
public void test056v() {
1279
	Map options = getCompilerOptions();
1280
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1281
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
1282
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.WARNING);
1283
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1284
	String expectedProblems = this.complianceLevel >= ClassFileConstants.JDK1_7 ?
1285
				"----------\n" +
1286
				"1. ERROR in X.java (at line 4)\n" +
1287
				"	FileReader reader = new FileReader(\"file\");\n" +
1288
				"	           ^^^^^^\n" +
1289
				"Resource leak: 'reader' is never closed\n" +
1290
				"----------\n" +
1291
				"2. WARNING in X.java (at line 19)\n" +
1292
				"	FileReader reader111 = new FileReader(\"file2\");\n" +
1293
				"	           ^^^^^^^^^\n" +
1294
				"Resource 'reader111' should be managed by try-with-resource\n" +
1295
				"----------\n" +
1296
				"3. ERROR in X.java (at line 42)\n" +
1297
				"	return;\n" +
1298
				"	^^^^^^^\n" +
1299
				"Resource leak: 'reader2' is not closed at this location\n" +
1300
				"----------\n"
1301
			:
1302
				"----------\n" +
1303
				"1. ERROR in X.java (at line 4)\n" +
1304
				"	FileReader reader = new FileReader(\"file\");\n" +
1305
				"	           ^^^^^^\n" +
1306
				"Resource leak: 'reader' is never closed\n" +
1307
				"----------\n" +
1308
				"2. ERROR in X.java (at line 42)\n" +
1309
				"	return;\n" +
1310
				"	^^^^^^^\n" +
1311
				"Resource leak: 'reader2' is not closed at this location\n" +
1312
				"----------\n";
1313
	this.runNegativeTest(
1314
		new String[] {
1315
			"X.java",
1316
			"import java.io.FileReader;\n" +
1317
			"public class X {\n" +
1318
			"    boolean foo1() throws Exception {\n" +
1319
			"        FileReader reader = new FileReader(\"file\");\n" +
1320
			"        try {\n" +
1321
			"            int ch;\n" +
1322
			"            while ((ch = reader.read()) != -1) {\n" +
1323
			"                System.out.println(ch);\n" +
1324
			"                reader.read();\n" +
1325
			"            }\n" +
1326
			"            if (ch > 10) {\n" +
1327
			"                return true;\n" +
1328
			"            }\n" +
1329
			"            return false;\n" + // return while resource from enclosing scope remains unclosed
1330
			"        } finally {\n" +
1331
			"        }\n" +
1332
			"    }\n" +
1333
			"    void foo111() throws Exception {\n" +
1334
			"        FileReader reader111 = new FileReader(\"file2\");\n" +
1335
			"        try {\n" +
1336
			"            int ch;\n" +
1337
			"            while ((ch = reader111.read()) != -1) {\n" +
1338
			"                System.out.println(ch);\n" +
1339
			"                reader111.read();\n" +
1340
			"            }\n" +
1341
			"            return;\n" + // this shouldn't spoil the warning "should be managed with t-w-r"
1342
			"        } finally {\n" +
1343
			"            if (reader111 != null) {\n" +
1344
			"                reader111.close();\n" +
1345
			"            }\n" +
1346
			"        }\n" +
1347
			"    }\n" +
1348
			"    void foo2() throws Exception {\n" +
1349
			"        FileReader reader2 = new FileReader(\"file\");\n" +
1350
			"        try {\n" +
1351
			"            int ch;\n" +
1352
			"            while ((ch = reader2.read()) != -1) {\n" +
1353
			"                System.out.println(ch);\n" +
1354
			"                reader2.read();\n" +
1355
			"            }\n" +
1356
			"            if (ch > 10) {\n" +
1357
			"                return;\n" + // potential leak
1358
			"            }\n" +
1359
			"        } finally {\n" +
1360
			"        }\n" +
1361
			"        reader2.close();\n" + // due to this close we don't say "never closed"
1362
			"    }\n" +
1363
			"}\n"
1364
		},
1365
		expectedProblems,
1366
		null,
1367
		true,
1368
		options);
1369
}
1370
// Bug 349326 - [1.7] new warning for missing try-with-resources
1371
// end of method is dead end, but before we have both a close() and an early return
1372
public void test056w() {
1373
	Map options = getCompilerOptions();
1374
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1375
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
1376
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1377
	this.runNegativeTest(
1378
		new String[] {
1379
			"X.java",
1380
			"import java.io.FileReader;\n" +
1381
			"public class X {\n" +
1382
			"    boolean foo1() throws Exception {\n" +
1383
			"        FileReader reader = new FileReader(\"file\");\n" +
1384
			"        try {\n" +
1385
			"            int ch;\n" +
1386
			"            while ((ch = reader.read()) != -1) {\n" +
1387
			"                System.out.println(ch);\n" +
1388
			"                reader.read();\n" +
1389
			"            }\n" +
1390
			"            if (ch > 10) {\n" +
1391
			"				 reader.close();\n" +
1392
			"                return true;\n" +
1393
			"            }\n" +
1394
			"            return false;\n" +
1395
			"        } finally {\n" +
1396
			"        }\n" +
1397
			"    }\n" +
1398
			"}\n"
1399
		},
1400
		"----------\n" +
1401
		"1. ERROR in X.java (at line 15)\n" +
1402
		"	return false;\n" +
1403
		"	^^^^^^^^^^^^^\n" +
1404
		"Resource leak: 'reader' is not closed at this location\n" +
1405
		"----------\n",
1406
		null,
1407
		true,
1408
		options);
1409
}
1410
// Bug 349326 - [1.7] new warning for missing try-with-resources
1411
// different early exits, if no close seen report as definitely unclosed
1412
public void test056x() {
1413
	Map options = getCompilerOptions();
1414
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1415
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
1416
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1417
	this.runNegativeTest(
1418
		new String[] {
1419
			"X.java",
1420
			"import java.io.FileReader;\n" +
1421
			"public class X {\n" +
1422
			"    void foo31(boolean b) throws Exception {\n" +
1423
			"        FileReader reader = new FileReader(\"file\");\n" +
1424
			"        if (b) {\n" +
1425
			"            reader.close();\n" +
1426
			"        } else {\n" +
1427
			"            return; // warning\n" +
1428
			"        }\n" +
1429
			"    }\n" +
1430
			"    void foo32(boolean b) throws Exception {\n" +
1431
			"        FileReader reader = new FileReader(\"file\"); // warn here\n" +
1432
			"        return;\n" +
1433
			"    }\n" +
1434
			"}\n"
1435
		},
1436
		"----------\n" +
1437
		"1. ERROR in X.java (at line 8)\n" +
1438
		"	return; // warning\n" +
1439
		"	^^^^^^^\n" +
1440
		"Resource leak: 'reader' is not closed at this location\n" +
1441
		"----------\n" +
1442
		"2. ERROR in X.java (at line 12)\n" +
1443
		"	FileReader reader = new FileReader(\"file\"); // warn here\n" +
1444
		"	           ^^^^^^\n" +
1445
		"Resource leak: 'reader' is never closed\n" +
1446
		"----------\n",
1447
		null,
1448
		true,
1449
		options);
1450
}
1451
// Bug 349326 - [1.7] new warning for missing try-with-resources
1452
// nested method passes the resource to outside code
1453
public void test056y() {
1454
	Map options = getCompilerOptions();
1455
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1456
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
1457
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1458
	this.runNegativeTest(
1459
		new String[] {
1460
			"X.java",
1461
			"import java.io.FileReader;\n" +
1462
			"public class X {\n" +
1463
			"    void foo31(boolean b) throws Exception {\n" +
1464
			"        final FileReader reader31 = new FileReader(\"file\");\n" +
1465
			"        new Runnable() {\n" +
1466
			"            public void run() {\n" +
1467
			"                foo18(reader31);\n" +
1468
			"            }\n" +
1469
			"        }.run();\n" +
1470
			"    }\n" +
1471
			"    void foo18(FileReader r18) {\n" +
1472
			"        // could theoretically close r18;\n" +
1473
			"    }\n" +
1474
			"    abstract class ResourceProvider {\n" +
1475
			"        abstract FileReader provide();" +
1476
			"    }\n" +
1477
			"    ResourceProvider provider;" +
1478
			"    void foo23() throws Exception {\n" +
1479
			"        final FileReader reader23 = new FileReader(\"file\");\n" +
1480
			"        provider = new ResourceProvider() {\n" +
1481
			"            public FileReader provide() {\n" +
1482
			"                return reader23;\n" +
1483
			"            }\n" +
1484
			"        };\n" +
1485
			"    }\n" +
1486
			"}\n"
1487
		},
1488
		"----------\n" +
1489
		"1. WARNING in X.java (at line 4)\n" +
1490
		"	final FileReader reader31 = new FileReader(\"file\");\n" +
1491
		"	                 ^^^^^^^^\n" +
1492
		"Potential resource leak: 'reader31' may not be closed\n" +
1493
		"----------\n" +
1494
		"2. WARNING in X.java (at line 17)\n" +
1495
		"	final FileReader reader23 = new FileReader(\"file\");\n" +
1496
		"	                 ^^^^^^^^\n" +
1497
		"Potential resource leak: 'reader23' may not be closed\n" +
1498
		"----------\n",
1499
		null,
1500
		true,
1501
		options);
1502
}
1503
// Bug 349326 - [1.7] new warning for missing try-with-resources
1504
// resource assigned to second local and is (potentially) closed on the latter
1505
public void test056z() {
1506
	Map options = getCompilerOptions();
1507
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1508
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1509
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1510
	this.runNegativeTest(
1511
		new String[] {
1512
			"X.java",
1513
			"import java.io.FileReader;\n" +
1514
			"public class X {\n" +
1515
			"    void foo17() throws Exception {\n" +
1516
			"        FileReader reader17 = new FileReader(\"file\");\n" +
1517
			"        final FileReader readerCopy = reader17;\n" +
1518
			"        readerCopy.close();\n" +
1519
			"    }\n" +
1520
			"    void foo17a() throws Exception {\n" +
1521
			"        FileReader reader17a = new FileReader(\"file\");\n" +
1522
			"        FileReader readerCopya;" +
1523
			"		 readerCopya = reader17a;\n" +
1524
			"        bar(readerCopya);\n" + // potentially closes
1525
			"    }\n" +
1526
			"    void bar(FileReader r) {}\n" +
1527
			"}\n"
1528
		},
1529
		"----------\n" +
1530
		"1. ERROR in X.java (at line 9)\n" +
1531
		"	FileReader reader17a = new FileReader(\"file\");\n" +
1532
		"	           ^^^^^^^^^\n" +
1533
		"Potential resource leak: 'reader17a' may not be closed\n" +
1534
		"----------\n",
1535
		null,
1536
		true,
1537
		options);
1538
}
1539
// Bug 349326 - [1.7] new warning for missing try-with-resources
1540
// multiple early exists from nested scopes (always closed)
1541
public void test056zz() {
1542
	Map options = getCompilerOptions();
1543
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1544
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1545
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
1546
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1547
	runTestsExpectingErrorsOnlyIn17(
1548
		new String[] {
1549
			"X.java",
1550
			"import java.io.FileReader;\n" +
1551
			"public class X {\n" +
1552
			"    void foo16() throws Exception {\n" +
1553
			"        FileReader reader16 = new FileReader(\"file\");\n" +
1554
			"        try {\n" +
1555
			"            reader16.close();\n " +
1556
			"            return;\n" +
1557
			"        } catch (RuntimeException re) {\n" +
1558
			"            return;\n" +
1559
			"        } catch (Error e) {\n" +
1560
			"            return;\n" +
1561
			"        } finally {\n" +
1562
			"            reader16.close();\n " +
1563
			"        }\n" +
1564
			"    }\n" +
1565
			"}\n"
1566
		},
1567
		"----------\n" +
1568
		"1. ERROR in X.java (at line 4)\n" +
1569
		"	FileReader reader16 = new FileReader(\"file\");\n" +
1570
		"	           ^^^^^^^^\n" +
1571
		"Resource 'reader16' should be managed by try-with-resource\n" +
1572
		"----------\n",
1573
		options);
1574
}
1575
// Bug 349326 - [1.7] new warning for missing try-with-resources
1576
// multiple early exists from nested scopes (never closed)
1577
public void test056zzz() {
1578
	Map options = getCompilerOptions();
1579
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1580
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1581
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
1582
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1583
	this.runNegativeTest(
1584
		new String[] {
1585
			"X.java",
1586
			"import java.io.FileReader;\n" +
1587
			"public class X {\n" +
1588
			"    void foo16() throws Exception {\n" +
1589
			"        FileReader reader16 = new FileReader(\"file\");\n" +
1590
			"        try {\n" +
1591
			"            return;\n" +
1592
			"        } catch (RuntimeException re) {\n" +
1593
			"            return;\n" +
1594
			"        } catch (Error e) {\n" +
1595
			"            return;\n" +
1596
			"        } finally {\n" +
1597
			"            System.out.println();\n " +
1598
			"        }\n" +
1599
			"    }\n" +
1600
			"}\n"
1601
		},
1602
		"----------\n" +
1603
		"1. ERROR in X.java (at line 4)\n" +
1604
		"	FileReader reader16 = new FileReader(\"file\");\n" +
1605
		"	           ^^^^^^^^\n" +
1606
		"Resource leak: 'reader16' is never closed\n" +
1607
		"----------\n",
1608
		null,
1609
		true,
1610
		options);
1611
}
1612
// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
1613
// explicit throw is a true method exit here
1614
public void test056throw1() {
1615
	Map options = getCompilerOptions();
1616
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1617
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1618
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
1619
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1620
	this.runNegativeTest(
1621
		new String[] {
1622
			"X.java",
1623
			"import java.io.FileReader;\n" +
1624
			"public class X {\n" +
1625
			"    void foo2(boolean a, boolean b, boolean c) throws Exception {\n" +
1626
			"        FileReader reader = new FileReader(\"file\");\n" +
1627
			"        if(a)\n" +
1628
			"            throw new Exception();    //warning 1\n" +
1629
			"        else if (b)\n" +
1630
			"            reader.close();\n" +
1631
			"        else if(c)\n" +
1632
			"            throw new Exception();    //warning 2\n" +
1633
			"        reader.close();\n" +
1634
			"    }\n" +
1635
			"}\n"
1636
		},
1637
		"----------\n" +
1638
		"1. ERROR in X.java (at line 6)\n" +
1639
		"	throw new Exception();    //warning 1\n" +
1640
		"	^^^^^^^^^^^^^^^^^^^^^^\n" +
1641
		"Resource leak: 'reader' is not closed at this location\n" +
1642
		"----------\n" +
1643
		"2. ERROR in X.java (at line 10)\n" +
1644
		"	throw new Exception();    //warning 2\n" +
1645
		"	^^^^^^^^^^^^^^^^^^^^^^\n" +
1646
		"Resource leak: 'reader' is not closed at this location\n" +
1647
		"----------\n",
1648
		null,
1649
		true,
1650
		options);
1651
}
1652
// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
1653
// close() within finally provides protection for throw
1654
public void test056throw2() {
1655
	Map options = getCompilerOptions();
1656
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1657
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1658
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
1659
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1660
	runTestsExpectingErrorsOnlyIn17(
1661
		new String[] {
1662
			"X.java",
1663
			"import java.io.FileReader;\n" +
1664
					"public class X {\n" +
1665
					"    void foo1() throws Exception {\n" +
1666
					"        FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
1667
					"        try {\n" +
1668
					"            reader.read();\n" +
1669
					"            return;\n" +
1670
					"        } catch (Exception e) {\n" +
1671
					"            throw new Exception();\n" +
1672
					"        } finally {\n" +
1673
					"            reader.close();\n" +
1674
					"        }\n" +
1675
					"    }\n" +
1676
					"\n" +
1677
					"    void foo2() throws Exception {\n" +
1678
					"        FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
1679
					"        try {\n" +
1680
					"            reader.read();\n" +
1681
					"            throw new Exception(); // should not warn here\n" +
1682
					"        } catch (Exception e) {\n" +
1683
					"            throw new Exception();\n" +
1684
					"        } finally {\n" +
1685
					"            reader.close();\n" +
1686
					"        }\n" +
1687
					"    }\n" +
1688
					"\n" +
1689
					"    void foo3() throws Exception {\n" +
1690
					"        FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
1691
					"        try {\n" +
1692
					"            reader.read();\n" +
1693
					"            throw new Exception();\n" +
1694
					"        } finally {\n" +
1695
					"            reader.close();\n" +
1696
					"        }\n" +
1697
					"    }\n" +
1698
					"}\n"
1699
			},
1700
			"----------\n" +
1701
			"1. ERROR in X.java (at line 4)\n" +
1702
			"	FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
1703
			"	           ^^^^^^\n" +
1704
			"Resource 'reader' should be managed by try-with-resource\n" +
1705
			"----------\n" +
1706
			"2. ERROR in X.java (at line 16)\n" +
1707
			"	FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
1708
			"	           ^^^^^^\n" +
1709
			"Resource 'reader' should be managed by try-with-resource\n" +
1710
			"----------\n" +
1711
			"3. ERROR in X.java (at line 28)\n" +
1712
			"	FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
1713
			"	           ^^^^^^\n" +
1714
			"Resource 'reader' should be managed by try-with-resource\n" +
1715
			"----------\n",
1716
			options);
1717
}
1718
// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
1719
// close() nested within finally provides protection for throw
1720
public void test056throw3() {
1721
	Map options = getCompilerOptions();
1722
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1723
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1724
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
1725
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1726
	runTestsExpectingErrorsOnlyIn17(
1727
		new String[] {
1728
			"X.java",
1729
			"import java.io.FileReader;\n" +
1730
			"public class X {\n" +
1731
			"    void foo2x() throws Exception {\n" +
1732
			"        FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
1733
			"        try {\n" +
1734
			"            reader.read();\n" +
1735
			"            throw new Exception(); // should not warn here\n" +
1736
			"        } catch (Exception e) {\n" +
1737
			"            throw new Exception();\n" +
1738
			"        } finally {\n" +
1739
			"            if (reader != null)\n" +
1740
			"                 try {\n" +
1741
			"                     reader.close();\n" +
1742
			"                 } catch (java.io.IOException io) {}\n" +
1743
			"        }\n" +
1744
			"    }\n" +
1745
			"}\n"
1746
		},
1747
		"----------\n" +
1748
		"1. ERROR in X.java (at line 4)\n" +
1749
		"	FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
1750
		"	           ^^^^^^\n" +
1751
		"Resource 'reader' should be managed by try-with-resource\n" +
1752
		"----------\n",
1753
		options);
1754
}
1755
// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
1756
// additional boolean should shed doubt on whether we reach the close() call
1757
public void test056throw4() {
1758
	Map options = getCompilerOptions();
1759
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1760
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1761
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
1762
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1763
	this.runNegativeTest(
1764
		new String[] {
1765
			"X.java",
1766
			"import java.io.FileReader;\n" +
1767
			"public class X {\n" +
1768
			"    void foo2x(boolean b) throws Exception {\n" +
1769
			"        FileReader reader = new FileReader(\"file\");\n" +
1770
			"        try {\n" +
1771
			"            reader.read();\n" +
1772
			"            throw new Exception(); // should warn here\n" +
1773
			"        } catch (Exception e) {\n" +
1774
			"            throw new Exception(); // should warn here\n" +
1775
			"        } finally {\n" +
1776
			"            if (reader != null && b)\n" + // this condition is too strong to protect reader
1777
			"                 try {\n" +
1778
			"                     reader.close();\n" +
1779
			"                 } catch (java.io.IOException io) {}\n" +
1780
			"        }\n" +
1781
			"    }\n" +
1782
			"}\n"
1783
		},
1784
		"----------\n" +
1785
		"1. ERROR in X.java (at line 7)\n" +
1786
		"	throw new Exception(); // should warn here\n" +
1787
		"	^^^^^^^^^^^^^^^^^^^^^^\n" +
1788
		"Potential resource leak: 'reader' may not be closed at this location\n" +
1789
		"----------\n" +
1790
		"2. ERROR in X.java (at line 9)\n" +
1791
		"	throw new Exception(); // should warn here\n" +
1792
		"	^^^^^^^^^^^^^^^^^^^^^^\n" +
1793
		"Potential resource leak: 'reader' may not be closed at this location\n" +
1794
		"----------\n",
1795
		null,
1796
		true,
1797
		options);
1798
}
1799
// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
1800
// similar to test056throw3() but indirectly calling close(), so doubts remain.
1801
public void test056throw5() {
1802
	Map options = getCompilerOptions();
1803
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1804
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
1805
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
1806
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
1807
	this.runNegativeTest(
1808
		new String[] {
1809
			"X.java",
1810
			"import java.io.FileReader;\n" +
1811
			"public class X {\n" +
1812
			"    void foo2x() throws Exception {\n" +
1813
			"        FileReader reader = new FileReader(\"file\");\n" +
1814
			"        try {\n" +
1815
			"            reader.read();\n" +
1816
			"            throw new Exception(); // should warn 'may not' here\n" +
1817
			"        } catch (Exception e) {\n" +
1818
			"            throw new Exception(); // should warn 'may not' here\n" +
1819
			"        } finally {\n" +
1820
			"            doClose(reader);\n" +
1821
			"        }\n" +
1822
			"    }\n" +
1823
			"    void doClose(FileReader r) { try { r.close(); } catch (java.io.IOException ex) {}}\n" +
1824
			"}\n"
1825
		},
1826
		"----------\n" +
1827
		"1. ERROR in X.java (at line 7)\n" +
1828
		"	throw new Exception(); // should warn \'may not\' here\n" +
1829
		"	^^^^^^^^^^^^^^^^^^^^^^\n" +
1830
		"Potential resource leak: 'reader' may not be closed at this location\n" +
1831
		"----------\n" +
1832
		"2. ERROR in X.java (at line 9)\n" +
1833
		"	throw new Exception(); // should warn \'may not\' here\n" +
1834
		"	^^^^^^^^^^^^^^^^^^^^^^\n" +
1835
		"Potential resource leak: 'reader' may not be closed at this location\n" +
1836
		"----------\n",
1837
		null,
1838
		true,
1839
		options);
1840
}
1841
// Bug 358903 - Filter practically unimportant resource leak warnings
1842
// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
1843
// a resource wrapper is not closed but the underlying resource is
1844
public void test061a() {
1845
	Map options = getCompilerOptions();
1846
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
1847
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
1848
	this.runConformTest(
1849
		new String[] {
1850
			"X.java",
1851
			"import java.io.File;\n" +
1852
			"import java.io.BufferedInputStream;\n" +
1853
			"import java.io.FileInputStream;\n" +
1854
			"import java.io.IOException;\n" +
1855
			"public class X {\n" +
1856
			"    void foo() throws IOException {\n" +
1857
			"        File file = new File(\"somefile\");\n" +
1858
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
1859
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
1860
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
1861
			"        System.out.println(bis.available());\n" +
1862
			"        fileStream.close();\n" +
1863
			"    }\n" +
1864
			"    void inline() throws IOException {\n" +
1865
			"        File file = new File(\"somefile\");\n" +
1866
			"        FileInputStream fileStream;\n" +
1867
			"        BufferedInputStream bis = new BufferedInputStream(fileStream = new FileInputStream(file));\n" +
1868
			"        System.out.println(bis.available());\n" +
1869
			"        fileStream.close();\n" +
1870
			"    }\n" +
1871
			"    public static void main(String[] args) throws IOException {\n" +
1872
			"        try {\n" +
1873
			"            new X().foo();\n" +
1874
			"        } catch (IOException ex) {" +
1875
			"            System.out.println(\"Got IO Exception\");\n" +
1876
			"        }\n" +
1877
			"    }\n" +
1878
			"}\n"
1879
		},
1880
		"Got IO Exception",
1881
		null,
1882
		true,
1883
		null,
1884
		options,
1885
		null);
1886
}
1887
// Bug 358903 - Filter practically unimportant resource leak warnings
1888
// a closeable without OS resource is not closed
1889
public void test061b() {
1890
	Map options = getCompilerOptions();
1891
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
1892
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
1893
	this.runConformTest(
1894
		new String[] {
1895
			"X.java",
1896
			"import java.io.StringReader;\n" +
1897
			"import java.io.IOException;\n" +
1898
			"public class X {\n" +
1899
			"    void foo() throws IOException {\n" +
1900
			"        StringReader string  = new StringReader(\"content\");\n" +
1901
			"        System.out.println(string.read());\n" +
1902
			"    }\n" +
1903
			"    public static void main(String[] args) throws IOException {\n" +
1904
			"        new X().foo();\n" +
1905
			"    }\n" +
1906
			"}\n"
1907
		},
1908
		"99", // character 'c'
1909
		null,
1910
		true,
1911
		null,
1912
		options,
1913
		null);
1914
}
1915
// Bug 358903 - Filter practically unimportant resource leak warnings
1916
// a resource wrapper is not closed but the underlying closeable is resource-free
1917
public void test061c() {
1918
	Map options = getCompilerOptions();
1919
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
1920
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
1921
	this.runConformTest(
1922
		new String[] {
1923
			"X.java",
1924
			"import java.io.BufferedReader;\n" +
1925
			"import java.io.StringReader;\n" +
1926
			"import java.io.IOException;\n" +
1927
			"public class X {\n" +
1928
			"    void foo() throws IOException {\n" +
1929
			"        StringReader input = new StringReader(\"content\");\n" +
1930
			"        BufferedReader br = new BufferedReader(input);\n" +
1931
			"        BufferedReader doubleWrap = new BufferedReader(br);\n" +
1932
			"        System.out.println(br.read());\n" +
1933
			"    }\n" +
1934
			"    void inline() throws IOException {\n" +
1935
			"        BufferedReader br = new BufferedReader(new StringReader(\"content\"));\n" +
1936
			"        System.out.println(br.read());\n" +
1937
			"    }\n" +
1938
			"    public static void main(String[] args) throws IOException {\n" +
1939
			"        new X().foo();\n" +
1940
			"    }\n" +
1941
			"}\n"
1942
		},
1943
		"99",
1944
		null,
1945
		true,
1946
		null,
1947
		options,
1948
		null);
1949
}
1950
// Bug 358903 - Filter practically unimportant resource leak warnings
1951
// a resource wrapper is not closed neither is the underlying resource
1952
public void test061d() {
1953
	Map options = getCompilerOptions();
1954
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
1955
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
1956
	this.runNegativeTest(
1957
		new String[] {
1958
			"X.java",
1959
			"import java.io.File;\n" +
1960
			"import java.io.BufferedInputStream;\n" +
1961
			"import java.io.FileInputStream;\n" +
1962
			"import java.io.IOException;\n" +
1963
			"public class X {\n" +
1964
			"    void foo() throws IOException {\n" +
1965
			"        File file = new File(\"somefile\");\n" +
1966
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
1967
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
1968
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
1969
			"        System.out.println(bis.available());\n" +
1970
			"    }\n" +
1971
			"    void inline() throws IOException {\n" +
1972
			"        File file = new File(\"somefile\");\n" +
1973
			"        BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(file));\n" +
1974
			"        System.out.println(bis2.available());\n" +
1975
			"    }\n" +
1976
			"    public static void main(String[] args) throws IOException {\n" +
1977
			"        try {\n" +
1978
			"            new X().foo();\n" +
1979
			"        } catch (IOException ex) {" +
1980
			"            System.out.println(\"Got IO Exception\");\n" +
1981
			"        }\n" +
1982
			"    }\n" +
1983
			"}\n"
1984
		},
1985
		"----------\n" +
1986
		"1. ERROR in X.java (at line 10)\n" +
1987
		"	BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
1988
		"	                    ^^^^^^^^^^\n" +
1989
		"Resource leak: \'doubleWrap\' is never closed\n" +
1990
		"----------\n" +
1991
		"2. ERROR in X.java (at line 15)\n" +
1992
		"	BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(file));\n" +
1993
		"	                    ^^^^\n" +
1994
		"Resource leak: \'bis2\' is never closed\n" +
1995
		"----------\n",
1996
		null,
1997
		true,
1998
		options);
1999
}
2000
// Bug 358903 - Filter practically unimportant resource leak warnings
2001
// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
2002
// a resource wrapper is closed closing also the underlying resource
2003
public void test061e() {
2004
	Map options = getCompilerOptions();
2005
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2006
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2007
	this.runConformTest(
2008
		new String[] {
2009
			"X.java",
2010
			"import java.io.File;\n" +
2011
			"import java.io.BufferedInputStream;\n" +
2012
			"import java.io.FileInputStream;\n" +
2013
			"import java.io.IOException;\n" +
2014
			"public class X {\n" +
2015
			"    FileInputStream fis;" +
2016
			"    void foo() throws IOException {\n" +
2017
			"        File file = new File(\"somefile\");\n" +
2018
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
2019
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
2020
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
2021
			"        System.out.println(bis.available());\n" +
2022
			"        bis.close();\n" +
2023
			"    }\n" +
2024
			"    void inline() throws IOException {\n" +
2025
			"        File file = new File(\"somefile\");\n" +
2026
			"        BufferedInputStream bis2 = new BufferedInputStream(fis = new FileInputStream(file));\n" + // field assignment
2027
			"        System.out.println(bis2.available());\n" +
2028
			"        bis2.close();\n" +
2029
			"        FileInputStream fileStream  = null;\n" +
2030
			"        BufferedInputStream bis3 = new BufferedInputStream(fileStream = new FileInputStream(file));\n" +
2031
			"        System.out.println(bis3.available());\n" +
2032
			"        bis3.close();\n" +
2033
			"    }\n" +
2034
			"    public static void main(String[] args) throws IOException {\n" +
2035
			"        try {\n" +
2036
			"            new X().foo();\n" +
2037
			"        } catch (IOException ex) {" +
2038
			"            System.out.println(\"Got IO Exception\");\n" +
2039
			"        }\n" +
2040
			"    }\n" +
2041
			"}\n"
2042
		},
2043
		"Got IO Exception",
2044
		null,
2045
		true,
2046
		null,
2047
		options,
2048
		null);
2049
}
2050
// Bug 358903 - Filter practically unimportant resource leak warnings
2051
// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
2052
// a resource wrapper is closed closing also the underlying resource - original test case
2053
public void test061f() throws IOException {
2054
	Map options = getCompilerOptions();
2055
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2056
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2057
	URL url = FileLocator.toFileURL(FileLocator.find(Platform.getBundle("org.eclipse.jdt.core.tests.compiler"), new Path("META-INF/MANIFEST.MF"), null));
2058
	this.runConformTest(
2059
		new String[] {
2060
			"X.java",
2061
			"import java.io.InputStream;\n" +
2062
			"import java.io.InputStreamReader;\n" +
2063
			"import java.io.BufferedReader;\n" +
2064
			"import java.io.IOException;\n" +
2065
			"import java.net.URL;\n" +
2066
			"public class X {\n" +
2067
			"    boolean loadURL(final URL url) throws IOException {\n" +
2068
			"        InputStream stream = null;\n" +
2069
			"        BufferedReader reader = null;\n" +
2070
			"        try {\n" +
2071
			"            stream = url.openStream();\n" +
2072
			"            reader = new BufferedReader(new InputStreamReader(stream));\n" +
2073
			"            System.out.println(reader.readLine());\n" +
2074
			"        } finally {\n" +
2075
			"            try {\n" +
2076
			"                if (reader != null)\n" +
2077
			"                    reader.close();\n" +
2078
			"            } catch (IOException x) {\n" +
2079
			"            }\n" +
2080
			"        }\n" +
2081
			"        return false; // 'stream' may not be closed at this location\n" +
2082
			"    }\n" +
2083
			"    public static void main(String[] args) throws IOException {\n" +
2084
			"        try {\n" +
2085
			"            new X().loadURL(new URL(\""+url.toString()+"\"));\n" +
2086
			"        } catch (IOException ex) {\n" +
2087
			"            System.out.println(\"Got IO Exception\"+ex);\n" +
2088
			"        }\n" +
2089
			"    }\n" +
2090
			"}\n"
2091
		},
2092
		"Manifest-Version: 1.0",
2093
		null,
2094
		true,
2095
		null,
2096
		options,
2097
		null);
2098
}
2099
// Bug 358903 - Filter practically unimportant resource leak warnings
2100
// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
2101
// a resource wrapper is closed closing also the underlying resource - from a real-world example
2102
public void test061f2() throws IOException {
2103
	Map options = getCompilerOptions();
2104
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2105
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2106
	this.runConformTest(
2107
		new String[] {
2108
			"X.java",
2109
			"import java.io.OutputStream;\n" +
2110
			"import java.io.FileOutputStream;\n" +
2111
			"import java.io.BufferedOutputStream;\n" +
2112
			"import java.io.IOException;\n" +
2113
			"public class X {\n" +
2114
			"    void zork() throws IOException {\n" +
2115
			"		try {\n" +
2116
			"			OutputStream os = null;\n" +
2117
			"			try {\n" +
2118
			"				os = new BufferedOutputStream(new FileOutputStream(\"somefile\"));\n" +
2119
			"				String externalForm = \"externalPath\";\n" +
2120
			"			} finally {\n" +
2121
			"				if (os != null)\n" +
2122
			"					os.close();\n" +
2123
			"			}\n" +
2124
			"		} catch (IOException e) {\n" +
2125
			"			e.printStackTrace();\n" +
2126
			"		}\n" +
2127
			"    }\n" +
2128
			"}\n"
2129
		},
2130
		"",
2131
		null,
2132
		true,
2133
		null,
2134
		options,
2135
		null);
2136
}
2137
// Bug 358903 - Filter practically unimportant resource leak warnings
2138
// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
2139
// a resource wrapper is sent to another method affecting also the underlying resource - from a real-world example
2140
public void test061f3() throws IOException {
2141
	Map options = getCompilerOptions();
2142
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2143
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2144
	this.runNegativeTest(
2145
		new String[] {
2146
			"X.java",
2147
			"import java.io.File;\n" +
2148
			"import java.io.FileInputStream;\n" +
2149
			"import java.io.FileNotFoundException;\n" +
2150
			"import java.io.InputStream;\n" +
2151
			"import java.io.BufferedInputStream;\n" +
2152
			"public class X {\n" +
2153
			"    String loadProfile(File profileFile) {\n" +
2154
			"		try {\n" +
2155
			"			InputStream stream = new BufferedInputStream(new FileInputStream(profileFile));\n" +
2156
			"			return loadProfile(stream);\n" +
2157
			"		} catch (FileNotFoundException e) {\n" +
2158
			"			//null\n" +
2159
			"		}\n" +
2160
			"		return null;\n" +
2161
			"	}\n" +
2162
			"	private String loadProfile(InputStream stream) {\n" +
2163
			"		return null;\n" +
2164
			"	}\n" +
2165
			"}\n"
2166
		},
2167
		"----------\n" +
2168
		"1. ERROR in X.java (at line 10)\n" +
2169
		"	return loadProfile(stream);\n" +
2170
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
2171
		"Potential resource leak: \'stream\' may not be closed at this location\n" +
2172
		"----------\n",
2173
		null,
2174
		true,
2175
		options);
2176
}
2177
// Bug 358903 - Filter practically unimportant resource leak warnings
2178
// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
2179
// Different points in a resource chain are closed
2180
public void test061g() {
2181
	Map options = getCompilerOptions();
2182
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2183
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2184
	this.runNegativeTest(
2185
		new String[] {
2186
			"X.java",
2187
			"import java.io.File;\n" +
2188
			"import java.io.BufferedInputStream;\n" +
2189
			"import java.io.FileInputStream;\n" +
2190
			"import java.io.IOException;\n" +
2191
			"public class X {\n" +
2192
			"    void closeMiddle() throws IOException {\n" +
2193
			"        File file = new File(\"somefile\");\n" +
2194
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
2195
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
2196
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
2197
			"        System.out.println(bis.available());\n" +
2198
			"        bis.close();\n" +
2199
			"    }\n" +
2200
			"    void closeOuter() throws IOException {\n" +
2201
			"        File file2 = new File(\"somefile\");\n" +
2202
			"        FileInputStream fileStream2  = new FileInputStream(file2);\n" +
2203
			"        BufferedInputStream bis2 = new BufferedInputStream(fileStream2);\n" +
2204
			"        BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" +
2205
			"        System.out.println(bis2.available());\n" +
2206
			"        doubleWrap2.close();\n" +
2207
			"    }\n" +
2208
			"    void neverClosed() throws IOException {\n" +
2209
			"        File file3 = new File(\"somefile\");\n" +
2210
			"        FileInputStream fileStream3  = new FileInputStream(file3);\n" +
2211
			"        BufferedInputStream bis3 = new BufferedInputStream(fileStream3);\n" +
2212
			"        BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" +
2213
			"        System.out.println(doubleWrap3.available());\n" +
2214
			"    }\n" +
2215
			"}\n"
2216
		},
2217
		"----------\n" +
2218
		"1. ERROR in X.java (at line 26)\n" +
2219
		"	BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" +
2220
		"	                    ^^^^^^^^^^^\n" +
2221
		"Resource leak: \'doubleWrap3\' is never closed\n" +
2222
		"----------\n",
2223
		null,
2224
		true,
2225
		options);
2226
}
2227
// Bug 358903 - Filter practically unimportant resource leak warnings
2228
// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
2229
// Different points in a resource chain are potentially closed
2230
public void test061h() {
2231
	Map options = getCompilerOptions();
2232
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2233
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2234
	this.runNegativeTest(
2235
		new String[] {
2236
			"X.java",
2237
			"import java.io.File;\n" +
2238
			"import java.io.BufferedInputStream;\n" +
2239
			"import java.io.FileInputStream;\n" +
2240
			"import java.io.IOException;\n" +
2241
			"public class X {\n" +
2242
			"    void closeMiddle(boolean b) throws IOException {\n" +
2243
			"        File file = new File(\"somefile\");\n" +
2244
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
2245
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
2246
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
2247
			"        System.out.println(bis.available());\n" +
2248
			"        if (b)\n" +
2249
			"            bis.close();\n" +
2250
			"    }\n" +
2251
			"    void closeOuter(boolean b) throws IOException {\n" +
2252
			"        File file2 = new File(\"somefile\");\n" +
2253
			"        FileInputStream fileStream2  = new FileInputStream(file2);\n" +
2254
			"        BufferedInputStream dummy;\n" +
2255
			"        BufferedInputStream bis2 = (dummy = new BufferedInputStream(fileStream2));\n" +
2256
			"        BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" +
2257
			"        System.out.println(bis2.available());\n" +
2258
			"        if (b)\n" +
2259
			"            doubleWrap2.close();\n" +
2260
			"    }\n" +
2261
			"    void potAndDef(boolean b) throws IOException {\n" +
2262
			"        File file3 = new File(\"somefile\");\n" +
2263
			"        FileInputStream fileStream3  = new FileInputStream(file3);\n" +
2264
			"        BufferedInputStream bis3 = new BufferedInputStream(fileStream3);\n" +
2265
			"        BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" +
2266
			"        System.out.println(doubleWrap3.available());\n" +
2267
			"        if (b) bis3.close();\n" +
2268
			"        fileStream3.close();\n" +
2269
			"    }\n" +
2270
			"}\n"
2271
		},
2272
		"----------\n" +
2273
		"1. ERROR in X.java (at line 10)\n" +
2274
		"	BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
2275
		"	                    ^^^^^^^^^^\n" +
2276
		"Potential resource leak: \'doubleWrap\' may not be closed\n" +
2277
		"----------\n" +
2278
		"2. ERROR in X.java (at line 20)\n" +
2279
		"	BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" +
2280
		"	                    ^^^^^^^^^^^\n" +
2281
		"Potential resource leak: \'doubleWrap2\' may not be closed\n" +
2282
		"----------\n",
2283
		null,
2284
		true,
2285
		options);
2286
}
2287
// Bug 358903 - Filter practically unimportant resource leak warnings
2288
// local var is re-used for two levels of wrappers
2289
public void test061i() {
2290
	Map options = getCompilerOptions();
2291
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2292
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2293
	this.runNegativeTest(
2294
		new String[] {
2295
			"X.java",
2296
			"import java.io.File;\n" +
2297
			"import java.io.InputStream;\n" +
2298
			"import java.io.BufferedInputStream;\n" +
2299
			"import java.io.FileInputStream;\n" +
2300
			"import java.io.IOException;\n" +
2301
			"public class X {\n" +
2302
			"    void closeMiddle() throws IOException {\n" +
2303
			"        File file = new File(\"somefile\");\n" +
2304
			"        InputStream stream  = new FileInputStream(file);\n" +
2305
			"        stream = new BufferedInputStream(stream);\n" +
2306
			"        InputStream middle;\n" +
2307
			"        stream = new BufferedInputStream(middle = stream);\n" +
2308
			"        System.out.println(stream.available());\n" +
2309
			"        middle.close();\n" +
2310
			"    }\n" +
2311
			"    void closeOuter() throws IOException {\n" +
2312
			"        File file = new File(\"somefile\");\n" +
2313
			"        InputStream stream2  = new FileInputStream(file);\n" +
2314
			"        stream2 = new BufferedInputStream(stream2);\n" +
2315
			"        stream2 = new BufferedInputStream(stream2);\n" +
2316
			"        System.out.println(stream2.available());\n" +
2317
			"        stream2.close();\n" +
2318
			"    }\n" +
2319
			"    void neverClosed() throws IOException {\n" +
2320
			"        File file = new File(\"somefile\");\n" +
2321
			"        InputStream stream3  = new FileInputStream(file);\n" +
2322
			"        stream3 = new BufferedInputStream(stream3);\n" +
2323
			"        stream3 = new BufferedInputStream(stream3);\n" +
2324
			"        System.out.println(stream3.available());\n" +
2325
			"    }\n" +
2326
			"}\n"
2327
		},
2328
		"----------\n" +
2329
		"1. ERROR in X.java (at line 26)\n" +
2330
		"	InputStream stream3  = new FileInputStream(file);\n" +
2331
		"	            ^^^^^^^\n" +
2332
		"Resource leak: \'stream3\' is never closed\n" +
2333
		"----------\n",
2334
		null,
2335
		true,
2336
		options);
2337
}
2338
// Bug 358903 - Filter practically unimportant resource leak warnings
2339
// self-wrapping a method argument (caused NPE UnconditionalFlowInfo.markAsDefinitelyNull(..)).
2340
public void test061j() {
2341
	Map options = getCompilerOptions();
2342
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2343
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2344
	this.runConformTest(
2345
		new String[] {
2346
			"X.java",
2347
			"import java.io.InputStream;\n" +
2348
			"import java.io.BufferedInputStream;\n" +
2349
			"import java.io.IOException;\n" +
2350
			"public class X {\n" +
2351
			"    void foo(InputStream stream) throws IOException {\n" +
2352
			"        stream = new BufferedInputStream(stream);\n" +
2353
			"        System.out.println(stream.available());\n" +
2354
			"        stream.close();\n" +
2355
			"    }\n" +
2356
			"    void boo(InputStream stream2) throws IOException {\n" +
2357
			"        stream2 = new BufferedInputStream(stream2);\n" +
2358
			"        System.out.println(stream2.available());\n" +
2359
			"    }\n" +
2360
			"}\n"
2361
		},
2362
		"",
2363
		null,
2364
		true,
2365
		null,
2366
		options,
2367
		null);
2368
}
2369
// Bug 358903 - Filter practically unimportant resource leak warnings
2370
// a wrapper is created in a return statement
2371
public void test061k() throws IOException {
2372
	Map options = getCompilerOptions();
2373
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2374
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2375
	this.runConformTest(
2376
		new String[] {
2377
			"X.java",
2378
			"import java.io.File;\n" +
2379
			"import java.io.FileInputStream;\n" +
2380
			"import java.io.BufferedInputStream;\n" +
2381
			"import java.io.IOException;\n" +
2382
			"public class X {\n" +
2383
			"    BufferedInputStream getReader(File file) throws IOException {\n" +
2384
			"        FileInputStream stream = new FileInputStream(file);\n" +
2385
			"        return new BufferedInputStream(stream);\n" +
2386
			"    }\n" +
2387
			"}\n"
2388
		},
2389
		"",
2390
		null,
2391
		true,
2392
		null,
2393
		options,
2394
		null);
2395
}
2396
// Bug 358903 - Filter practically unimportant resource leak warnings
2397
// a closeable is assigned to a field
2398
public void test061l() throws IOException {
2399
	Map options = getCompilerOptions();
2400
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2401
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2402
	this.runConformTest(
2403
		new String[] {
2404
			"X.java",
2405
			"import java.io.File;\n" +
2406
			"import java.io.FileInputStream;\n" +
2407
			"import java.io.BufferedInputStream;\n" +
2408
			"import java.io.IOException;\n" +
2409
			"public class X {\n" +
2410
			"    BufferedInputStream stream;\n" +
2411
			"    void foo(File file) throws IOException {\n" +
2412
			"        FileInputStream s = new FileInputStream(file);\n" +
2413
			"        stream = new BufferedInputStream(s);\n" +
2414
			"    }\n" +
2415
			"}\n"
2416
		},
2417
		"",
2418
		null,
2419
		true,
2420
		null,
2421
		options,
2422
		null);
2423
}
2424
// Bug 358903 - Filter practically unimportant resource leak warnings
2425
// a closeable is passed to another method in a return statement
2426
// example constructed after org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository#getArtifact(..)
2427
public void test061m() throws IOException {
2428
	Map options = getCompilerOptions();
2429
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2430
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2431
	this.runNegativeTest(
2432
		new String[] {
2433
			"X.java",
2434
			"import java.io.File;\n" +
2435
			"import java.io.FileInputStream;\n" +
2436
			"import java.io.BufferedInputStream;\n" +
2437
			"import java.io.InputStream;\n" +
2438
			"import java.io.IOException;\n" +
2439
			"public class X {\n" +
2440
			"    BufferedInputStream stream;\n" +
2441
			"    BufferedInputStream foo(File file) throws IOException {\n" +
2442
			"        FileInputStream s = new FileInputStream(file);\n" +
2443
			"        return check(new BufferedInputStream(s));\n" +
2444
			"    }\n" +
2445
			"    BufferedInputStream foo2(FileInputStream s, File file) throws IOException {\n" +
2446
			"        s = new FileInputStream(file);\n" +
2447
			"        return check(s);\n" +
2448
			"    }\n" +
2449
			"    BufferedInputStream foo3(InputStream s) throws IOException {\n" +
2450
			"        s = check(s);\n" +
2451
			"        return check(s);\n" +
2452
			"    }\n" +
2453
			"    BufferedInputStream check(InputStream s) { return null; }\n" +
2454
			"}\n"
2455
		},
2456
		// TODO: also these warnings *might* be avoidable by detecting check(s) as a wrapper creation??
2457
		"----------\n" +
2458
		"1. ERROR in X.java (at line 14)\n" +
2459
		"	return check(s);\n" +
2460
		"	^^^^^^^^^^^^^^^^\n" +
2461
		"Potential resource leak: \'s\' may not be closed at this location\n" +
2462
		"----------\n" +
2463
		"2. ERROR in X.java (at line 18)\n" +
2464
		"	return check(s);\n" +
2465
		"	^^^^^^^^^^^^^^^^\n" +
2466
		"Potential resource leak: \'s\' may not be closed at this location\n" +
2467
		"----------\n",
2468
		null,
2469
		true,
2470
		options);
2471
}
2472
// Bug 358903 - Filter practically unimportant resource leak warnings
2473
// a resource wrapper does not wrap any provided resource
2474
public void test061n() {
2475
	Map options = getCompilerOptions();
2476
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2477
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2478
	this.runNegativeTest(
2479
		new String[] {
2480
			"X.java",
2481
			"import java.io.PrintWriter;\n" +
2482
			"import java.io.IOException;\n" +
2483
			"public class X {\n" +
2484
			"    void foo() throws IOException {\n" +
2485
			"        PrintWriter writer = new PrintWriter(\"filename\");\n" +
2486
			"        writer.write(1);\n" +
2487
			"    }\n" +
2488
			"}\n"
2489
		},
2490
		"----------\n" +
2491
		"1. ERROR in X.java (at line 5)\n" +
2492
		"	PrintWriter writer = new PrintWriter(\"filename\");\n" +
2493
		"	            ^^^^^^\n" +
2494
		"Resource leak: \'writer\' is never closed\n" +
2495
		"----------\n",
2496
		null,
2497
		true,
2498
		options);
2499
}
2500
// Bug 358903 - Filter practically unimportant resource leak warnings
2501
// a resource wrapper is closed only in its local block, underlying resource may leak
2502
public void test061o() {
2503
	Map options = getCompilerOptions();
2504
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2505
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2506
	this.runNegativeTest(
2507
		new String[] {
2508
			"X.java",
2509
			"import java.io.File;\n" +
2510
			"import java.io.FileInputStream;\n" +
2511
			"import java.io.BufferedInputStream;\n" +
2512
			"import java.io.IOException;\n" +
2513
			"public class X {\n" +
2514
			"    void foo(boolean bar) throws IOException {\n" +
2515
			"        File file = new File(\"somefil\");\n" +
2516
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
2517
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);   \n" +
2518
			"        if (bar) {\n" +
2519
			"            BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
2520
			"            doubleWrap.close();\n" +
2521
			"        }\n" +
2522
			"    }\n" +
2523
			"}\n"
2524
		},
2525
		"----------\n" +
2526
		"1. ERROR in X.java (at line 9)\n" +
2527
		"	BufferedInputStream bis = new BufferedInputStream(fileStream);   \n" +
2528
		"	                    ^^^\n" +
2529
		"Potential resource leak: \'bis\' may not be closed\n" +
2530
		"----------\n",
2531
		null,
2532
		true,
2533
		options);
2534
}
2535
// Bug 358903 - Filter practically unimportant resource leak warnings
2536
// a resource wrapper is conditionally allocated but not closed - from a real-world example
2537
public void test061f4() throws IOException {
2538
	Map options = getCompilerOptions();
2539
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2540
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2541
	this.runNegativeTest(
2542
		new String[] {
2543
			"X.java",
2544
			"import java.io.File;\n" +
2545
			"import java.io.FileInputStream;\n" +
2546
			"import java.io.FileNotFoundException;\n" +
2547
			"import java.io.InputStream;\n" +
2548
			"import java.io.BufferedInputStream;\n" +
2549
			"public class X {\n" +
2550
			"    	void foo(File location, String adviceFilePath) throws FileNotFoundException {\n" +
2551
			"		InputStream stream = null;\n" +
2552
			"		if (location.isDirectory()) {\n" +
2553
			"			File adviceFile = new File(location, adviceFilePath);\n" +
2554
			"			stream = new BufferedInputStream(new FileInputStream(adviceFile));\n" +
2555
			"		}\n" +
2556
			"	}\n" +
2557
			"}\n"
2558
		},
2559
		"----------\n" +
2560
		"1. ERROR in X.java (at line 11)\n" +
2561
		"	stream = new BufferedInputStream(new FileInputStream(adviceFile));\n" +
2562
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
2563
		"Potential resource leak: \'stream\' may not be closed\n" + // message could be stronger, but the enclosing if blurs the picture
2564
		"----------\n",
2565
		null,
2566
		true,
2567
		options);
2568
}
2569
// Bug 358903 - Filter practically unimportant resource leak warnings
2570
// a t-w-r wraps an existing resource
2571
public void test061p() {
2572
	if (this.complianceLevel < ClassFileConstants.JDK1_7) return;
2573
	Map options = getCompilerOptions();
2574
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2575
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2576
	this.runConformTest(
2577
		new String[] {
2578
			"X.java",
2579
			"import java.io.PrintWriter;\n" +
2580
			"import java.io.BufferedWriter;\n" +
2581
			"import java.io.IOException;\n" +
2582
			"public class X {\n" +
2583
			"    void foo() throws IOException {\n" +
2584
			"        PrintWriter writer = new PrintWriter(\"filename\");\n" +
2585
			"        try (BufferedWriter bw = new BufferedWriter(writer)) {\n" +
2586
			"            bw.write(1);\n" +
2587
			"        }\n" +
2588
			"    }\n" +
2589
			"}\n"
2590
		},
2591
		"",
2592
		null,
2593
		true,
2594
		null,
2595
		options,
2596
		null);
2597
}
2598
// Bug 358903 - Filter practically unimportant resource leak warnings
2599
// a t-w-r potentially wraps an existing resource
2600
// DISABLED, fails because we currently don't include t-w-r managed resources in the analysis
2601
public void _test061q() {
2602
	if (this.complianceLevel < ClassFileConstants.JDK1_7) return;
2603
	Map options = getCompilerOptions();
2604
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2605
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2606
	this.runNegativeTest(
2607
		new String[] {
2608
			"X.java",
2609
			"import java.io.PrintWriter;\n" +
2610
			"import java.io.BufferedWriter;\n" +
2611
			"import java.io.IOException;\n" +
2612
			"public class X {\n" +
2613
			"    void foo(boolean b) throws IOException {\n" +
2614
			"        PrintWriter writer = new PrintWriter(\"filename\");\n" +
2615
			"        if (b)\n" +
2616
			"            try (BufferedWriter bw = new BufferedWriter(writer)) {\n" +
2617
			"                bw.write(1);\n" +
2618
			"            }\n" +
2619
			"    }\n" +
2620
			"}\n"
2621
		},
2622
		"----------\n" +
2623
		"1. ERROR in X.java (at line 6)\n" +
2624
		"	PrintWriter writer = new PrintWriter(\\\"filename\\\");\n" +
2625
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
2626
		"Potential resource leak: \'writer\' may not be closed\n" +
2627
		"----------\n",
2628
		null,
2629
		true,
2630
		options);
2631
}
2632
// Bug 358903 - Filter practically unimportant resource leak warnings
2633
// the inner from a wrapper is returned
2634
public void test061r() {
2635
	Map options = getCompilerOptions();
2636
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2637
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2638
	this.runConformTest(
2639
		new String[] {
2640
			"X.java",
2641
			"import java.io.FileInputStream;\n" +
2642
			"import java.io.File;\n" +
2643
			"import java.io.BufferedInputStream;\n" +
2644
			"import java.io.IOException;\n" +
2645
			"public class X {\n" +
2646
			"    FileInputStream foo() throws IOException {\n" +
2647
			"        File file = new File(\"somefil\");\n" +
2648
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
2649
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);   \n" +
2650
			"        return fileStream;\n" +
2651
			"    }\n" +
2652
			"}\n"
2653
		},
2654
		"",
2655
		null,
2656
		true,
2657
		null,
2658
		options,
2659
		null);
2660
}
2661
// Bug 358903 - Filter practically unimportant resource leak warnings
2662
// a wrapper is forgotten, the inner is closed afterwards
2663
public void test061s() {
2664
	Map options = getCompilerOptions();
2665
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2666
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2667
	this.runConformTest(
2668
		new String[] {
2669
			"X.java",
2670
			"import java.io.FileInputStream;\n" +
2671
			"import java.io.File;\n" +
2672
			"import java.io.BufferedInputStream;\n" +
2673
			"import java.io.IOException;\n" +
2674
			"public class X {\n" +
2675
			"    void foo() throws IOException {\n" +
2676
			"        File file = new File(\"somefil\");\n" +
2677
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
2678
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
2679
			"        bis = null;\n" +
2680
			"        fileStream.close();\n" +
2681
			"    }\n" +
2682
			"}\n"
2683
		},
2684
		"",
2685
		null,
2686
		true,
2687
		null,
2688
		options,
2689
		null);
2690
}
2691
// Bug 362331 - Resource leak not detected when closeable not assigned to variable
2692
// a resource is never assigned
2693
public void test062a() throws IOException {
2694
	Map options = getCompilerOptions();
2695
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2696
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2697
	this.runNegativeTest(
2698
		new String[] {
2699
			"X.java",
2700
			"import java.io.File;\n" +
2701
			"import java.io.FileOutputStream;\n" +
2702
			"import java.io.IOException;\n" +
2703
			"public class X {\n" +
2704
			"    void foo() throws IOException {\n" +
2705
			"        new FileOutputStream(new File(\"C:\\temp\\foo.txt\")).write(1);\n" +
2706
			"    }\n" +
2707
			"}\n"
2708
		},
2709
		"----------\n" +
2710
		"1. ERROR in X.java (at line 6)\n" +
2711
		"	new FileOutputStream(new File(\"C:\\temp\\foo.txt\")).write(1);\n" +
2712
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
2713
		"Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
2714
		"----------\n",
2715
		null,
2716
		true,
2717
		options);
2718
}
2719
// Bug 362331 - Resource leak not detected when closeable not assigned to variable
2720
// a freshly allocated resource is immediately closed
2721
public void test062b() throws IOException {
2722
	Map options = getCompilerOptions();
2723
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2724
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2725
	this.runConformTest(
2726
		new String[] {
2727
			"X.java",
2728
			"import java.io.File;\n" +
2729
			"import java.io.FileOutputStream;\n" +
2730
			"import java.io.IOException;\n" +
2731
			"public class X {\n" +
2732
			"    void foo() throws IOException {\n" +
2733
			"        new FileOutputStream(new File(\"C:\\temp\\foo.txt\")).close();\n" +
2734
			"    }\n" +
2735
			"}\n"
2736
		},
2737
		"",
2738
		null,
2739
		true,
2740
		null,
2741
		options,
2742
		null);
2743
}
2744
// Bug 362331 - Resource leak not detected when closeable not assigned to variable
2745
// a resource is directly passed to another method
2746
public void test062c() throws IOException {
2747
	Map options = getCompilerOptions();
2748
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2749
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2750
	this.runConformTest(
2751
		new String[] {
2752
			"X.java",
2753
			"import java.io.File;\n" +
2754
			"import java.io.FileOutputStream;\n" +
2755
			"import java.io.IOException;\n" +
2756
			"public class X {\n" +
2757
			"    void foo() throws IOException {\n" +
2758
			"        writeIt(new FileOutputStream(new File(\"C:\\temp\\foo.txt\")));\n" +
2759
			"    }\n" +
2760
			"    void writeIt(FileOutputStream fos) throws IOException {\n" +
2761
			"        fos.write(1);\n" +
2762
			"        fos.close();\n" +
2763
			"    }\n" +
2764
			"}\n"
2765
		},
2766
		"",
2767
		null,
2768
		true,
2769
		null,
2770
		options,
2771
		null);
2772
}
2773
// Bug 362331 - Resource leak not detected when closeable not assigned to variable
2774
// a resource is not used
2775
public void test062d() throws IOException {
2776
	Map options = getCompilerOptions();
2777
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2778
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2779
	this.runNegativeTest(
2780
		new String[] {
2781
			"X.java",
2782
			"import java.io.File;\n" +
2783
			"import java.io.FileOutputStream;\n" +
2784
			"import java.io.IOException;\n" +
2785
			"public class X {\n" +
2786
			"    void foo() throws IOException {\n" +
2787
			"        new FileOutputStream(new File(\"C:\\temp\\foo.txt\"));\n" +
2788
			"    }\n" +
2789
			"}\n"
2790
		},
2791
		"----------\n" +
2792
		"1. ERROR in X.java (at line 6)\n" +
2793
		"	new FileOutputStream(new File(\"C:\\temp\\foo.txt\"));\n" +
2794
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
2795
		"Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
2796
		"----------\n",
2797
		null,
2798
		true,
2799
		options);
2800
}
2801
// Bug 362332 - Only report potential leak when closeable not created in the local scope
2802
// a wrapper is obtained from another method
2803
public void test063a() throws IOException {
2804
	Map options = getCompilerOptions();
2805
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2806
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2807
	this.runNegativeTest(
2808
		new String[] {
2809
			"X.java",
2810
			"import java.io.File;\n" +
2811
			"import java.io.FileInputStream;\n" +
2812
			"import java.io.BufferedInputStream;\n" +
2813
			"import java.io.IOException;\n" +
2814
			"public class X {\n" +
2815
			"    void read(File file) throws IOException {\n" +
2816
			"        FileInputStream stream = new FileInputStream(file);\n" +
2817
			"        BufferedInputStream bis = new BufferedInputStream(stream); // never since reassigned\n" +
2818
			"        FileInputStream stream2 = new FileInputStream(file); // unsure since passed to method\n" +
2819
			"        bis = getReader(stream2); // unsure since obtained from method\n" +
2820
			"        bis.available();\n" +
2821
			"    }\n" +
2822
			"    BufferedInputStream getReader(FileInputStream stream) throws IOException {\n" +
2823
			"        return new BufferedInputStream(stream);\n" +
2824
			"    }\n" +
2825
			"}\n"
2826
		},
2827
		"----------\n" +
2828
		"1. ERROR in X.java (at line 7)\n" +
2829
		"	FileInputStream stream = new FileInputStream(file);\n" +
2830
		"	                ^^^^^^\n" +
2831
		"Resource leak: \'stream\' is never closed\n" +
2832
		"----------\n" +
2833
		"2. ERROR in X.java (at line 9)\n" +
2834
		"	FileInputStream stream2 = new FileInputStream(file); // unsure since passed to method\n" +
2835
		"	                ^^^^^^^\n" +
2836
		"Potential resource leak: \'stream2\' may not be closed\n" +
2837
		"----------\n" +
2838
		"3. ERROR in X.java (at line 10)\n" +
2839
		"	bis = getReader(stream2); // unsure since obtained from method\n" +
2840
		"	^^^^^^^^^^^^^^^^^^^^^^^^\n" +
2841
		"Potential resource leak: \'bis\' may not be closed\n" +
2842
		"----------\n",
2843
		null,
2844
		true,
2845
		options);
2846
}
2847
// Bug 362332 - Only report potential leak when closeable not created in the local scope
2848
// a wrapper is obtained from a field read
2849
public void test063b() throws IOException {
2850
	Map options = getCompilerOptions();
2851
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2852
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2853
	this.runConformTest(
2854
		new String[] {
2855
			"X.java",
2856
			"import java.io.FileInputStream;\n" +
2857
			"import java.io.BufferedInputStream;\n" +
2858
			"import java.io.IOException;\n" +
2859
			"public class X {\n" +
2860
			"    FileInputStream stream;\n" +
2861
			"    void read() throws IOException {\n" +
2862
			"        FileInputStream s = this.stream;\n" +
2863
			"        BufferedInputStream bis = new BufferedInputStream(s); // don't complain since s is obtained from a field\n" +
2864
			"        bis.available();\n" +
2865
			"    }\n" +
2866
			"}\n"
2867
		},
2868
		"",
2869
		null,
2870
		true,
2871
		null,
2872
		options,
2873
		null);
2874
}
2875
// Bug 362332 - Only report potential leak when closeable not created in the local scope
2876
// a wrapper is assigned to a field
2877
public void test063c() throws IOException {
2878
	Map options = getCompilerOptions();
2879
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2880
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2881
	this.runConformTest(
2882
		new String[] {
2883
			"X.java",
2884
			"import java.io.FileInputStream;\n" +
2885
			"import java.io.BufferedInputStream;\n" +
2886
			"import java.io.IOException;\n" +
2887
			"public class X {\n" +
2888
			"    BufferedInputStream stream;\n" +
2889
			"    void read() throws IOException {\n" +
2890
			"        FileInputStream s = new FileInputStream(\"somefile\");\n" +
2891
			"        BufferedInputStream bis = new BufferedInputStream(s);\n" +
2892
			"        this.stream = bis;\n" +
2893
			"    }\n" +
2894
			"}\n"
2895
		},
2896
		"",
2897
		null,
2898
		true,
2899
		null,
2900
		options,
2901
		null);
2902
}
2903
// Bug 362332 - Only report potential leak when closeable not created in the local scope
2904
// a resource is obtained as a method argument and/or assigned with a cast
2905
public void test063d() throws IOException {
2906
	Map options = getCompilerOptions();
2907
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2908
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2909
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
2910
	runTestsExpectingErrorsOnlyIn17(
2911
		new String[] {
2912
			"X.java",
2913
			"import java.io.FileInputStream;\n" +
2914
			"import java.io.BufferedInputStream;\n" +
2915
			"import java.io.InputStream;\n" +
2916
			"import java.io.IOException;\n" +
2917
			"public class X {\n" +
2918
			"    void foo( InputStream input) throws IOException {\n" +
2919
			"        FileInputStream input1  = (FileInputStream)input;\n" +
2920
			"        System.out.println(input1.read());\n" +
2921
			"        input.close();\n" + // don't propose t-w-r for argument
2922
			"    }\n" +
2923
			"    void foo() throws IOException {\n" +
2924
			"        InputStream input = new FileInputStream(\"somefile\");\n" +
2925
			"        FileInputStream input1  = (FileInputStream)input;\n" +
2926
			"        System.out.println(input1.read());\n" +
2927
			"        input.close();\n" + // do propose t-w-r, not from a method argument
2928
			"    }\n" +
2929
			"    void foo3( InputStream input, InputStream input2) throws IOException {\n" +
2930
			"        FileInputStream input1  = (FileInputStream)input;\n" + // still don't claim because obtained from outside
2931
			"        System.out.println(input1.read());\n" +
2932
			"        BufferedInputStream bis = new BufferedInputStream(input2);\n" +
2933
			"        System.out.println(bis.read());\n" +
2934
			"    }\n" +
2935
			"}\n"
2936
		},
2937
		"----------\n" +
2938
		"1. ERROR in X.java (at line 12)\n" +
2939
		"	InputStream input = new FileInputStream(\"somefile\");\n" +
2940
		"	            ^^^^^\n" +
2941
		"Resource \'input\' should be managed by try-with-resource\n" +
2942
		"----------\n",
2943
		options);
2944
}
2945
// Bug 362332 - Only report potential leak when closeable not created in the local scope
2946
// a resource is obtained from a field read, then re-assigned
2947
public void test063e() {
2948
	Map options = getCompilerOptions();
2949
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
2950
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
2951
	this.runConformTest(
2952
		new String[] {
2953
			"X.java",
2954
			"import java.io.FileInputStream;\n" +
2955
			"import java.io.IOException;\n" +
2956
			"public class X {\n" +
2957
			"    FileInputStream input1;\n" +
2958
			"    public void foo() throws IOException {\n" +
2959
			"        FileInputStream input = input1;\n" +
2960
			"        input = new FileInputStream(\"adfafd\");\n" +
2961
			"        input.close();\n" +
2962
			"    }\n" +
2963
			"}\n"
2964
		},
2965
		"",
2966
		null,
2967
		true,
2968
		null,
2969
		options,
2970
		null);
2971
}
2972
2973
}
(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java (-2 / +5 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *     Stephan Herrmann - Contributions for
11
 *								bug 186342 - [compiler][null] Using annotations for null checking
12
 *								bug 358903 - Filter practically unimportant resource leak warnings
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.core.tests.compiler.regression;
14
package org.eclipse.jdt.core.tests.compiler.regression;
13
15
Lines 74-79 public static Test suite() { Link Here
74
	standardTests.add(ProgrammingProblemsTest.class);
76
	standardTests.add(ProgrammingProblemsTest.class);
75
	standardTests.add(ManifestAnalyzerTest.class);
77
	standardTests.add(ManifestAnalyzerTest.class);
76
	standardTests.add(InitializationTests.class);
78
	standardTests.add(InitializationTests.class);
79
	standardTests.add(ResourceLeakTests.class);
77
80
78
	// add all javadoc tests
81
	// add all javadoc tests
79
	for (int i=0, l=JavadocTest.ALL_CLASSES.size(); i<l; i++) {
82
	for (int i=0, l=JavadocTest.ALL_CLASSES.size(); i<l; i++) {
(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java (-1874 / +142 lines)
Lines 16-29 package org.eclipse.jdt.core.tests.compiler.regression; Link Here
16
16
17
import java.util.Map;
17
import java.util.Map;
18
18
19
import org.eclipse.jdt.core.JavaCore;
20
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
21
22
import junit.framework.Test;
19
import junit.framework.Test;
20
21
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
23
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
22
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
24
23
25
static {
24
static {
26
//	TESTS_NAMES = new String[] { "test056throw"};
25
//	TESTS_NAMES = new String[] { "test061m"};
27
//	TESTS_NUMBERS = new int[] { 50 };
26
//	TESTS_NUMBERS = new int[] { 50 };
28
//	TESTS_RANGE = new int[] { 11, -1 };
27
//	TESTS_RANGE = new int[] { 11, -1 };
29
}
28
}
Lines 3454-5360 public void test055a() { Link Here
3454
		},
3453
		},
3455
		"Done");
3454
		"Done");
3456
}
3455
}
3457
// Bug 349326 - [1.7] new warning for missing try-with-resources
3456
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=361053
3458
// a method uses an AutoCloseable without ever closing it.
3457
public void test057() {
3459
public void test056() {
3458
	this.runConformTest(
3460
	Map options = getCompilerOptions();
3461
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3462
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3463
	this.runNegativeTest(
3464
		new String[] {
3459
		new String[] {
3465
			"X.java",
3460
			"X.java",
3466
			"import java.io.File;\n" +
3461
			"public class X implements AutoCloseable {\n" +
3467
			"import java.io.FileReader;\n" +
3462
			"	@Override\n" +
3468
			"import java.io.IOException;\n" +
3463
			"	public void close() throws Exception {\n" +
3469
			"public class X {\n" +
3464
			"		throw new Exception();\n" +
3470
			"    void foo() throws IOException {\n" +
3465
			"	}\n" +
3471
			"        File file = new File(\"somefile\");\n" +
3466
			"	public static void main(String[] args) {\n" +
3472
			"        FileReader fileReader = new FileReader(file);\n" +
3467
			"		final boolean foo;\n" +
3473
// not invoking any methods on FileReader, try to avoid necessary call to superclass() in the compiler
3468
			"		try (X a = new X(); X b = new X()) {\n" +
3474
//			"        char[] in = new char[50];\n" +
3469
			"			foo = true;\n" +
3475
//			"        fileReader.read(in);\n" +
3470
			"		} catch (final Exception exception) {\n" +
3476
			"    }\n" +
3471
			"			return;\n" +
3477
			"    public static void main(String[] args) throws IOException {\n" +
3472
			"		}\n" +
3478
			"        new X().foo();\n" +
3473
			"	}\n" +
3479
			"    }\n" +
3480
			"}\n"
3474
			"}\n"
3481
		},
3475
		},  "");	
3482
		"----------\n" + 
3483
		"1. ERROR in X.java (at line 7)\n" + 
3484
		"	FileReader fileReader = new FileReader(file);\n" + 
3485
		"	           ^^^^^^^^^^\n" + 
3486
		"Resource leak: 'fileReader' is never closed\n" +
3487
		"----------\n",
3488
		null,
3489
		true,
3490
		options);
3491
}
3476
}
3492
// Bug 349326 - [1.7] new warning for missing try-with-resources
3477
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=364008
3493
// a method uses an AutoCloseable and closes it but not protected by t-w-r nor regular try-finally
3478
public void test058() {
3494
public void test056a() {
3479
	this.runConformTest(
3495
	Map options = getCompilerOptions();
3496
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3497
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
3498
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
3499
	this.runNegativeTest(
3500
		new String[] {
3480
		new String[] {
3501
			"X.java",
3481
			"X.java",
3502
			"import java.io.File;\n" +
3482
			"import java.io.ByteArrayOutputStream;\n" +
3503
			"import java.io.FileReader;\n" +
3483
			"import java.io.FileOutputStream;\n" +
3504
			"import java.io.IOException;\n" +
3484
			"import java.io.IOException;\n" +
3485
			"\n" +
3505
			"public class X {\n" +
3486
			"public class X {\n" +
3506
			"    void foo() throws IOException {\n" +
3487
			"\n" +
3507
			"        File file = new File(\"somefile\");\n" +
3488
			"  public static void main(final String[] args) throws IOException {\n" +
3508
			"        FileReader fileReader = new FileReader(file);\n" +
3489
			"    byte[] data;\n" +
3509
			"        char[] in = new char[50];\n" +
3490
			"    try (final ByteArrayOutputStream os = new ByteArrayOutputStream();\n" +
3510
			"        fileReader.read(in);\n" +
3491
			"         final FileOutputStream out = new FileOutputStream(\"test.dat\")) {\n" +
3511
			"		 fileReader.close();\n" +
3492
			"      data = os.toByteArray();\n" +
3512
			"    }\n" +
3513
			"    public static void main(String[] args) {\n" +
3514
			"        try {\n" +
3515
			"            new X().foo();\n" +
3516
			"        } catch (IOException ioex) {\n" +
3517
			"            System.out.println(\"caught\");\n" +
3518
			"        }\n" +
3519
			"    }\n" +
3493
			"    }\n" +
3494
			"  }\n" +
3520
			"}\n"
3495
			"}\n"
3521
		},
3496
		},  "");	
3522
		"----------\n" + 
3523
		"1. ERROR in X.java (at line 7)\n" + 
3524
		"	FileReader fileReader = new FileReader(file);\n" + 
3525
		"	           ^^^^^^^^^^\n" + 
3526
		"Resource 'fileReader' should be managed by try-with-resource\n" + 
3527
		"----------\n",
3528
		null,
3529
		true,
3530
		options);
3531
}
3497
}
3532
// Bug 349326 - [1.7] new warning for missing try-with-resources
3498
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=367566 - In try-with-resources statement close() method of resource is not called
3533
// a method uses an AutoCloseable and closes it properly in a finally block
3499
public void test059() {
3534
public void test056b() {
3535
	Map options = getCompilerOptions();
3536
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3537
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
3538
	this.runConformTest(
3500
	this.runConformTest(
3539
		new String[] {
3501
		new String[] {
3540
			"X.java",
3502
			"X.java",
3541
			"import java.io.File;\n" +
3542
			"import java.io.FileReader;\n" +
3543
			"import java.io.IOException;\n" +
3503
			"import java.io.IOException;\n" +
3544
			"public class X {\n" +
3504
			"\n" +
3545
			"    void foo() throws IOException {\n" +
3505
			"public class X implements java.lang.AutoCloseable {\n" +
3546
			"        File file = new File(\"somefile\");\n" +
3506
			"  static boolean isOpen = true;\n" +
3547
			"        FileReader fileReader = new FileReader(file);\n" +
3507
			"  public static void main(final String[] args) throws IOException {\n" +
3548
			"        try {\n" +
3508
			"    foo();\n" +
3549
			"            char[] in = new char[50];\n" +
3509
			"    System.out.println(isOpen);\n" +
3550
			"            fileReader.read(in);\n" +
3510
			"  }\n" +
3551
			"        } finally {\n" +
3511
			"  static boolean foo() {\n" +
3552
			"		     fileReader.close();\n" +
3512
			"    try (final X x = new X()) {\n" +
3553
			"        }\n" +
3513
			"      return x.num() >= 1;\n" +
3554
			"    }\n" +
3555
			"    public static void main(String[] args) {\n" +
3556
			"        try {\n" +
3557
			"            new X().foo();\n" +
3558
			"        } catch (IOException ioex) {\n" +
3559
			"            System.out.println(\"caught\");\n" +
3560
			"        }\n" +
3561
			"    }\n" +
3514
			"    }\n" +
3515
			"  }\n" +
3516
			"  int num() { return 2; }\n" +
3517
			"  public void close() {\n" +
3518
			"    isOpen = false;\n" +
3519
			"  }\n" +
3562
			"}\n"
3520
			"}\n"
3563
		},
3521
		},  
3564
		"caught", /*output*/
3522
		"false");	
3565
		null/*classLibs*/,
3566
		true/*shouldFlush*/,
3567
		null/*vmargs*/,
3568
		options,
3569
		null/*requestor*/);
3570
}
3523
}
3571
// Bug 349326 - [1.7] new warning for missing try-with-resources
3524
3572
// a method uses an AutoCloseable properly within try-with-resources.
3525
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=367566 - In try-with-resources statement close() method of resource is not called
3573
public void test056c() {
3526
public void test060() {
3574
	Map options = getCompilerOptions();
3575
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3576
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3577
	this.runConformTest(
3527
	this.runConformTest(
3578
		new String[] {
3528
		new String[] {
3579
			"X.java",
3529
			"X.java",
3580
			"import java.io.File;\n" +
3530
			"public class X implements AutoCloseable {\n" +
3581
			"import java.io.FileReader;\n" +
3531
			"	static int num = 10 ;\n" +
3582
			"import java.io.IOException;\n" +
3532
			"    public static void main(String [] args) throws Exception { \n" +
3583
			"public class X {\n" +
3533
			"    	System.out.println(foo(1));\n" +
3584
			"    void foo() throws IOException {\n" +
3534
			"    	System.out.println(foo(2));\n" +
3585
			"        File file = new File(\"somefile\");\n" +
3535
			"    	System.out.println(foo(3));\n" +
3586
			"        try (FileReader fileReader = new FileReader(file)) {\n" +
3587
			"            char[] in = new char[50];\n" +
3588
			"            fileReader.read(in);\n" +
3589
			"		 }\n" +
3590
			"    }\n" +
3536
			"    }\n" +
3591
			"    public static void main(String[] args) {\n" +
3537
			"	private static boolean foo(int where) throws Exception {\n" +
3592
			"        try {\n" +
3538
			"		final boolean getOut = true;\n" +
3593
			"            new X().foo();\n" +
3539
			"    	System.out.println(\"Main\");\n" +
3594
			"        } catch (IOException ioex) {\n" +
3540
			"    	try (X x1 = new X(); X x2 = new X()) {\n" +
3595
			"            System.out.println(\"caught\");\n" +
3541
			"    		if (where == 1) {\n" +
3542
			"    			return where == 1;\n" +
3543
			"    		}\n" +
3544
			"            System.out.println(\"Outer Try\");\n" +
3545
			"            while (true) {\n" +
3546
			"            	try (Y y1 = new Y(); Y y2 = new Y()) { \n" +
3547
			"            		if (where == 2) {\n" +
3548
			"            			return where == 2;\n" +
3549
			"            		}		\n" +
3550
			"            		System.out.println(\"Middle Try\");\n" +
3551
			"            		try (Z z1 = new Z(); Z z2 = new Z()) {\n" +
3552
			"            			System.out.println(\"Inner Try\");\n" +
3553
			"            			if (getOut) \n" +
3554
			"            				return num >= 10;\n" +
3555
			"            			else\n" +
3556
			"            				break; \n" +
3557
			"            		}\n" +
3558
			"            	}\n" +
3559
			"            }\n" +
3560
			"            System.out.println(\"Out of while\");\n" +
3596
			"        }\n" +
3561
			"        }\n" +
3562
			"		return false;\n" +
3563
			"	}\n" +
3564
			"    public X() {\n" +
3565
			"        System.out.println(\"X::X\");\n" +
3597
			"    }\n" +
3566
			"    }\n" +
3598
			"}\n"
3567
			"    @Override\n" +
3599
		},
3568
			"	public void close() throws Exception {\n" +
3600
		"caught", /*output*/
3569
			"        System.out.println(\"X::~X\");\n" +
3601
		null/*classLibs*/,
3602
		true/*shouldFlush*/,
3603
		null/*vmargs*/,
3604
		options,
3605
		null/*requestor*/);
3606
}
3607
// Bug 349326 - [1.7] new warning for missing try-with-resources
3608
// a method uses two AutoCloseables (testing independent analysis)
3609
// - one closeable may be unclosed at a conditional return
3610
// - the other is only conditionally closed
3611
public void test056d() {
3612
	Map options = getCompilerOptions();
3613
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3614
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3615
	this.runNegativeTest(
3616
		new String[] {
3617
			"X.java",
3618
			"import java.io.File;\n" +
3619
			"import java.io.FileReader;\n" +
3620
			"import java.io.IOException;\n" +
3621
			"public class X {\n" +
3622
			"    void foo(boolean flag1, boolean flag2) throws IOException {\n" +
3623
			"        File file = new File(\"somefile\");\n" +
3624
			"        char[] in = new char[50];\n" +
3625
			"        FileReader fileReader1 = new FileReader(file);\n" +
3626
			"        fileReader1.read(in);\n" +
3627
			"        FileReader fileReader2 = new FileReader(file);\n" +
3628
			"        fileReader2.read(in);\n" +
3629
			"        if (flag1) {\n" +
3630
			"            fileReader2.close();\n" +
3631
			"            return;\n" +
3632
			"        } else if (flag2) {\n" +
3633
			"            fileReader2.close();\n" +
3634
			"        }\n" +
3635
			"        fileReader1.close();\n" +
3636
			"    }\n" +
3570
			"    }\n" +
3637
			"    public static void main(String[] args) throws IOException {\n" +
3571
			"}\n" +
3638
			"        new X().foo(false, true);\n" +
3572
			"class Y implements AutoCloseable {\n" +
3573
			"    public Y() {\n" +
3574
			"        System.out.println(\"Y::Y\");\n" +
3639
			"    }\n" +
3575
			"    }\n" +
3640
			"}\n"
3576
			"    @Override\n" +
3641
		},
3577
			"	public void close() throws Exception {\n" +
3642
		"----------\n" + 
3578
			"        System.out.println(\"Y::~Y\");\n" +
3643
		"1. WARNING in X.java (at line 10)\n" + 
3644
		"	FileReader fileReader2 = new FileReader(file);\n" + 
3645
		"	           ^^^^^^^^^^^\n" + 
3646
		"Potential resource leak: 'fileReader2' may not be closed\n" +
3647
		"----------\n" + 
3648
		"2. ERROR in X.java (at line 14)\n" + 
3649
		"	return;\n" + 
3650
		"	^^^^^^^\n" + 
3651
		"Resource leak: 'fileReader1' is not closed at this location\n" + 
3652
		"----------\n",
3653
		null,
3654
		true,
3655
		options);
3656
}
3657
//Bug 349326 - [1.7] new warning for missing try-with-resources
3658
//a method uses two AutoCloseables (testing independent analysis)
3659
//- one closeable may be unclosed at a conditional return
3660
//- the other is only conditionally closed
3661
public void test056d_suppress() {
3662
	Map options = getCompilerOptions();
3663
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3664
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3665
	options.put(CompilerOptions.OPTION_SuppressOptionalErrors, CompilerOptions.ENABLED);
3666
	this.runNegativeTest(
3667
		new String[] {
3668
			"X.java",
3669
			"import java.io.File;\n" +
3670
			"import java.io.FileReader;\n" +
3671
			"import java.io.IOException;\n" +
3672
			"public class X {\n" +
3673
			"    void foo(boolean flag1, boolean flag2) throws IOException {\n" +
3674
			"        @SuppressWarnings(\"resource\") File file = new File(\"somefile\"); // unnecessary suppress\n" +
3675
			"        char[] in = new char[50];\n" +
3676
			"        FileReader fileReader1 = new FileReader(file);\n" +
3677
			"        fileReader1.read(in);\n" +
3678
			"        @SuppressWarnings(\"resource\") FileReader fileReader2 = new FileReader(file); // useful suppress\n" +
3679
			"        fileReader2.read(in);\n" +
3680
			"        if (flag1) {\n" +
3681
			"            fileReader2.close();\n" +
3682
			"            return; // not suppressed\n" +
3683
			"        } else if (flag2) {\n" +
3684
			"            fileReader2.close();\n" +
3685
			"        }\n" +
3686
			"        fileReader1.close();\n" +
3687
			"    }\n" +
3579
			"    }\n" +
3688
			"    @SuppressWarnings(\"resource\") // useful suppress\n" +
3580
			"}\n" +
3689
			"    void bar() throws IOException {\n" +
3581
			"class Z implements AutoCloseable {\n" +
3690
			"        File file = new File(\"somefile\");\n" +
3582
			"    public Z() {\n" +
3691
			"        FileReader fileReader = new FileReader(file);\n" +
3583
			"        System.out.println(\"Z::Z\");\n" +
3692
			"        char[] in = new char[50];\n" +
3693
			"        fileReader.read(in);\n" +
3694
			"    }\n" +
3584
			"    }\n" +
3695
			"    public static void main(String[] args) throws IOException {\n" +
3585
			"    @Override\n" +
3696
			"        new X().foo(false, true);\n" +
3586
			"	public void close() throws Exception {\n" +
3587
			"        System.out.println(\"Z::~Z\");\n" +
3697
			"    }\n" +
3588
			"    }\n" +
3698
			"}\n"
3589
			"}\n"
3699
		},
3590
		}, 
3700
		"----------\n" + 
3591
		"Main\n" + 
3701
		"1. WARNING in X.java (at line 6)\n" + 
3592
		"X::X\n" + 
3702
		"	@SuppressWarnings(\"resource\") File file = new File(\"somefile\"); // unnecessary suppress\n" + 
3593
		"X::X\n" + 
3703
		"	                  ^^^^^^^^^^\n" + 
3594
		"X::~X\n" + 
3704
		"Unnecessary @SuppressWarnings(\"resource\")\n" + 
3595
		"X::~X\n" + 
3705
		"----------\n" + 
3596
		"true\n" + 
3706
		"2. ERROR in X.java (at line 14)\n" + 
3597
		"Main\n" + 
3707
		"	return; // not suppressed\n" + 
3598
		"X::X\n" + 
3708
		"	^^^^^^^\n" + 
3599
		"X::X\n" + 
3709
		"Resource leak: 'fileReader1' is not closed at this location\n" + 
3600
		"Outer Try\n" + 
3710
		"----------\n",
3601
		"Y::Y\n" + 
3711
		null,
3602
		"Y::Y\n" + 
3712
		true,
3603
		"Y::~Y\n" + 
3713
		options);
3604
		"Y::~Y\n" + 
3605
		"X::~X\n" + 
3606
		"X::~X\n" + 
3607
		"true\n" + 
3608
		"Main\n" + 
3609
		"X::X\n" + 
3610
		"X::X\n" + 
3611
		"Outer Try\n" + 
3612
		"Y::Y\n" + 
3613
		"Y::Y\n" + 
3614
		"Middle Try\n" + 
3615
		"Z::Z\n" + 
3616
		"Z::Z\n" + 
3617
		"Inner Try\n" + 
3618
		"Z::~Z\n" + 
3619
		"Z::~Z\n" + 
3620
		"Y::~Y\n" + 
3621
		"Y::~Y\n" + 
3622
		"X::~X\n" + 
3623
		"X::~X\n" + 
3624
		"true");
3714
}
3625
}
3715
// Bug 349326 - [1.7] new warning for missing try-with-resources
3716
// one method returns an AutoCleasble, a second method uses this object without ever closing it.
3717
public void test056e() {
3718
	Map options = getCompilerOptions();
3719
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3720
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3721
	this.runNegativeTest(
3722
		new String[] {
3723
			"X.java",
3724
			"import java.io.File;\n" +
3725
			"import java.io.FileReader;\n" +
3726
			"import java.io.IOException;\n" +
3727
			"public class X {\n" +
3728
			"    FileReader getReader(String filename) throws IOException {\n" +
3729
			"        File file = new File(\"somefile\");\n" +
3730
			"        FileReader fileReader = new FileReader(file);\n" +
3731
			"        return fileReader;\n" + 		// don't complain here, pass responsibility to caller
3732
			"    }\n" +
3733
			"    void foo() throws IOException {\n" +
3734
			"        FileReader reader = getReader(\"somefile\");\n" +
3735
			"        char[] in = new char[50];\n" +
3736
			"        reader.read(in);\n" +
3737
			"    }\n" +
3738
			"    public static void main(String[] args) throws IOException {\n" +
3739
			"        new X().foo();\n" +
3740
			"    }\n" +
3741
			"}\n"
3742
		},
3743
		"----------\n" + 
3744
		"1. ERROR in X.java (at line 11)\n" + 
3745
		"	FileReader reader = getReader(\"somefile\");\n" + 
3746
		"	           ^^^^^^\n" + 
3747
		"Resource leak: 'reader' is never closed\n" + 
3748
		"----------\n",
3749
		null,
3750
		true,
3751
		options);
3752
}
3753
// Bug 349326 - [1.7] new warning for missing try-with-resources
3754
// a method explicitly closes its AutoCloseable rather than using t-w-r
3755
public void test056f() {
3756
	Map options = getCompilerOptions();
3757
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3758
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3759
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
3760
	this.runNegativeTest(
3761
		new String[] {
3762
			"X.java",
3763
			"import java.io.File;\n" +
3764
			"import java.io.FileReader;\n" +
3765
			"import java.io.IOException;\n" +
3766
			"public class X {\n" +
3767
			"    void foo() throws IOException {\n" +
3768
			"        File file = new File(\"somefile\");\n" +
3769
			"        FileReader fileReader = null;\n" +
3770
			"        try {\n" +
3771
			"            fileReader = new FileReader(file);\n" +
3772
			"            char[] in = new char[50];\n" +
3773
			"            fileReader.read(in);\n" +
3774
			"        } finally {\n" +
3775
			"            fileReader.close();\n" +
3776
			"        }\n" +
3777
			"    }\n" +
3778
			"    public static void main(String[] args) throws IOException {\n" +
3779
			"        new X().foo();\n" +
3780
			"    }\n" +
3781
			"}\n"
3782
		},
3783
		"----------\n" + 
3784
		"1. ERROR in X.java (at line 7)\n" + 
3785
		"	FileReader fileReader = null;\n" + 
3786
		"	           ^^^^^^^^^^\n" + 
3787
		"Resource 'fileReader' should be managed by try-with-resource\n" + 
3788
		"----------\n",
3789
		null,
3790
		true,
3791
		options);
3792
}
3793
// Bug 349326 - [1.7] new warning for missing try-with-resources
3794
// an AutoCloseable local is re-assigned
3795
public void test056g() {
3796
	Map options = getCompilerOptions();
3797
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
3798
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
3799
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
3800
	this.runNegativeTest(
3801
		new String[] {
3802
			"X.java",
3803
			"import java.io.File;\n" +
3804
			"import java.io.FileReader;\n" +
3805
			"import java.io.IOException;\n" +
3806
			"public class X {\n" +
3807
			"    void foo() throws IOException {\n" +
3808
			"        File file = new File(\"somefile\");\n" +
3809
			"        FileReader fileReader = new FileReader(file);\n" +
3810
			"        char[] in = new char[50];\n" +
3811
			"        fileReader.read(in);\n" +
3812
			"        fileReader = new FileReader(file);\n" +
3813
			"        fileReader.read(in);\n" +
3814
			"        fileReader.close();\n" +
3815
			"        fileReader = null;\n" +
3816
			"    }\n" +
3817
			"    public static void main(String[] args) throws IOException {\n" +
3818
			"        new X().foo();\n" +
3819
			"    }\n" +
3820
			"}\n"
3821
		},
3822
		"----------\n" + 
3823
		"1. ERROR in X.java (at line 10)\n" + 
3824
		"	fileReader = new FileReader(file);\n" + 
3825
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
3826
		"Resource leak: 'fileReader' is not closed at this location\n" + 
3827
		"----------\n",
3828
		null,
3829
		true,
3830
		options);
3831
}
3832
// Bug 349326 - [1.7] new warning for missing try-with-resources
3833
// an AutoCloseable local is re-assigned after null-assigned
3834
public void test056g2() {
3835
	Map options = getCompilerOptions();
3836
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
3837
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
3838
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
3839
	this.runNegativeTest(
3840
		new String[] {
3841
			"X.java",
3842
			"import java.io.File;\n" +
3843
			"import java.io.FileReader;\n" +
3844
			"import java.io.IOException;\n" +
3845
			"public class X {\n" +
3846
			"    void foo() throws IOException {\n" +
3847
			"        File file = new File(\"somefile\");\n" +
3848
			"        FileReader fileReader = new FileReader(file);\n" +
3849
			"        char[] in = new char[50];\n" +
3850
			"        fileReader.read(in);\n" +
3851
			"        fileReader = null;\n" +
3852
			"        fileReader = new FileReader(file);\n" + // don't complain again, fileReader is null, so nothing can leak here
3853
			"        fileReader.read(in);\n" +
3854
			"        fileReader.close();\n" +
3855
			"    }\n" +
3856
			"    public static void main(String[] args) throws IOException {\n" +
3857
			"        new X().foo();\n" +
3858
			"    }\n" +
3859
			"}\n"
3860
		},
3861
		"----------\n" + 
3862
		"1. ERROR in X.java (at line 10)\n" + 
3863
		"	fileReader = null;\n" + 
3864
		"	^^^^^^^^^^^^^^^^^\n" + 
3865
		"Resource leak: 'fileReader' is not closed at this location\n" + 
3866
		"----------\n",
3867
		null,
3868
		true,
3869
		options);
3870
}
3871
// Bug 349326 - [1.7] new warning for missing try-with-resources
3872
// two AutoCloseables at different nesting levels (anonymous local type)
3873
public void test056h() {
3874
	Map options = getCompilerOptions();
3875
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
3876
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
3877
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
3878
	this.runNegativeTest(
3879
		new String[] {
3880
			"X.java",
3881
			"import java.io.File;\n" +
3882
			"import java.io.FileReader;\n" +
3883
			"import java.io.IOException;\n" +
3884
			"public class X {\n" +
3885
			"    void foo() throws IOException {\n" +
3886
			"        final File file = new File(\"somefile\");\n" +
3887
			"        final FileReader fileReader = new FileReader(file);\n" +
3888
			"        char[] in = new char[50];\n" +
3889
			"        fileReader.read(in);\n" +
3890
			"        new Runnable() {\n public void run() {\n" +
3891
			"            try {\n" +
3892
			"                fileReader.close();\n" +
3893
			"                FileReader localReader = new FileReader(file);\n" +
3894
			"            } catch (IOException ex) { /* nop */ }\n" +
3895
			"        }}.run();\n" +
3896
			"    }\n" +
3897
			"    public static void main(String[] args) throws IOException {\n" +
3898
			"        new X().foo();\n" +
3899
			"    }\n" +
3900
			"}\n"
3901
		},
3902
		"----------\n" + 
3903
		"1. WARNING in X.java (at line 7)\n" + 
3904
		"	final FileReader fileReader = new FileReader(file);\n" + 
3905
		"	                 ^^^^^^^^^^\n" + 
3906
		"Potential resource leak: 'fileReader' may not be closed\n" + 
3907
		"----------\n" + 
3908
		"2. ERROR in X.java (at line 14)\n" + 
3909
		"	FileReader localReader = new FileReader(file);\n" + 
3910
		"	           ^^^^^^^^^^^\n" + 
3911
		"Resource leak: 'localReader' is never closed\n" + 
3912
		"----------\n",
3913
		null,
3914
		true,
3915
		options);
3916
}
3917
// Bug 349326 - [1.7] new warning for missing try-with-resources
3918
// three AutoCloseables in different blocks of the same method
3919
public void test056i() {
3920
	Map options = getCompilerOptions();
3921
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
3922
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
3923
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
3924
	this.runNegativeTest(
3925
		new String[] {
3926
			"X.java",
3927
			"import java.io.File;\n" +
3928
			"import java.io.FileReader;\n" +
3929
			"import java.io.IOException;\n" +
3930
			"public class X {\n" +
3931
			"    void foo(boolean f1, boolean f2) throws IOException {\n" +
3932
			"        File file = new File(\"somefile\");\n" +
3933
			"        if (f1) {\n" +
3934
			"            FileReader fileReader = new FileReader(file); // err: not closed\n" +
3935
			"            char[] in = new char[50];\n" +
3936
			"            fileReader.read(in);\n" +
3937
			"            while (true) {\n" +
3938
			"                 FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" +
3939
			"                 loopReader.close();" +
3940
			"                 break;\n" +
3941
			"            }\n" +
3942
			"        } else {\n" +
3943
			"            FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
3944
			"            if (f2)\n" +
3945
			"                fileReader.close();\n" +
3946
			"        }\n" +
3947
			"    }\n" +
3948
			"    public static void main(String[] args) throws IOException {\n" +
3949
			"        new X().foo(true, true);\n" +
3950
			"    }\n" +
3951
			"}\n"
3952
		},
3953
		"----------\n" + 
3954
		"1. ERROR in X.java (at line 8)\n" + 
3955
		"	FileReader fileReader = new FileReader(file); // err: not closed\n" + 
3956
		"	           ^^^^^^^^^^\n" + 
3957
		"Resource leak: 'fileReader' is never closed\n" + 
3958
		"----------\n" + 
3959
		"2. WARNING in X.java (at line 16)\n" + 
3960
		"	FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + 
3961
		"	           ^^^^^^^^^^\n" + 
3962
		"Potential resource leak: 'fileReader' may not be closed\n" + 
3963
		"----------\n",
3964
		null,
3965
		true,
3966
		options);
3967
}
3968
// Bug 349326 - [1.7] new warning for missing try-with-resources
3969
// three AutoCloseables in different blocks of the same method
3970
public void test056i2() {
3971
	Map options = getCompilerOptions();
3972
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
3973
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
3974
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
3975
	this.runNegativeTest(
3976
		new String[] {
3977
			"X.java",
3978
			"import java.io.File;\n" + 
3979
			"import java.io.FileReader;\n" + 
3980
			"import java.io.IOException;\n" + 
3981
			"public class X {\n" +
3982
			"    void foo(boolean f1, boolean f2) throws IOException {\n" + 
3983
			"        File file = new File(\"somefile\");\n" + 
3984
			"        if (f1) {\n" + 
3985
			"            FileReader fileReader = new FileReader(file); // properly closed\n" + 
3986
			"            char[] in = new char[50];\n" + 
3987
			"            fileReader.read(in);\n" + 
3988
			"            while (true) {\n" + 
3989
			"                  fileReader.close();\n" + 
3990
			"                  FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" + 
3991
			"                  loopReader.close();\n" + 
3992
			"                  break;\n" + 
3993
			"            }\n" + 
3994
			"        } else {\n" + 
3995
			"            FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + 
3996
			"            if (f2)\n" + 
3997
			"                fileReader.close();\n" + 
3998
			"        }\n" + 
3999
			"    }\n" + 
4000
			"    public static void main(String[] args) throws IOException {\n" + 
4001
			"        new X().foo(true, true);\n" + 
4002
			"    }\n" + 
4003
			"}\n"
4004
		},
4005
		"----------\n" + 
4006
		"1. ERROR in X.java (at line 18)\n" + 
4007
		"	FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + 
4008
		"	           ^^^^^^^^^^\n" + 
4009
		"Potential resource leak: 'fileReader' may not be closed\n" + 
4010
		"----------\n",
4011
		null,
4012
		true,
4013
		options);
4014
}
4015
// Bug 349326 - [1.7] new warning for missing try-with-resources
4016
// a method uses an AutoCloseable without closing it locally but passing as arg to another method
4017
public void test056j() {
4018
	Map options = getCompilerOptions();
4019
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
4020
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
4021
	this.runNegativeTest(
4022
		new String[] {
4023
			"X.java",
4024
			"import java.io.File;\n" +
4025
			"import java.io.FileReader;\n" +
4026
			"import java.io.IOException;\n" +
4027
			"public class X {\n" +
4028
			"    void foo() throws IOException {\n" +
4029
			"        File file = new File(\"somefile\");\n" +
4030
			"        FileReader fileReader = new FileReader(file);\n" +
4031
			"        read(fileReader);\n" +
4032
			"    }\n" +
4033
			"    void read(FileReader reader) { }\n" +
4034
			"    public static void main(String[] args) throws IOException {\n" +
4035
			"        new X().foo();\n" +
4036
			"    }\n" +
4037
			"}\n"
4038
		},
4039
		"----------\n" + 
4040
		"1. ERROR in X.java (at line 7)\n" + 
4041
		"	FileReader fileReader = new FileReader(file);\n" + 
4042
		"	           ^^^^^^^^^^\n" + 
4043
		"Potential resource leak: 'fileReader' may not be closed\n" + 
4044
		"----------\n",
4045
		null,
4046
		true,
4047
		options);
4048
}
4049
// Bug 349326 - [1.7] new warning for missing try-with-resources
4050
// a method uses an AutoCloseable without closing it locally but passing as arg to another method
4051
public void test056jconditional() {
4052
	Map options = getCompilerOptions();
4053
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
4054
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
4055
	this.runNegativeTest(
4056
		new String[] {
4057
			"X.java",
4058
			"import java.io.File;\n" +
4059
			"import java.io.FileReader;\n" +
4060
			"import java.io.IOException;\n" +
4061
			"public class X {\n" +
4062
			"    void foo(boolean b) throws IOException {\n" +
4063
			"        File file = new File(\"somefile\");\n" +
4064
			"        FileReader fileReader = new FileReader(file);\n" +
4065
			"        synchronized (b ? this : new X()) {\n" +
4066
			"            new ReadDelegator(fileReader);\n" +
4067
			"        }\n" +
4068
			"    }\n" +
4069
			"    class ReadDelegator { ReadDelegator(FileReader reader) { } }\n" +
4070
			"    public static void main(String[] args) throws IOException {\n" +
4071
			"        new X().foo(true);\n" +
4072
			"    }\n" +
4073
			"}\n"
4074
		},
4075
		"----------\n" + 
4076
		"1. ERROR in X.java (at line 7)\n" + 
4077
		"	FileReader fileReader = new FileReader(file);\n" + 
4078
		"	           ^^^^^^^^^^\n" + 
4079
		"Potential resource leak: 'fileReader' may not be closed\n" + 
4080
		"----------\n",
4081
		null,
4082
		true,
4083
		options);
4084
}
4085
// Bug 349326 - [1.7] new warning for missing try-with-resources
4086
// many locals, some are AutoCloseable.
4087
// Unfortunately analysis cannot respect how exception exits may affect ra3 and rb3,
4088
// doing so would create false positives.
4089
public void test056k() {
4090
	Map options = getCompilerOptions();
4091
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
4092
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
4093
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
4094
	this.runNegativeTest(
4095
		new String[] {
4096
			"X.java",
4097
			"import java.io.File;\n" +
4098
			"import java.io.FileReader;\n" +
4099
			"import java.io.IOException;\n" +
4100
			"public class X {\n" +
4101
			"    void foo() throws IOException {\n" +
4102
			"        int i01, i02, i03, i04, i05, i06, i07, i08, i09,\n" +
4103
			"            i11, i12, i13, i14, i15, i16, i17, i18, i19,\n" +
4104
			"            i21, i22, i23, i24, i25, i26, i27, i28, i29,\n" +
4105
			"            i31, i32, i33, i34, i35, i36, i37, i38, i39,\n" +
4106
			"            i41, i42, i43, i44, i45, i46, i47, i48, i49;\n" +
4107
			"        File file = new File(\"somefile\");\n" +
4108
			"        FileReader ra1 = null, ra2 = null;\n" +
4109
			"        try {\n" +
4110
			"            ra1 = new FileReader(file);\n" +
4111
			"            ra2 = new FileReader(file);\n" +
4112
			"            FileReader ra3 = new FileReader(file);\n" +
4113
			"            char[] in = new char[50];\n" +
4114
			"            ra1.read(in);\n" +
4115
			"            ra2.read(in);\n" +
4116
			"            ra3.close();\n" +
4117
			"        } finally {\n" +
4118
			"            ra1.close();\n" +
4119
			"        }\n" +
4120
			"        int i51, i52, i53, i54, i55, i56, i57, i58, i59, i60;\n" + // beyond this point locals are analyzed using extraBits
4121
			"        FileReader rb1 = null, rb2 = null;\n" +
4122
			"        try {\n" +
4123
			"            rb1 = new FileReader(file);\n" +
4124
			"            rb2 = new FileReader(file);\n" +
4125
			"            FileReader rb3 = new FileReader(file);\n" +
4126
			"            char[] in = new char[50];\n" +
4127
			"            rb1.read(in);\n" +
4128
			"            rb2.read(in);\n" +
4129
			"            rb3.close();\n" +
4130
			"        } finally {\n" +
4131
			"            rb1.close();\n" +
4132
			"        }\n" +
4133
			"    }\n" +
4134
			"    public static void main(String[] args) throws IOException {\n" +
4135
			"        new X().foo();\n" +
4136
			"    }\n" +
4137
			"}\n"
4138
		},
4139
		"----------\n" + 
4140
		"1. ERROR in X.java (at line 12)\n" + 
4141
		"	FileReader ra1 = null, ra2 = null;\n" + 
4142
		"	           ^^^\n" + 
4143
		"Resource 'ra1' should be managed by try-with-resource\n" + 
4144
		"----------\n" + 
4145
		"2. ERROR in X.java (at line 15)\n" + 
4146
		"	ra2 = new FileReader(file);\n" + 
4147
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
4148
		"Resource leak: 'ra2' is never closed\n" + 
4149
		"----------\n" + 
4150
		"3. ERROR in X.java (at line 16)\n" + 
4151
		"	FileReader ra3 = new FileReader(file);\n" + 
4152
		"	           ^^^\n" + 
4153
		"Resource 'ra3' should be managed by try-with-resource\n" +
4154
		"----------\n" + 
4155
		"4. ERROR in X.java (at line 25)\n" + 
4156
		"	FileReader rb1 = null, rb2 = null;\n" + 
4157
		"	           ^^^\n" + 
4158
		"Resource 'rb1' should be managed by try-with-resource\n" + 
4159
		"----------\n" + 
4160
		"5. ERROR in X.java (at line 28)\n" + 
4161
		"	rb2 = new FileReader(file);\n" + 
4162
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
4163
		"Resource leak: 'rb2' is never closed\n" + 
4164
		"----------\n" + 
4165
		"6. ERROR in X.java (at line 29)\n" + 
4166
		"	FileReader rb3 = new FileReader(file);\n" + 
4167
		"	           ^^^\n" + 
4168
		"Resource 'rb3' should be managed by try-with-resource\n" + 
4169
		"----------\n",
4170
		null,
4171
		true,
4172
		options);
4173
}
4174
// Bug 349326 - [1.7] new warning for missing try-with-resources
4175
// various non-problems
4176
public void test056l() {
4177
	Map options = getCompilerOptions();
4178
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
4179
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
4180
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
4181
	this.runNegativeTest(
4182
		new String[] {
4183
			"X.java",
4184
			"import java.io.File;\n" +
4185
			"import java.io.FileReader;\n" +
4186
			"import java.io.IOException;\n" +
4187
			"public class X {\n" +
4188
			"    X(FileReader r0) {}\n" + // don't complain against argument
4189
			"    FileReader getReader() { return null; }\n" +
4190
			"    void foo(FileReader r1) throws IOException {\n" +
4191
			"        FileReader fileReader = getReader();\n" +
4192
			"        if (fileReader == null)\n" +
4193
			"            return;\n" + // don't complain, resource is actually null
4194
			"        FileReader r3 = getReader();\n" +
4195
			"        if (r3 == null)\n" +
4196
			"            r3 = new FileReader(new File(\"absent\"));\n" + // don't complain, previous resource is actually null
4197
			"        try {\n" +
4198
			"            char[] in = new char[50];\n" +
4199
			"            fileReader.read(in);\n" +
4200
			"            r1.read(in);\n" +
4201
			"        } finally {\n" +
4202
			"            fileReader.close();\n" +
4203
			"            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
4204
			"        }\n" +
4205
			"    }\n" +
4206
			"    public static void main(String[] args) throws IOException {\n" +
4207
			"        FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" +
4208
			"        new X(r2).foo(new FileReader(new File(\"notthere\")));\n" +
4209
			"    }\n" +
4210
			"}\n"
4211
		},
4212
		"----------\n" + 
4213
		"1. ERROR in X.java (at line 8)\n" + 
4214
		"	FileReader fileReader = getReader();\n" + 
4215
		"	           ^^^^^^^^^^\n" + 
4216
		"Resource 'fileReader' should be managed by try-with-resource\n" + 
4217
		"----------\n" + 
4218
		"2. ERROR in X.java (at line 11)\n" + 
4219
		"	FileReader r3 = getReader();\n" + 
4220
		"	           ^^\n" + 
4221
		"Resource 'r3' should be managed by try-with-resource\n" +
4222
		"----------\n" + 
4223
		"3. ERROR in X.java (at line 24)\n" + 
4224
		"	FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" + 
4225
		"	           ^^\n" + 
4226
		"Potential resource leak: 'r2' may not be closed\n" + 
4227
		"----------\n",
4228
		null,
4229
		true,
4230
		options);
4231
}
4232
// Bug 349326 - [1.7] new warning for missing try-with-resources
4233
// nested try with early exit
4234
public void test056m() {
4235
	Map options = getCompilerOptions();
4236
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
4237
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
4238
	this.runConformTest(
4239
		new String[] {
4240
			"X.java",
4241
			"import java.io.File;\n" +
4242
			"import java.io.FileReader;\n" +
4243
			"import java.io.IOException;\n" +
4244
			"public class X {\n" +
4245
			"    void foo() {\n" +
4246
			"        File file = new File(\"somefile\");" +
4247
			"        try {\n" +
4248
			"            FileReader fileReader = new FileReader(file);\n" +
4249
			"            try {\n" +
4250
			"                char[] in = new char[50];\n" +
4251
			"                if (fileReader.read(in)==0)\n" +
4252
			"                    return;\n" +
4253
			"            } finally {\n" +
4254
			"		         fileReader.close();\n" +
4255
			"            }\n" +
4256
			"        } catch (IOException e) {\n" +
4257
			"            System.out.println(\"caught\");\n" +
4258
			"        }\n" +
4259
			"    }\n" +
4260
			"    public static void main(String[] args) {\n" +
4261
			"        new X().foo();\n" +
4262
			"    }\n" +
4263
			"}\n"
4264
		},
4265
		"caught", /*output*/
4266
		null/*classLibs*/,
4267
		true/*shouldFlush*/,
4268
		null/*vmargs*/,
4269
		options,
4270
		null/*requestor*/);
4271
}
4272
// Bug 349326 - [1.7] new warning for missing try-with-resources
4273
// nested try should not interfere with earlier analysis.
4274
public void test056n() {
4275
	Map options = getCompilerOptions();
4276
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
4277
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
4278
	this.runConformTest(
4279
		new String[] {
4280
			"X.java",
4281
			"import java.io.File;\n" +
4282
			"import java.io.FileReader;\n" +
4283
			"import java.io.IOException;\n" +
4284
			"import java.io.FileNotFoundException;\n" +
4285
			"public class X {\n" +
4286
			"    void foo(File someFile, char[] buf) throws IOException {\n" + 
4287
			"		FileReader fr1 = new FileReader(someFile);\n" + 
4288
			"		try {\n" + 
4289
			"			fr1.read(buf);\n" + 
4290
			"		} finally {\n" + 
4291
			"			fr1.close();\n" + 
4292
			"		}\n" + 
4293
			"		try {\n" + 
4294
			"			FileReader fr3 = new FileReader(someFile);\n" + 
4295
			"			try {\n" + 
4296
			"			} finally {\n" + 
4297
			"				fr3.close();\n" + 
4298
			"			}\n" + 
4299
			"		} catch (IOException e) {\n" + 
4300
			"		}\n" + 
4301
			"	 }\n" +
4302
			"    public static void main(String[] args) throws IOException {\n" +
4303
			"        try {\n" +
4304
			"            new X().foo(new File(\"missing\"), new char[100]);\n" +
4305
			"        } catch (FileNotFoundException e) {\n" +
4306
			"            System.out.println(\"caught\");\n" +
4307
			"        }\n" +
4308
			"    }\n" +
4309
			"}\n"
4310
		},
4311
		"caught", /*output*/
4312
		null/*classLibs*/,
4313
		true/*shouldFlush*/,
4314
		null/*vmargs*/,
4315
		options,
4316
		null/*requestor*/);
4317
}
4318
// Bug 349326 - [1.7] new warning for missing try-with-resources
4319
// if close is guarded by null check this should still be recognized as definitely closed
4320
public void test056o() {
4321
	Map options = getCompilerOptions();
4322
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
4323
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
4324
	this.runConformTest(
4325
		new String[] {
4326
			"X.java",
4327
			"import java.io.File;\n" +
4328
			"import java.io.FileReader;\n" +
4329
			"import java.io.IOException;\n" +
4330
			"import java.io.FileNotFoundException;\n" +
4331
			"public class X {\n" +
4332
			"    void foo(File someFile, char[] buf) throws IOException {\n" + 
4333
			"		FileReader fr1 = null;\n" + 
4334
			"		try {\n" +
4335
			"           fr1 = new FileReader(someFile);" + 
4336
			"			fr1.read(buf);\n" + 
4337
			"		} finally {\n" + 
4338
			"			if (fr1 != null)\n" +
4339
			"               try {\n" +
4340
			"                   fr1.close();\n" +
4341
			"               } catch (IOException e) { /*do nothing*/ }\n" + 
4342
			"		}\n" + 
4343
			"	 }\n" +
4344
			"    public static void main(String[] args) throws IOException {\n" +
4345
			"        try {\n" +
4346
			"            new X().foo(new File(\"missing\"), new char[100]);\n" +
4347
			"        } catch (FileNotFoundException e) {\n" +
4348
			"            System.out.println(\"caught\");\n" +
4349
			"        }\n" +
4350
			"    }\n" +
4351
			"}\n"
4352
		},
4353
		"caught", /*output*/
4354
		null/*classLibs*/,
4355
		true/*shouldFlush*/,
4356
		null/*vmargs*/,
4357
		options,
4358
		null/*requestor*/);
4359
}
4360
// Bug 349326 - [1.7] new warning for missing try-with-resources
4361
// a method uses an AutoCloseable without ever closing it, type from a type variable
4362
public void test056p() {
4363
	Map options = getCompilerOptions();
4364
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
4365
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
4366
	this.runNegativeTest(
4367
		new String[] {
4368
			"X.java",
4369
			"import java.io.File;\n" +
4370
			"import java.io.FileReader;\n" +
4371
			"import java.io.Reader;\n" +
4372
			"import java.io.IOException;\n" +
4373
			"public abstract class X <T extends Reader> {\n" +
4374
			"    void foo() throws IOException {\n" +
4375
			"        File file = new File(\"somefile\");\n" +
4376
			"        T fileReader = newReader(file);\n" +
4377
			"        char[] in = new char[50];\n" +
4378
			"        fileReader.read(in);\n" +
4379
			"    }\n" +
4380
			"    abstract T newReader(File file) throws IOException;\n" +
4381
			"    public static void main(String[] args) throws IOException {\n" +
4382
			"        new X<FileReader>() {\n" +
4383
			"            FileReader newReader(File f) throws IOException { return new FileReader(f); }\n" +
4384
			"        }.foo();\n" +
4385
			"    }\n" +
4386
			"}\n"
4387
		},
4388
		"----------\n" + 
4389
		"1. ERROR in X.java (at line 8)\n" + 
4390
		"	T fileReader = newReader(file);\n" + 
4391
		"	  ^^^^^^^^^^\n" + 
4392
		"Resource leak: 'fileReader' is never closed\n" +
4393
		"----------\n",
4394
		null,
4395
		true,
4396
		options);
4397
}
4398
// Bug 349326 - [1.7] new warning for missing try-with-resources
4399
// closed in dead code
4400
public void test056q() {
4401
	Map options = getCompilerOptions();
4402
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4403
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
4404
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
4405
	this.runNegativeTest(
4406
		new String[] {
4407
			"X.java",
4408
			"import java.io.File;\n" +
4409
			"import java.io.FileReader;\n" +
4410
			"import java.io.IOException;\n" +
4411
			"public class X {\n" +
4412
			"    void foo() throws IOException {\n" +
4413
			"        File file = new File(\"somefile\");\n" +
4414
			"        FileReader fileReader = new FileReader(file);\n" +
4415
			"        char[] in = new char[50];\n" +
4416
			"        fileReader.read(in);\n" +
4417
			"        if (2*2 == 4)\n" +
4418
			"        	return;\n" +
4419
			"        fileReader.close();\n" +
4420
			"    }\n" +
4421
			"    public static void main(String[] args) throws IOException {\n" +
4422
			"        new X().foo();\n" +
4423
			"    }\n" +
4424
			"}\n"
4425
		},
4426
		"----------\n" + 
4427
		"1. ERROR in X.java (at line 7)\n" + 
4428
		"	FileReader fileReader = new FileReader(file);\n" + 
4429
		"	           ^^^^^^^^^^\n" + 
4430
		"Resource leak: 'fileReader' is never closed\n" + 
4431
		"----------\n" + 
4432
		"2. WARNING in X.java (at line 10)\n" + 
4433
		"	if (2*2 == 4)\n" + 
4434
		"	    ^^^^^^^^\n" + 
4435
		"Comparing identical expressions\n" + 
4436
		"----------\n" + 
4437
		"3. WARNING in X.java (at line 12)\n" + 
4438
		"	fileReader.close();\n" + 
4439
		"	^^^^^^^^^^^^^^^^^^\n" + 
4440
		"Dead code\n" + 
4441
		"----------\n",
4442
		null,
4443
		true,
4444
		options);
4445
}
4446
// Bug 349326 - [1.7] new warning for missing try-with-resources
4447
// closed in dead code
4448
public void test056r() {
4449
	Map options = getCompilerOptions();
4450
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4451
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
4452
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
4453
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
4454
	this.runNegativeTest(
4455
		new String[] {
4456
			"X.java",
4457
			"import java.io.File;\n" +
4458
			"import java.io.FileReader;\n" +
4459
			"import java.io.IOException;\n" +
4460
			"public class X {\n" +
4461
			"    void foo() throws IOException {\n" +
4462
			"        File file = new File(\"somefile\");\n" +
4463
			"        FileReader fr = new FileReader(file);\n" +
4464
			"  		 Object b = null;\n" + 
4465
			"        fr.close();\n" + 
4466
			"        if (b != null) {\n" + 
4467
			"            fr = new FileReader(file);\n" + 
4468
			"            return;\n" + 
4469
			"        } else {\n" + 
4470
			"            System.out.print(42);\n" + 
4471
			"        }\n" + 
4472
			"        return;     // Should not complain about fr\n" +
4473
			"    }\n" +
4474
			"    public static void main(String[] args) throws IOException {\n" +
4475
			"        new X().foo();\n" +
4476
			"    }\n" +
4477
			"}\n"
4478
		},
4479
		"----------\n" + 
4480
		"1. ERROR in X.java (at line 10)\n" + 
4481
		"	if (b != null) {\n" + 
4482
		"            fr = new FileReader(file);\n" + 
4483
		"            return;\n" + 
4484
		"        } else {\n" + 
4485
		"	               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
4486
		"Dead code\n" + 
4487
		"----------\n" + 
4488
		"2. WARNING in X.java (at line 13)\n" + 
4489
		"	} else {\n" + 
4490
		"            System.out.print(42);\n" + 
4491
		"        }\n" + 
4492
		"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
4493
		"Statement unnecessarily nested within else clause. The corresponding then clause does not complete normally\n" + 
4494
		"----------\n",
4495
		null,
4496
		true,
4497
		options);
4498
}
4499
// Bug 349326 - [1.7] new warning for missing try-with-resources
4500
// resource inside t-w-r is re-assigned, shouldn't even record an errorLocation
4501
public void test056s() {
4502
	Map options = getCompilerOptions();
4503
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4504
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
4505
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
4506
	this.runNegativeTest(
4507
		new String[] {
4508
			"X.java",
4509
			"import java.io.File;\n" + 
4510
			"import java.io.FileReader;\n" + 
4511
			"import java.io.IOException;\n" + 
4512
			"public class X {\n" + 
4513
			"    void foo() throws IOException {\n" + 
4514
			"        File file = new File(\"somefile\");\n" + 
4515
			"        try (FileReader fileReader = new FileReader(file);) {\n" + 
4516
			"            char[] in = new char[50];\n" + 
4517
			"            fileReader.read(in);\n" + 
4518
			"            fileReader = new FileReader(file);  // debug here\n" + 
4519
			"            fileReader.read(in);\n" + 
4520
			"        }\n" + 
4521
			"    }\n" +
4522
			"    public static void main(String[] args) throws IOException {\n" + 
4523
			"        new X().foo();\n" + 
4524
			"    }\n" + 
4525
			"}\n"
4526
		},
4527
		"----------\n" + 
4528
		"1. ERROR in X.java (at line 10)\n" + 
4529
		"	fileReader = new FileReader(file);  // debug here\n" + 
4530
		"	^^^^^^^^^^\n" + 
4531
		"The resource fileReader of a try-with-resources statement cannot be assigned\n" + 
4532
		"----------\n",
4533
		null,
4534
		true,
4535
		options);
4536
}
4537
// Bug 349326 - [1.7] new warning for missing try-with-resources
4538
// resource is closed, dead code follows
4539
public void test056t() {
4540
	Map options = getCompilerOptions();
4541
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4542
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
4543
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
4544
	this.runNegativeTest(
4545
		new String[] {
4546
			"X.java",
4547
			"import java.io.FileReader;\n" + 
4548
			"import java.io.IOException;\n" + 
4549
			"public class X {\n" + 
4550
			"    void foo31() throws IOException {\n" + 
4551
			"        FileReader reader = new FileReader(\"file\"); //warning\n" +
4552
			"        if (reader != null) {\n" + 
4553
			"            reader.close();\n" + 
4554
			"        } else {\n" + 
4555
			"            // nop\n" + 
4556
			"        }\n" + 
4557
			"    }\n" + 
4558
			"    public static void main(String[] args) throws IOException {\n" + 
4559
			"        new X().foo31();\n" + 
4560
			"    }\n" + 
4561
			"}\n"
4562
		},
4563
		"----------\n" + 
4564
		"1. ERROR in X.java (at line 8)\n" + 
4565
		"	} else {\n" + 
4566
		"            // nop\n" + 
4567
		"        }\n" + 
4568
		"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
4569
		"Dead code\n" + 
4570
		"----------\n",
4571
		null,
4572
		true,
4573
		options);
4574
}
4575
// Bug 349326 - [1.7] new warning for missing try-with-resources
4576
// resource is reassigned within t-w-r with different resource
4577
// was initially broken due to https://bugs.eclipse.org/358827
4578
public void test056u() {
4579
	Map options = getCompilerOptions();
4580
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4581
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
4582
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
4583
	this.runNegativeTest(
4584
		new String[] {
4585
			"X.java",
4586
			"import java.io.FileReader;\n" +
4587
			"public class X {\n" +
4588
			"    void foo() throws Exception {\n" +
4589
			"        FileReader reader1 = new FileReader(\"file1\");\n" +
4590
			"        FileReader reader2 = new FileReader(\"file2\");\n" +
4591
			"        reader2 = reader1;// this disconnects reader 2\n" +
4592
			"        try (FileReader reader3 = new FileReader(\"file3\")) {\n" +
4593
			"            int ch;\n" +
4594
			"            while ((ch = reader2.read()) != -1) {\n" +
4595
			"                System.out.println(ch);\n" +
4596
			"                reader1.read();\n" +
4597
			"            }\n" +
4598
			"            reader2 = reader1; // warning 1 regarding original reader1\n" + // this warning was missing
4599
			"            reader2 = reader1; // warning 2 regarding original reader1\n" +
4600
			"        } finally {\n" +
4601
			"            if (reader2 != null) {\n" +
4602
			"                reader2.close();\n" +
4603
			"            } else {\n" +
4604
			"                System.out.println();\n" +
4605
			"            }\n" +
4606
			"        }\n" +
4607
			"    }\n" +
4608
			"}\n"
4609
		},
4610
		"----------\n" + 
4611
		"1. ERROR in X.java (at line 5)\n" + 
4612
		"	FileReader reader2 = new FileReader(\"file2\");\n" + 
4613
		"	           ^^^^^^^\n" + 
4614
		"Resource leak: 'reader2' is never closed\n" + 
4615
		"----------\n" + 
4616
		"2. ERROR in X.java (at line 13)\n" + 
4617
		"	reader2 = reader1; // warning 1 regarding original reader1\n" + 
4618
		"	^^^^^^^^^^^^^^^^^\n" + 
4619
		"Resource leak: 'reader1' is not closed at this location\n" + 
4620
		"----------\n" + 
4621
		"3. ERROR in X.java (at line 14)\n" + 
4622
		"	reader2 = reader1; // warning 2 regarding original reader1\n" + 
4623
		"	^^^^^^^^^^^^^^^^^\n" + 
4624
		"Resource leak: 'reader1' is not closed at this location\n" + 
4625
		"----------\n",
4626
		null,
4627
		true,
4628
		options);
4629
}
4630
// Bug 349326 - [1.7] new warning for missing try-with-resources
4631
// scope-related pbs reported in https://bugs.eclipse.org/349326#c70 and https://bugs.eclipse.org/349326#c82  
4632
public void test056v() {
4633
	Map options = getCompilerOptions();
4634
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4635
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
4636
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.WARNING);
4637
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
4638
	this.runNegativeTest(
4639
		new String[] {
4640
			"X.java",
4641
			"import java.io.FileReader;\n" + 
4642
			"public class X {\n" + 
4643
			"    boolean foo1() throws Exception {\n" + 
4644
			"        FileReader reader = new FileReader(\"file\");\n" + 
4645
			"        try {\n" + 
4646
			"            int ch;\n" + 
4647
			"            while ((ch = reader.read()) != -1) {\n" + 
4648
			"                System.out.println(ch);\n" + 
4649
			"                reader.read();\n" + 
4650
			"            }\n" + 
4651
			"            if (ch > 10) {\n" + 
4652
			"                return true;\n" + 
4653
			"            }\n" + 
4654
			"            return false;\n" + // return while resource from enclosing scope remains unclosed
4655
			"        } finally {\n" + 
4656
			"        }\n" + 
4657
			"    }\n" + 
4658
			"    void foo111() throws Exception {\n" + 
4659
			"        FileReader reader111 = new FileReader(\"file2\");\n" + 
4660
			"        try {\n" + 
4661
			"            int ch;\n" + 
4662
			"            while ((ch = reader111.read()) != -1) {\n" + 
4663
			"                System.out.println(ch);\n" + 
4664
			"                reader111.read();\n" + 
4665
			"            }\n" + 
4666
			"            return;\n" + // this shouldn't spoil the warning "should be managed with t-w-r" 
4667
			"        } finally {\n" + 
4668
			"            if (reader111 != null) {\n" + 
4669
			"                reader111.close();\n" + 
4670
			"            }\n" + 
4671
			"        }\n" + 
4672
			"    }\n" +
4673
			"    void foo2() throws Exception {\n" + 
4674
			"        FileReader reader2 = new FileReader(\"file\");\n" + 
4675
			"        try {\n" + 
4676
			"            int ch;\n" + 
4677
			"            while ((ch = reader2.read()) != -1) {\n" + 
4678
			"                System.out.println(ch);\n" + 
4679
			"                reader2.read();\n" + 
4680
			"            }\n" + 
4681
			"            if (ch > 10) {\n" + 
4682
			"                return;\n" + // potential leak
4683
			"            }\n" + 
4684
			"        } finally {\n" + 
4685
			"        }\n" +
4686
			"        reader2.close();\n" + // due to this close we don't say "never closed"
4687
			"    }\n" + 
4688
			"}\n"
4689
		},
4690
		"----------\n" + 
4691
		"1. ERROR in X.java (at line 4)\n" + 
4692
		"	FileReader reader = new FileReader(\"file\");\n" + 
4693
		"	           ^^^^^^\n" + 
4694
		"Resource leak: 'reader' is never closed\n" + 
4695
		"----------\n" + 
4696
		"2. WARNING in X.java (at line 19)\n" + 
4697
		"	FileReader reader111 = new FileReader(\"file2\");\n" + 
4698
		"	           ^^^^^^^^^\n" + 
4699
		"Resource 'reader111' should be managed by try-with-resource\n" + 
4700
		"----------\n" + 
4701
		"3. ERROR in X.java (at line 42)\n" + 
4702
		"	return;\n" + 
4703
		"	^^^^^^^\n" + 
4704
		"Resource leak: 'reader2' is not closed at this location\n" + 
4705
		"----------\n",
4706
		null,
4707
		true,
4708
		options);
4709
}
4710
// Bug 349326 - [1.7] new warning for missing try-with-resources
4711
// end of method is dead end, but before we have both a close() and an early return
4712
public void test056w() {
4713
	Map options = getCompilerOptions();
4714
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4715
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
4716
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
4717
	this.runNegativeTest(
4718
		new String[] {
4719
			"X.java",
4720
			"import java.io.FileReader;\n" + 
4721
			"public class X {\n" + 
4722
			"    boolean foo1() throws Exception {\n" + 
4723
			"        FileReader reader = new FileReader(\"file\");\n" + 
4724
			"        try {\n" + 
4725
			"            int ch;\n" + 
4726
			"            while ((ch = reader.read()) != -1) {\n" + 
4727
			"                System.out.println(ch);\n" + 
4728
			"                reader.read();\n" + 
4729
			"            }\n" + 
4730
			"            if (ch > 10) {\n" +
4731
			"				 reader.close();\n" + 
4732
			"                return true;\n" + 
4733
			"            }\n" + 
4734
			"            return false;\n" + 
4735
			"        } finally {\n" + 
4736
			"        }\n" + 
4737
			"    }\n" + 
4738
			"}\n"
4739
		},
4740
		"----------\n" + 
4741
		"1. ERROR in X.java (at line 15)\n" + 
4742
		"	return false;\n" + 
4743
		"	^^^^^^^^^^^^^\n" + 
4744
		"Resource leak: 'reader' is not closed at this location\n" + 
4745
		"----------\n",
4746
		null,
4747
		true,
4748
		options);
4749
}
4750
// Bug 349326 - [1.7] new warning for missing try-with-resources
4751
// different early exits, if no close seen report as definitely unclosed
4752
public void test056x() {
4753
	Map options = getCompilerOptions();
4754
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4755
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
4756
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
4757
	this.runNegativeTest(
4758
		new String[] {
4759
			"X.java",
4760
			"import java.io.FileReader;\n" +
4761
			"public class X {\n" +
4762
			"    void foo31(boolean b) throws Exception {\n" +
4763
			"        FileReader reader = new FileReader(\"file\");\n" +
4764
			"        if (b) {\n" +
4765
			"            reader.close();\n" +
4766
			"        } else {\n" +
4767
			"            return; // warning\n" +
4768
			"        }\n" +
4769
			"    }\n" +
4770
			"    void foo32(boolean b) throws Exception {\n" +
4771
			"        FileReader reader = new FileReader(\"file\"); // warn here\n" +
4772
			"        return;\n" +
4773
			"    }\n" +
4774
			"}\n"
4775
		},
4776
		"----------\n" +
4777
		"1. ERROR in X.java (at line 8)\n" +
4778
		"	return; // warning\n" +
4779
		"	^^^^^^^\n" +
4780
		"Resource leak: 'reader' is not closed at this location\n" +
4781
		"----------\n" +
4782
		"2. ERROR in X.java (at line 12)\n" +
4783
		"	FileReader reader = new FileReader(\"file\"); // warn here\n" +
4784
		"	           ^^^^^^\n" +
4785
		"Resource leak: 'reader' is never closed\n" +
4786
		"----------\n",
4787
		null,
4788
		true,
4789
		options);
4790
}
4791
// Bug 349326 - [1.7] new warning for missing try-with-resources
4792
// nested method passes the resource to outside code
4793
public void test056y() {
4794
	Map options = getCompilerOptions();
4795
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4796
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
4797
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
4798
	this.runNegativeTest(
4799
		new String[] {
4800
			"X.java",
4801
			"import java.io.FileReader;\n" +
4802
			"public class X {\n" +
4803
			"    void foo31(boolean b) throws Exception {\n" +
4804
			"        final FileReader reader31 = new FileReader(\"file\");\n" +
4805
			"        new Runnable() {\n" +
4806
			"            public void run() {\n" +
4807
			"                foo18(reader31);\n" +
4808
			"            }\n" +
4809
			"        }.run();\n" +
4810
			"    }\n" +
4811
			"    void foo18(FileReader r18) {\n" +
4812
			"        // could theoretically close r18;\n" +
4813
			"    }\n" +
4814
			"    abstract class ResourceProvider {\n" +
4815
			"        abstract FileReader provide();" +
4816
			"    }\n" +
4817
			"    ResourceProvider provider;" +
4818
			"    void foo23() throws Exception {\n" +
4819
			"        final FileReader reader23 = new FileReader(\"file\");\n" +
4820
			"        provider = new ResourceProvider() {\n" +
4821
			"            public FileReader provide() {\n" +
4822
			"                return reader23;\n" +
4823
			"            }\n" +
4824
			"        };\n" +
4825
			"    }\n" +
4826
			"}\n"
4827
		},
4828
		"----------\n" + 
4829
		"1. WARNING in X.java (at line 4)\n" + 
4830
		"	final FileReader reader31 = new FileReader(\"file\");\n" + 
4831
		"	                 ^^^^^^^^\n" + 
4832
		"Potential resource leak: 'reader31' may not be closed\n" + 
4833
		"----------\n" + 
4834
		"2. WARNING in X.java (at line 17)\n" + 
4835
		"	final FileReader reader23 = new FileReader(\"file\");\n" + 
4836
		"	                 ^^^^^^^^\n" + 
4837
		"Potential resource leak: 'reader23' may not be closed\n" + 
4838
		"----------\n",
4839
		null,
4840
		true,
4841
		options);
4842
}
4843
// Bug 349326 - [1.7] new warning for missing try-with-resources
4844
// resource assigned to second local and is (potentially) closed on the latter
4845
public void test056z() {
4846
	Map options = getCompilerOptions();
4847
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4848
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4849
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
4850
	this.runNegativeTest(
4851
		new String[] {
4852
			"X.java",
4853
			"import java.io.FileReader;\n" +
4854
			"public class X {\n" +
4855
			"    void foo17() throws Exception {\n" +
4856
			"        FileReader reader17 = new FileReader(\"file\");\n" +
4857
			"        final FileReader readerCopy = reader17;\n" +
4858
			"        readerCopy.close();\n" +
4859
			"    }\n" +
4860
			"    void foo17a() throws Exception {\n" +
4861
			"        FileReader reader17a = new FileReader(\"file\");\n" +
4862
			"        FileReader readerCopya;" +
4863
			"		 readerCopya = reader17a;\n" +
4864
			"        bar(readerCopya);\n" + // potentially closes
4865
			"    }\n" +
4866
			"    void bar(FileReader r) {}\n" +
4867
			"}\n"
4868
		},
4869
		"----------\n" + 
4870
		"1. ERROR in X.java (at line 9)\n" + 
4871
		"	FileReader reader17a = new FileReader(\"file\");\n" + 
4872
		"	           ^^^^^^^^^\n" + 
4873
		"Potential resource leak: 'reader17a' may not be closed\n" + 
4874
		"----------\n",
4875
		null,
4876
		true,
4877
		options);
4878
}
4879
// Bug 349326 - [1.7] new warning for missing try-with-resources
4880
// multiple early exists from nested scopes (always closed) 
4881
public void test056zz() {
4882
	Map options = getCompilerOptions();
4883
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4884
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4885
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
4886
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
4887
	this.runNegativeTest(
4888
		new String[] {
4889
			"X.java",
4890
			"import java.io.FileReader;\n" +
4891
			"public class X {\n" +
4892
			"    void foo16() throws Exception {\n" +
4893
			"        FileReader reader16 = new FileReader(\"file\");\n" +
4894
			"        try {\n" +
4895
			"            reader16.close();\n " +
4896
			"            return;\n" +
4897
			"        } catch (RuntimeException re) {\n" +
4898
			"            return;\n" +
4899
			"        } catch (Error e) {\n" +
4900
			"            return;\n" +
4901
			"        } finally {\n" +
4902
			"            reader16.close();\n " +
4903
			"        }\n" +
4904
			"    }\n" +
4905
			"}\n"
4906
		},
4907
		"----------\n" + 
4908
		"1. ERROR in X.java (at line 4)\n" + 
4909
		"	FileReader reader16 = new FileReader(\"file\");\n" + 
4910
		"	           ^^^^^^^^\n" + 
4911
		"Resource 'reader16' should be managed by try-with-resource\n" + 
4912
		"----------\n",
4913
		null,
4914
		true,
4915
		options);
4916
}
4917
// Bug 349326 - [1.7] new warning for missing try-with-resources
4918
// multiple early exists from nested scopes (never closed) 
4919
public void test056zzz() {
4920
	Map options = getCompilerOptions();
4921
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4922
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4923
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
4924
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
4925
	this.runNegativeTest(
4926
		new String[] {
4927
			"X.java",
4928
			"import java.io.FileReader;\n" +
4929
			"public class X {\n" +
4930
			"    void foo16() throws Exception {\n" +
4931
			"        FileReader reader16 = new FileReader(\"file\");\n" +
4932
			"        try {\n" +
4933
			"            return;\n" +
4934
			"        } catch (RuntimeException re) {\n" +
4935
			"            return;\n" +
4936
			"        } catch (Error e) {\n" +
4937
			"            return;\n" +
4938
			"        } finally {\n" +
4939
			"            System.out.println();\n " +
4940
			"        }\n" +
4941
			"    }\n" +
4942
			"}\n"
4943
		},
4944
		"----------\n" + 
4945
		"1. ERROR in X.java (at line 4)\n" + 
4946
		"	FileReader reader16 = new FileReader(\"file\");\n" + 
4947
		"	           ^^^^^^^^\n" + 
4948
		"Resource leak: 'reader16' is never closed\n" + 
4949
		"----------\n",
4950
		null,
4951
		true,
4952
		options);
4953
}
4954
// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
4955
// explicit throw is a true method exit here
4956
public void test056throw1() {
4957
	Map options = getCompilerOptions();
4958
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4959
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4960
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
4961
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
4962
	this.runNegativeTest(
4963
		new String[] {
4964
			"X.java",
4965
			"import java.io.FileReader;\n" +
4966
			"public class X {\n" +
4967
			"    void foo2(boolean a, boolean b, boolean c) throws Exception {\n" +
4968
			"        FileReader reader = new FileReader(\"file\");\n" +
4969
			"        if(a)\n" +
4970
			"            throw new Exception();    //warning 1\n" +
4971
			"        else if (b)\n" +
4972
			"            reader.close();\n" +
4973
			"        else if(c)\n" +
4974
			"            throw new Exception();    //warning 2\n" +
4975
			"        reader.close();\n" +
4976
			"    }\n" +
4977
			"}\n"
4978
		},
4979
		"----------\n" + 
4980
		"1. ERROR in X.java (at line 6)\n" +
4981
		"	throw new Exception();    //warning 1\n" +
4982
		"	^^^^^^^^^^^^^^^^^^^^^^\n" +
4983
		"Resource leak: 'reader' is not closed at this location\n" +
4984
		"----------\n" +
4985
		"2. ERROR in X.java (at line 10)\n" +
4986
		"	throw new Exception();    //warning 2\n" +
4987
		"	^^^^^^^^^^^^^^^^^^^^^^\n" +
4988
		"Resource leak: 'reader' is not closed at this location\n" +
4989
		"----------\n",
4990
		null,
4991
		true,
4992
		options);	
4993
}
4994
// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
4995
// close() within finally provides protection for throw
4996
public void test056throw2() {
4997
	Map options = getCompilerOptions();
4998
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4999
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
5000
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
5001
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
5002
	this.runNegativeTest(
5003
		new String[] {
5004
			"X.java",
5005
			"import java.io.FileReader;\n" +
5006
			"public class X {\n" +
5007
			"    void foo1() throws Exception {\n" + 
5008
			"        FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + 
5009
			"        try {\n" + 
5010
			"            reader.read();\n" + 
5011
			"            return;\n" + 
5012
			"        } catch (Exception e) {\n" + 
5013
			"            throw new Exception();\n" + 
5014
			"        } finally {\n" + 
5015
			"            reader.close();\n" + 
5016
			"        }\n" + 
5017
			"    }\n" + 
5018
			"\n" + 
5019
			"    void foo2() throws Exception {\n" + 
5020
			"        FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + 
5021
			"        try {\n" + 
5022
			"            reader.read();\n" + 
5023
			"            throw new Exception(); // should not warn here\n" + 
5024
			"        } catch (Exception e) {\n" + 
5025
			"            throw new Exception();\n" + 
5026
			"        } finally {\n" + 
5027
			"            reader.close();\n" + 
5028
			"        }\n" + 
5029
			"    }\n" + 
5030
			"\n" + 
5031
			"    void foo3() throws Exception {\n" + 
5032
			"        FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + 
5033
			"        try {\n" + 
5034
			"            reader.read();\n" + 
5035
			"            throw new Exception();\n" + 
5036
			"        } finally {\n" + 
5037
			"            reader.close();\n" + 
5038
			"        }\n" + 
5039
			"    }\n" + 
5040
			"}\n"
5041
		},
5042
		"----------\n" +
5043
		"1. ERROR in X.java (at line 4)\n" +
5044
		"	FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
5045
		"	           ^^^^^^\n" +
5046
		"Resource 'reader' should be managed by try-with-resource\n" +
5047
		"----------\n" +
5048
		"2. ERROR in X.java (at line 16)\n" +
5049
		"	FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
5050
		"	           ^^^^^^\n" +
5051
		"Resource 'reader' should be managed by try-with-resource\n" +
5052
		"----------\n" +
5053
		"3. ERROR in X.java (at line 28)\n" +
5054
		"	FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" +
5055
		"	           ^^^^^^\n" +
5056
		"Resource 'reader' should be managed by try-with-resource\n" +
5057
		"----------\n",
5058
		null,
5059
		true,
5060
		options);	
5061
}
5062
// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
5063
// close() nested within finally provides protection for throw
5064
public void test056throw3() {
5065
	Map options = getCompilerOptions();
5066
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
5067
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
5068
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
5069
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
5070
	this.runNegativeTest(
5071
		new String[] {
5072
			"X.java",
5073
			"import java.io.FileReader;\n" +
5074
			"public class X {\n" +
5075
			"    void foo2x() throws Exception {\n" + 
5076
			"        FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + 
5077
			"        try {\n" + 
5078
			"            reader.read();\n" + 
5079
			"            throw new Exception(); // should not warn here\n" + 
5080
			"        } catch (Exception e) {\n" + 
5081
			"            throw new Exception();\n" + 
5082
			"        } finally {\n" +
5083
			"            if (reader != null)\n" +
5084
			"                 try {\n" + 
5085
			"                     reader.close();\n" +
5086
			"                 } catch (java.io.IOException io) {}\n" + 
5087
			"        }\n" + 
5088
			"    }\n" + 
5089
			"}\n"
5090
		},
5091
		"----------\n" + 
5092
		"1. ERROR in X.java (at line 4)\n" + 
5093
		"	FileReader reader = new FileReader(\"file\"); // propose t-w-r\n" + 
5094
		"	           ^^^^^^\n" + 
5095
		"Resource 'reader' should be managed by try-with-resource\n" + 
5096
		"----------\n",
5097
		null,
5098
		true,
5099
		options);	
5100
}
5101
// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
5102
// additional boolean should shed doubt on whether we reach the close() call
5103
public void test056throw4() {
5104
	Map options = getCompilerOptions();
5105
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
5106
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
5107
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
5108
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
5109
	this.runNegativeTest(
5110
		new String[] {
5111
			"X.java",
5112
			"import java.io.FileReader;\n" +
5113
			"public class X {\n" +
5114
			"    void foo2x(boolean b) throws Exception {\n" + 
5115
			"        FileReader reader = new FileReader(\"file\");\n" + 
5116
			"        try {\n" + 
5117
			"            reader.read();\n" + 
5118
			"            throw new Exception(); // should warn here\n" + 
5119
			"        } catch (Exception e) {\n" + 
5120
			"            throw new Exception(); // should warn here\n" + 
5121
			"        } finally {\n" +
5122
			"            if (reader != null && b)\n" + // this condition is too strong to protect reader
5123
			"                 try {\n" + 
5124
			"                     reader.close();\n" +
5125
			"                 } catch (java.io.IOException io) {}\n" + 
5126
			"        }\n" + 
5127
			"    }\n" + 
5128
			"}\n"
5129
		},
5130
		"----------\n" +
5131
		"1. ERROR in X.java (at line 7)\n" +
5132
		"	throw new Exception(); // should warn here\n" +
5133
		"	^^^^^^^^^^^^^^^^^^^^^^\n" +
5134
		"Potential resource leak: 'reader' may not be closed at this location\n" +
5135
		"----------\n" +
5136
		"2. ERROR in X.java (at line 9)\n" +
5137
		"	throw new Exception(); // should warn here\n" +
5138
		"	^^^^^^^^^^^^^^^^^^^^^^\n" +
5139
		"Potential resource leak: 'reader' may not be closed at this location\n" +
5140
		"----------\n",
5141
		null,
5142
		true,
5143
		options);	
5144
}
5145
// Bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
5146
// similar to test056throw3() but indirectly calling close(), so doubts remain.
5147
public void test056throw5() {
5148
	Map options = getCompilerOptions();
5149
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
5150
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
5151
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.ERROR);
5152
	options.put(JavaCore.COMPILER_PB_DEAD_CODE, CompilerOptions.ERROR);
5153
	this.runNegativeTest(
5154
		new String[] {
5155
			"X.java",
5156
			"import java.io.FileReader;\n" +
5157
			"public class X {\n" +
5158
			"    void foo2x() throws Exception {\n" +
5159
			"        FileReader reader = new FileReader(\"file\");\n" +
5160
			"        try {\n" +
5161
			"            reader.read();\n" +
5162
			"            throw new Exception(); // should warn 'may not' here\n" +
5163
			"        } catch (Exception e) {\n" +
5164
			"            throw new Exception(); // should warn 'may not' here\n" +
5165
			"        } finally {\n" +
5166
			"            doClose(reader);\n" +
5167
			"        }\n" +
5168
			"    }\n" +
5169
			"    void doClose(FileReader r) { try { r.close(); } catch (java.io.IOException ex) {}}\n" + 
5170
			"}\n"
5171
		},
5172
		"----------\n" +
5173
		"1. ERROR in X.java (at line 7)\n" +
5174
		"	throw new Exception(); // should warn \'may not\' here\n" +
5175
		"	^^^^^^^^^^^^^^^^^^^^^^\n" +
5176
		"Potential resource leak: 'reader' may not be closed at this location\n" +
5177
		"----------\n" +
5178
		"2. ERROR in X.java (at line 9)\n" +
5179
		"	throw new Exception(); // should warn \'may not\' here\n" +
5180
		"	^^^^^^^^^^^^^^^^^^^^^^\n" +
5181
		"Potential resource leak: 'reader' may not be closed at this location\n" +
5182
		"----------\n",
5183
		null,
5184
		true,
5185
		options);	
5186
}
5187
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=361053
5188
public void test057() {
5189
	this.runConformTest(
5190
		new String[] {
5191
			"X.java",
5192
			"public class X implements AutoCloseable {\n" +
5193
			"	@Override\n" +
5194
			"	public void close() throws Exception {\n" +
5195
			"		throw new Exception();\n" +
5196
			"	}\n" +
5197
			"	public static void main(String[] args) {\n" +
5198
			"		final boolean foo;\n" +
5199
			"		try (X a = new X(); X b = new X()) {\n" +
5200
			"			foo = true;\n" +
5201
			"		} catch (final Exception exception) {\n" +
5202
			"			return;\n" +
5203
			"		}\n" +
5204
			"	}\n" +
5205
			"}\n"
5206
		},  "");	
5207
}
5208
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=364008
5209
public void test058() {
5210
	this.runConformTest(
5211
		new String[] {
5212
			"X.java",
5213
			"import java.io.ByteArrayOutputStream;\n" +
5214
			"import java.io.FileOutputStream;\n" +
5215
			"import java.io.IOException;\n" +
5216
			"\n" +
5217
			"public class X {\n" +
5218
			"\n" +
5219
			"  public static void main(final String[] args) throws IOException {\n" +
5220
			"    byte[] data;\n" +
5221
			"    try (final ByteArrayOutputStream os = new ByteArrayOutputStream();\n" +
5222
			"         final FileOutputStream out = new FileOutputStream(\"test.dat\")) {\n" +
5223
			"      data = os.toByteArray();\n" +
5224
			"    }\n" +
5225
			"  }\n" +
5226
			"}\n"
5227
		},  "");	
5228
}
5229
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=367566 - In try-with-resources statement close() method of resource is not called
5230
public void test059() {
5231
	this.runConformTest(
5232
		new String[] {
5233
			"X.java",
5234
			"import java.io.IOException;\n" +
5235
			"\n" +
5236
			"public class X implements java.lang.AutoCloseable {\n" +
5237
			"  static boolean isOpen = true;\n" +
5238
			"  public static void main(final String[] args) throws IOException {\n" +
5239
			"    foo();\n" +
5240
			"    System.out.println(isOpen);\n" +
5241
			"  }\n" +
5242
			"  static boolean foo() {\n" +
5243
			"    try (final X x = new X()) {\n" +
5244
			"      return x.num() >= 1;\n" +
5245
			"    }\n" +
5246
			"  }\n" +
5247
			"  int num() { return 2; }\n" +
5248
			"  public void close() {\n" +
5249
			"    isOpen = false;\n" +
5250
			"  }\n" +
5251
			"}\n"
5252
		},  
5253
		"false");	
5254
}
5255
5256
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=367566 - In try-with-resources statement close() method of resource is not called
5257
public void test060() {
5258
	this.runConformTest(
5259
		new String[] {
5260
			"X.java",
5261
			"public class X implements AutoCloseable {\n" +
5262
			"	static int num = 10 ;\n" +
5263
			"    public static void main(String [] args) throws Exception { \n" +
5264
			"    	System.out.println(foo(1));\n" +
5265
			"    	System.out.println(foo(2));\n" +
5266
			"    	System.out.println(foo(3));\n" +
5267
			"    }\n" +
5268
			"	private static boolean foo(int where) throws Exception {\n" +
5269
			"		final boolean getOut = true;\n" +
5270
			"    	System.out.println(\"Main\");\n" +
5271
			"    	try (X x1 = new X(); X x2 = new X()) {\n" +
5272
			"    		if (where == 1) {\n" +
5273
			"    			return where == 1;\n" +
5274
			"    		}\n" +
5275
			"            System.out.println(\"Outer Try\");\n" +
5276
			"            while (true) {\n" +
5277
			"            	try (Y y1 = new Y(); Y y2 = new Y()) { \n" +
5278
			"            		if (where == 2) {\n" +
5279
			"            			return where == 2;\n" +
5280
			"            		}		\n" +
5281
			"            		System.out.println(\"Middle Try\");\n" +
5282
			"            		try (Z z1 = new Z(); Z z2 = new Z()) {\n" +
5283
			"            			System.out.println(\"Inner Try\");\n" +
5284
			"            			if (getOut) \n" +
5285
			"            				return num >= 10;\n" +
5286
			"            			else\n" +
5287
			"            				break; \n" +
5288
			"            		}\n" +
5289
			"            	}\n" +
5290
			"            }\n" +
5291
			"            System.out.println(\"Out of while\");\n" +
5292
			"        }\n" +
5293
			"		return false;\n" +
5294
			"	}\n" +
5295
			"    public X() {\n" +
5296
			"        System.out.println(\"X::X\");\n" +
5297
			"    }\n" +
5298
			"    @Override\n" +
5299
			"	public void close() throws Exception {\n" +
5300
			"        System.out.println(\"X::~X\");\n" +
5301
			"    }\n" +
5302
			"}\n" +
5303
			"class Y implements AutoCloseable {\n" +
5304
			"    public Y() {\n" +
5305
			"        System.out.println(\"Y::Y\");\n" +
5306
			"    }\n" +
5307
			"    @Override\n" +
5308
			"	public void close() throws Exception {\n" +
5309
			"        System.out.println(\"Y::~Y\");\n" +
5310
			"    }\n" +
5311
			"}\n" +
5312
			"class Z implements AutoCloseable {\n" +
5313
			"    public Z() {\n" +
5314
			"        System.out.println(\"Z::Z\");\n" +
5315
			"    }\n" +
5316
			"    @Override\n" +
5317
			"	public void close() throws Exception {\n" +
5318
			"        System.out.println(\"Z::~Z\");\n" +
5319
			"    }\n" +
5320
			"}\n"
5321
		}, 
5322
		"Main\n" + 
5323
		"X::X\n" + 
5324
		"X::X\n" + 
5325
		"X::~X\n" + 
5326
		"X::~X\n" + 
5327
		"true\n" + 
5328
		"Main\n" + 
5329
		"X::X\n" + 
5330
		"X::X\n" + 
5331
		"Outer Try\n" + 
5332
		"Y::Y\n" + 
5333
		"Y::Y\n" + 
5334
		"Y::~Y\n" + 
5335
		"Y::~Y\n" + 
5336
		"X::~X\n" + 
5337
		"X::~X\n" + 
5338
		"true\n" + 
5339
		"Main\n" + 
5340
		"X::X\n" + 
5341
		"X::X\n" + 
5342
		"Outer Try\n" + 
5343
		"Y::Y\n" + 
5344
		"Y::Y\n" + 
5345
		"Middle Try\n" + 
5346
		"Z::Z\n" + 
5347
		"Z::Z\n" + 
5348
		"Inner Try\n" + 
5349
		"Z::~Z\n" + 
5350
		"Z::~Z\n" + 
5351
		"Y::~Y\n" + 
5352
		"Y::~Y\n" + 
5353
		"X::~X\n" + 
5354
		"X::~X\n" + 
5355
		"true");
5356
}
5357
5358
public static Class testClass() {
3626
public static Class testClass() {
5359
	return TryWithResourcesStatementTest.class;
3627
	return TryWithResourcesStatementTest.class;
5360
}
3628
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java (-3 / +14 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 12-17 Link Here
12
 *     						bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
12
 *     						bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
13
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
13
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
14
 * 							bug 186342 - [compiler][null] Using annotations for null checking
14
 * 							bug 186342 - [compiler][null] Using annotations for null checking
15
 *							bug 358903 - Filter practically unimportant resource leak warnings
15
 *******************************************************************************/
16
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.ast;
17
package org.eclipse.jdt.internal.compiler.ast;
17
18
Lines 37-61 public class AllocationExpression extends Expression implements InvocationSite { Link Here
37
	protected TypeBinding typeExpected;	  // for <> inference
38
	protected TypeBinding typeExpected;	  // for <> inference
38
	public boolean inferredReturnType;
39
	public boolean inferredReturnType;
39
40
41
	public FakedTrackingVariable closeTracker;	// when allocation a Closeable store a pre-liminary tracking variable here
42
40
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
43
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
41
	// check captured variables are initialized in current context (26134)
44
	// check captured variables are initialized in current context (26134)
42
	checkCapturedLocalInitializationIfNecessary((ReferenceBinding)this.binding.declaringClass.erasure(), currentScope, flowInfo);
45
	checkCapturedLocalInitializationIfNecessary((ReferenceBinding)this.binding.declaringClass.erasure(), currentScope, flowInfo);
43
46
44
	// process arguments
47
	// process arguments
45
	if (this.arguments != null) {
48
	if (this.arguments != null) {
49
		boolean hasResourceWrapperType = this.resolvedType instanceof ReferenceBinding 
50
				&& ((ReferenceBinding)this.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable);
46
		for (int i = 0, count = this.arguments.length; i < count; i++) {
51
		for (int i = 0, count = this.arguments.length; i < count; i++) {
47
			// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
48
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
49
			flowInfo =
52
			flowInfo =
50
				this.arguments[i]
53
				this.arguments[i]
51
					.analyseCode(currentScope, flowContext, flowInfo)
54
					.analyseCode(currentScope, flowContext, flowInfo)
52
					.unconditionalInits();
55
					.unconditionalInits();
56
			// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
57
			if (!hasResourceWrapperType) { // allocation of wrapped closeables is analyzed specially
58
				flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, false);
59
			}
53
			if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
60
			if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
54
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
61
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
55
			}
62
			}
56
		}
63
		}
57
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
64
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
58
	}
65
	}
66
67
	if (FakedTrackingVariable.isAnyCloseable(this.resolvedType))
68
		FakedTrackingVariable.analyseCloseableAllocation(currentScope, flowInfo, this);
69
59
	// record some dependency information for exception types
70
	// record some dependency information for exception types
60
	ReferenceBinding[] thrownExceptions;
71
	ReferenceBinding[] thrownExceptions;
61
	if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) {
72
	if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java (-11 / +20 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 14-19 Link Here
14
 *     						bug 335093 - [compiler][null] minimal hook for future null annotation support
14
 *     						bug 335093 - [compiler][null] minimal hook for future null annotation support
15
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
15
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
16
 *							bug 186342 - [compiler][null] Using annotations for null checking
16
 *							bug 186342 - [compiler][null] Using annotations for null checking
17
 *							bug 358903 - Filter practically unimportant resource leak warnings
17
 *******************************************************************************/
18
 *******************************************************************************/
18
package org.eclipse.jdt.internal.compiler.ast;
19
package org.eclipse.jdt.internal.compiler.ast;
19
20
Lines 46-64 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl Link Here
46
	if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
47
	if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
47
		this.expression.checkNPE(currentScope, flowContext, flowInfo);
48
		this.expression.checkNPE(currentScope, flowContext, flowInfo);
48
	}
49
	}
50
	
51
	FlowInfo preInitInfo = null;
52
	boolean shouldAnalyseResource = local != null 
53
			&& flowInfo.reachMode() == FlowInfo.REACHABLE 
54
			&& (FakedTrackingVariable.isAnyCloseable(this.expression.resolvedType)
55
					|| this.expression.resolvedType == TypeBinding.NULL);
56
	if (shouldAnalyseResource) {
57
		preInitInfo = flowInfo.unconditionalCopy();
58
		// analysis of resource leaks needs additional context while analyzing the RHS:
59
		FakedTrackingVariable.preConnectTrackerAcrossAssignment(this, local, this.expression);
60
	}
61
	
49
	flowInfo = ((Reference) this.lhs)
62
	flowInfo = ((Reference) this.lhs)
50
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
63
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
51
		.unconditionalInits();
64
		.unconditionalInits();
52
	if (local != null) {
65
53
		LocalVariableBinding previousTrackerBinding = null;
66
	if (shouldAnalyseResource)
54
		if (local.closeTracker != null) {
67
		FakedTrackingVariable.handleResourceAssignment(currentScope, preInitInfo, flowInfo, this, this.expression, local);
55
			// Assigning to a variable already holding an AutoCloseable, has it been closed before?
68
	else
56
			previousTrackerBinding = local.closeTracker.binding;
69
		FakedTrackingVariable.cleanUpAfterAssignment(currentScope, this.lhs.bits, this.expression);
57
			if (!flowInfo.isDefinitelyNull(local)) // only if previous value may be non-null
70
58
				local.closeTracker.recordErrorLocation(this, flowInfo.nullStatus(previousTrackerBinding));
59
		}
60
		FakedTrackingVariable.handleResourceAssignment(flowInfo, this, this.expression, local, previousTrackerBinding);
61
	}
62
	int nullStatus = this.expression.nullStatus(flowInfo);
71
	int nullStatus = this.expression.nullStatus(flowInfo);
63
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
72
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
64
		if (nullStatus == FlowInfo.NULL) {
73
		if (nullStatus == FlowInfo.NULL) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java (-70 / +553 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2011 GK Software AG and others.
2
 * Copyright (c) 2011, 2012 GK Software AG and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 14-21 import java.util.HashMap; Link Here
14
import java.util.Iterator;
14
import java.util.Iterator;
15
import java.util.Map;
15
import java.util.Map;
16
import java.util.Map.Entry;
16
import java.util.Map.Entry;
17
import java.util.Set;
17
18
18
import org.eclipse.jdt.core.compiler.CharOperation;
19
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
19
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
20
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
20
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
21
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
21
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
Lines 42-67 public class FakedTrackingVariable extends LocalDeclaration { Link Here
42
42
43
	// a call to close() was seen at least on one path:
43
	// a call to close() was seen at least on one path:
44
	private static final int CLOSE_SEEN = 1;
44
	private static final int CLOSE_SEEN = 1;
45
	// the resource was passed to outside code (arg in method/ctor call or as a return value from this method):
45
	// the resource is shared with outside code either by
46
	private static final int PASSED_TO_OUTSIDE = 2;
46
	// - passing as an arg in a method call or
47
	// - obtaining this from a method call or array reference
48
	// Interpret that we may or may not be responsible for closing
49
	private static final int SHARED_WITH_OUTSIDE = 2;
50
	// the resource is likely owned by outside code (owner has responsibility to close): 
51
	// - obtained as argument of the current method, or via a field read
52
	// - returned as the result of this method 
53
	private static final int OWNED_BY_OUTSIDE = 4;
47
	// If close() is invoked from a nested method (inside a local type) report remaining problems only as potential:
54
	// If close() is invoked from a nested method (inside a local type) report remaining problems only as potential:
48
	private static final int CLOSED_IN_NESTED_METHOD = 4;
55
	private static final int CLOSED_IN_NESTED_METHOD = 8;
49
	// a location independent issue has been reported already against this resource:
56
	// explicit closing has been reported already against this resource:
50
	private static final int REPORTED = 8;
57
	private static final int REPORTED_EXPLICIT_CLOSE = 16;
51
	
58
	// a location independent potential problem has been reported against this resource:
59
	private static final int REPORTED_POTENTIAL_LEAK = 32;
60
	// a location independent definitive problem has been reported against this resource:
61
	private static final int REPORTED_DEFINITIVE_LEAK = 64;
62
52
	/**
63
	/**
53
	 * Bitset of {@link #CLOSE_SEEN}, {@link #PASSED_TO_OUTSIDE}, {@link #CLOSED_IN_NESTED_METHOD} and {@link #REPORTED}.
64
	 * 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}.
54
	 */
65
	 */
55
	private int globalClosingState = 0;
66
	private int globalClosingState = 0;
56
67
57
	MethodScope methodScope; // designates the method declaring this variable
68
	public LocalVariableBinding originalBinding; // the real local being tracked, can be null for preliminary track vars for allocation expressions
58
	
59
	public LocalVariableBinding originalBinding; // the real local being tracked
60
	
69
	
61
	HashMap recordedLocations; // initially null, ASTNode -> Integer 
70
	public FakedTrackingVariable innerTracker; // chained tracking variable of a chained (wrapped) resource
71
	public FakedTrackingVariable outerTracker; // inverse of 'innerTracker'
72
73
	MethodScope methodScope; // designates the method declaring this variable
74
75
	private HashMap recordedLocations; // initially null, ASTNode -> Integer
62
76
77
	// temporary storage while analyzing "res = new Res();":
78
	private ASTNode currentAssignment; // temporarily store the assignment as the location for error reporting
63
79
64
	public FakedTrackingVariable(LocalVariableBinding original, Statement location) {
80
	public FakedTrackingVariable(LocalVariableBinding original, ASTNode location) {
65
		super(original.name, location.sourceStart, location.sourceEnd);
81
		super(original.name, location.sourceStart, location.sourceEnd);
66
		this.type = new SingleTypeReference(
82
		this.type = new SingleTypeReference(
67
				TypeConstants.OBJECT,
83
				TypeConstants.OBJECT,
Lines 70-75 public class FakedTrackingVariable extends LocalDeclaration { Link Here
70
		this.originalBinding = original;
86
		this.originalBinding = original;
71
		resolve(original.declaringScope);
87
		resolve(original.declaringScope);
72
	}
88
	}
89
90
	/* Create an unassigned tracking variable while analyzing an allocation expression: */
91
	private FakedTrackingVariable(BlockScope scope, ASTNode location) {
92
		super("<unassigned Closeable value>".toCharArray(), location.sourceStart, location.sourceEnd); //$NON-NLS-1$
93
		this.type = new SingleTypeReference(
94
				TypeConstants.OBJECT,
95
				((long)this.sourceStart <<32)+this.sourceEnd);
96
		this.methodScope = scope.methodScope();
97
		this.originalBinding = null;
98
		resolve(scope);
99
	}
73
	
100
	
74
	public void generateCode(BlockScope currentScope, CodeStream codeStream)
101
	public void generateCode(BlockScope currentScope, CodeStream codeStream)
75
	{ /* NOP - this variable is completely dummy, ie. for analysis only. */ }
102
	{ /* NOP - this variable is completely dummy, ie. for analysis only. */ }
Lines 81-86 public class FakedTrackingVariable extends LocalDeclaration { Link Here
81
				scope.getJavaLangObject(),  // dummy, just needs to be a reference type
108
				scope.getJavaLangObject(),  // dummy, just needs to be a reference type
82
				0,
109
				0,
83
				false);
110
				false);
111
		this.binding.declaringScope = scope;
84
		this.binding.setConstant(Constant.NotAConstant);
112
		this.binding.setConstant(Constant.NotAConstant);
85
		this.binding.useFlag = LocalVariableBinding.USED;
113
		this.binding.useFlag = LocalVariableBinding.USED;
86
		// use a free slot without assigning it:
114
		// use a free slot without assigning it:
Lines 88-173 public class FakedTrackingVariable extends LocalDeclaration { Link Here
88
	}
116
	}
89
117
90
	/**
118
	/**
91
	 * If expression resolves to a local variable binding of type AutoCloseable,
119
	 * If expression resolves to a value of type AutoCloseable answer the variable that tracks closing of that local.
92
	 * answer the variable that tracks closing of that local, creating it if needed.
120
	 * Covers two cases:
121
	 * <ul>
122
	 * <li>value is a local variable reference, create tracking variable it if needed.
123
	 * <li>value is an allocation expression, return a preliminary tracking variable if set.
124
	 * </ul>
93
	 * @param expression
125
	 * @param expression
94
	 * @return a new {@link FakedTrackingVariable} or null.
126
	 * @return a new {@link FakedTrackingVariable} or null.
95
	 */
127
	 */
96
	public static FakedTrackingVariable getCloseTrackingVariable(Expression expression) {
128
	public static FakedTrackingVariable getCloseTrackingVariable(Expression expression) {
129
		while (true) {
130
			if (expression instanceof CastExpression)
131
				expression = ((CastExpression) expression).expression;
132
			else if (expression instanceof Assignment)
133
				expression = ((Assignment) expression).expression;
134
			else
135
				break;
136
		}
97
		if (expression instanceof SingleNameReference) {
137
		if (expression instanceof SingleNameReference) {
98
			SingleNameReference name = (SingleNameReference) expression;
138
			SingleNameReference name = (SingleNameReference) expression;
99
			if (name.binding instanceof LocalVariableBinding) {
139
			if (name.binding instanceof LocalVariableBinding) {
100
				LocalVariableBinding local = (LocalVariableBinding)name.binding;
140
				LocalVariableBinding local = (LocalVariableBinding)name.binding;
101
				if (local.closeTracker != null)
141
				if (local.closeTracker != null)
102
					return local.closeTracker;
142
					return local.closeTracker;
103
				if (local.isParameter() || !isAutoCloseable(expression.resolvedType))
143
				if (!isAnyCloseable(expression.resolvedType))
104
					return null;
144
					return null;
105
				// tracking var doesn't yet exist. This happens in finally block
145
				// tracking var doesn't yet exist. This happens in finally block
106
				// which is analyzed before the corresponding try block
146
				// which is analyzed before the corresponding try block
107
				Statement location = local.declaration;
147
				Statement location = local.declaration;
108
				return local.closeTracker = new FakedTrackingVariable(local, location);
148
				local.closeTracker = new FakedTrackingVariable(local, location);
149
				if (local.isParameter()) {
150
					local.closeTracker.globalClosingState |= OWNED_BY_OUTSIDE;
151
					// status of this tracker is now UNKNOWN
152
				}
153
				return local.closeTracker;
109
			}
154
			}
110
		}
155
		} else if (expression instanceof AllocationExpression) {
156
			// return any preliminary tracking variable from analyseCloseableAllocation 
157
			return ((AllocationExpression) expression).closeTracker;
158
		}		
111
		return null;
159
		return null;
112
	}
160
	}
113
161
114
	/** if 'invocationSite' is a call to close() that has a registered tracking variable, answer that variable's binding. */
162
	/**
115
	public static LocalVariableBinding getTrackerForCloseCall(ASTNode invocationSite) {
163
	 * Before analyzing an assignment of this shape: <code>singleName = new Allocation()</code>
116
		if (invocationSite instanceof MessageSend) {
164
	 * connect any tracking variable of the LHS with the allocation on the RHS.
117
			MessageSend send = (MessageSend) invocationSite;
165
	 * Also the assignment is temporarily stored in the tracking variable in case we need to
118
			if (CharOperation.equals(TypeConstants.CLOSE, send.selector) && send.receiver instanceof SingleNameReference) {
166
	 * report errors because the assignment leaves the old LHS value unclosed.
119
				Binding receiverBinding = ((SingleNameReference)send.receiver).binding;
167
	 * In this case the assignment should be used as the error location.
120
				if (receiverBinding instanceof LocalVariableBinding) {
168
	 * 
121
					FakedTrackingVariable trackingVariable = ((LocalVariableBinding)receiverBinding).closeTracker;
169
	 * @param location the assignment/local declaration being analyzed
122
					if (trackingVariable != null)
170
	 * @param local the local variable being assigned to
123
						return trackingVariable.binding;
171
	 * @param rhs the rhs of the assignment resp. the initialization of the local variable declaration.
172
	 * 		<strong>Precondition:</strong> client has already checked that the resolved type of this expression is either a closeable type or NULL.
173
	 */
174
	public static void preConnectTrackerAcrossAssignment(ASTNode location, LocalVariableBinding local, Expression rhs) {
175
		FakedTrackingVariable closeTracker = null;
176
		if (rhs instanceof AllocationExpression) {
177
			closeTracker = local.closeTracker;
178
			if (closeTracker == null) {
179
				if (rhs.resolvedType != TypeBinding.NULL) { // not NULL means valid closeable as per method precondition
180
					closeTracker = new FakedTrackingVariable(local, location);
181
					if (local.isParameter()) {
182
						closeTracker.globalClosingState |= OWNED_BY_OUTSIDE;
183
					}
184
				}					
185
			}
186
			if (closeTracker != null) {
187
				closeTracker.currentAssignment = location;
188
				((AllocationExpression)rhs).closeTracker = closeTracker;
189
			}
190
		}
191
	}
192
193
	/** 
194
	 * Compute/assign a tracking variable for a freshly allocated closeable value, using information from our white lists.
195
	 * See  Bug 358903 - Filter practically unimportant resource leak warnings 
196
	 */
197
	public static void analyseCloseableAllocation(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation) {
198
		// client has checked that the resolvedType is an AutoCloseable, hence the following cast is safe:
199
		if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitResourceFreeCloseable)) {
200
			// remove unnecessary attempts (closeable is not relevant)
201
			if (allocation.closeTracker != null) {
202
				scope.removeTrackingVar(allocation.closeTracker);
203
				allocation.closeTracker = null;
204
			}
205
		} else if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable)) {
206
			boolean isWrapper = true;
207
			if (allocation.arguments != null &&  allocation.arguments.length > 0) {
208
				// find the wrapped resource represented by its tracking var:
209
				FakedTrackingVariable innerTracker = findCloseTracker(scope, flowInfo, allocation, allocation.arguments[0]);
210
				if (innerTracker != null) {
211
					if (innerTracker == allocation.closeTracker)
212
						return; // self wrap (res = new Res(res)) -> neither change (here) nor remove (below)
213
					int newStatus = FlowInfo.NULL;
214
					if (allocation.closeTracker == null) {
215
						allocation.closeTracker = new FakedTrackingVariable(scope, allocation); // no local available, closeable is unassigned
216
					} else {
217
						if (scope.finallyInfo != null) {
218
							// inject results from analysing a finally block onto the newly connected wrapper
219
							int finallyStatus = scope.finallyInfo.nullStatus(allocation.closeTracker.binding);
220
							if (finallyStatus != FlowInfo.UNKNOWN)
221
								newStatus = finallyStatus;
222
						}
223
					}
224
					allocation.closeTracker.innerTracker = innerTracker;
225
					innerTracker.outerTracker = allocation.closeTracker;
226
					flowInfo.markNullStatus(allocation.closeTracker.binding, newStatus);
227
					if (newStatus != FlowInfo.NULL) {
228
						// propagate results from a finally block also into nested resources:
229
						FakedTrackingVariable currentTracker = innerTracker;
230
						while (currentTracker != null) {
231
							flowInfo.markNullStatus(currentTracker.binding, newStatus);
232
							currentTracker.globalClosingState |= allocation.closeTracker.globalClosingState;
233
							currentTracker = currentTracker.innerTracker;
234
						}
235
					}
236
					return; // keep chaining wrapper (by avoiding to fall through to removeTrackingVar below)
237
				} else {
238
					if (!isAnyCloseable(allocation.arguments[0].resolvedType)) {
239
						isWrapper = false; // argument is not closeable
240
					}
241
				}
242
			} else {
243
				isWrapper = false; // no argument
244
			}
245
			// successful wrapper detection has exited above, let's see why that failed
246
			if (isWrapper) {
247
				// remove unnecessary attempts (wrapper has no relevant inner)
248
				if (allocation.closeTracker != null) {
249
					scope.removeTrackingVar(allocation.closeTracker);
250
					allocation.closeTracker = null;
124
				}
251
				}
252
			} else {
253
				// allocation does not provide a resource as the first argument -> don't treat as a wrapper
254
				handleRegularResource(scope, flowInfo, allocation);
125
			}
255
			}
256
		} else { // regular resource
257
			handleRegularResource(scope, flowInfo, allocation);
126
		}
258
		}
127
		return null;
259
	}
260
261
	private static void handleRegularResource(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation) {
262
		FakedTrackingVariable presetTracker = allocation.closeTracker;
263
		if (presetTracker != null && presetTracker.originalBinding != null) {
264
			// the current assignment forgets a previous resource in the LHS, may cause a leak
265
			// report now because handleResourceAssignment can't distinguish this from a self-wrap situation
266
			int closeStatus = flowInfo.nullStatus(presetTracker.binding);
267
			if (closeStatus != FlowInfo.NON_NULL		// old resource was not closed
268
					&& closeStatus != FlowInfo.UNKNOWN	// old resource had some flow information
269
					&& !flowInfo.isDefinitelyNull(presetTracker.originalBinding)		// old resource was not null
270
					&& !(presetTracker.currentAssignment instanceof LocalDeclaration))	// forgetting old val in local decl is syntactically impossible
271
				allocation.closeTracker.recordErrorLocation(presetTracker.currentAssignment, closeStatus);
272
		} else {
273
			allocation.closeTracker = new FakedTrackingVariable(scope, allocation); // no local available, closeable is unassigned
274
		}
275
		flowInfo.markAsDefinitelyNull(allocation.closeTracker.binding);
276
	}
277
278
	/** Find an existing tracking variable for the argument of an allocation for a resource wrapper. */
279
	private static FakedTrackingVariable findCloseTracker(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation, Expression arg)
280
	{
281
		while (arg instanceof Assignment) {
282
			Assignment assign = (Assignment)arg;
283
			LocalVariableBinding innerLocal = assign.localVariableBinding();
284
			if (innerLocal != null) {
285
				// nested assignment has already been processed
286
				return innerLocal.closeTracker;
287
			} else {
288
				arg = assign.expression; // unwrap assignment and fall through
289
			}
290
		}
291
		if (arg instanceof SingleNameReference) {
292
			// is allocation arg a reference to an existing closeable?
293
			LocalVariableBinding local = arg.localVariableBinding();
294
			if (local != null) {
295
				return local.closeTracker;
296
			}
297
		} else if (arg instanceof AllocationExpression) {
298
			// nested allocation
299
			return ((AllocationExpression)arg).closeTracker;
300
		}
301
		return null; // not a tracked expression
128
	}
302
	}
129
303
130
	/** 
304
	/** 
131
	 * Check if the rhs of an assignment or local declaration is an (Auto)Closeable.
305
	 * Check if the rhs of an assignment or local declaration is an (Auto)Closeable.
132
	 * If so create or re-use a tracking variable, and wire and initialize everything. 
306
	 * If so create or re-use a tracking variable, and wire and initialize everything.
307
	 * @param scope scope containing the assignment
308
	 * @param upstreamInfo info without analysis of the rhs, use this to determine the status of a resource being disconnected
309
	 * @param flowInfo info with analysis of the rhs, use this for recording resource status because this will be passed downstream
310
	 * @param location where to report warnigs/errors against
311
	 * @param rhs the right hand side of the assignment, this expression is to be analyzed.
312
	 *			The caller has already checked that the rhs is either of a closeable type or null.
313
	 * @param local the local variable into which the rhs is being assigned
133
	 */
314
	 */
134
	public static void handleResourceAssignment(FlowInfo flowInfo, Statement location, Expression rhs, LocalVariableBinding local,
315
	public static void handleResourceAssignment(BlockScope scope, FlowInfo upstreamInfo, FlowInfo flowInfo, ASTNode location, Expression rhs, LocalVariableBinding local)
135
				LocalVariableBinding previousTrackerBinding) 
136
	{
316
	{
137
		if (isAutoCloseable(rhs.resolvedType)) {
317
		// does the LHS (local) already have a tracker, indicating we may leak a resource by the assignment?
318
		FakedTrackingVariable previousTracker = null;
319
		FakedTrackingVariable disconnectedTracker = null;
320
		if (local.closeTracker != null) {
321
			// assigning to a variable already holding an AutoCloseable, has it been closed before?
322
			previousTracker = local.closeTracker;
323
			int nullStatus = upstreamInfo.nullStatus(local);
324
			if (nullStatus != FlowInfo.NULL && nullStatus != FlowInfo.UNKNOWN) // only if previous value may be relevant
325
				disconnectedTracker = previousTracker; // report error below, unless we have a self-wrap assignment
326
		}
327
328
		if (rhs.resolvedType != TypeBinding.NULL) {
138
			// new value is AutoCloseable, start tracking, possibly re-using existing tracker var:
329
			// new value is AutoCloseable, start tracking, possibly re-using existing tracker var:
139
	
140
			FakedTrackingVariable rhsTrackVar = getCloseTrackingVariable(rhs);
330
			FakedTrackingVariable rhsTrackVar = getCloseTrackingVariable(rhs);
141
			if (rhsTrackVar != null) {								// 1. share tracking variable with RHS?
331
			if (rhsTrackVar != null) {								// 1. if RHS has a tracking variable...
142
				local.closeTracker = rhsTrackVar;
332
				if (local.closeTracker == null) {
143
				// keep null-status unchanged across this assignment
333
					// null shouldn't occur but let's play safe
144
			} else if (previousTrackerBinding != null) {			// 2. re-use tracking variable from the LHS?
334
					if (rhsTrackVar.originalBinding != null)
145
				// re-assigning from a fresh, mark as not-closed again:
335
						local.closeTracker = rhsTrackVar;			//		a.: let fresh LHS share it 
146
				flowInfo.markAsDefinitelyNull(previousTrackerBinding);
336
				} else {
337
					if (rhsTrackVar == disconnectedTracker && rhs instanceof AllocationExpression)
338
						return; 									// 		b.: self wrapper: res = new Wrap(res); -> done!
339
					local.closeTracker = rhsTrackVar;				//		c.: conflicting LHS and RHS, proceed with recordErrorLocation below
340
				}
341
				// keep close-status of RHS unchanged across this assignment
342
			} else if (previousTracker != null) {					// 2. re-use tracking variable from the LHS?
343
				// re-assigning from a fresh value, mark as not-closed again:
344
				if ((previousTracker.globalClosingState & (SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE)) == 0)
345
					flowInfo.markAsDefinitelyNull(previousTracker.binding);
346
				local.closeTracker = analyseCloseableExpression(flowInfo, local, location, rhs, previousTracker);
147
			} else {												// 3. no re-use, create a fresh tracking variable:
347
			} else {												// 3. no re-use, create a fresh tracking variable:
148
				local.closeTracker = new FakedTrackingVariable(local, location);
348
				rhsTrackVar = analyseCloseableExpression(flowInfo, local, location, rhs, null);
149
				// a fresh resource, mark as not-closed:
349
				if (rhsTrackVar != null) {
150
				flowInfo.markAsDefinitelyNull(local.closeTracker.binding);
350
					local.closeTracker = rhsTrackVar;
351
					// a fresh resource, mark as not-closed:
352
					if ((rhsTrackVar.globalClosingState & (SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE)) == 0)
353
						flowInfo.markAsDefinitelyNull(rhsTrackVar.binding);
151
// TODO(stephan): this might be useful, but I could not find a test case for it: 
354
// TODO(stephan): this might be useful, but I could not find a test case for it: 
152
//				if (flowContext.initsOnFinally != null)
355
//					if (flowContext.initsOnFinally != null)
153
//					flowContext.initsOnFinally.markAsDefinitelyNonNull(trackerBinding);
356
//						flowContext.initsOnFinally.markAsDefinitelyNonNull(trackerBinding);
357
				}
358
			}
359
		}
360
361
		if (disconnectedTracker != null) {
362
			if (disconnectedTracker.innerTracker != null && disconnectedTracker.innerTracker.binding.declaringScope == scope) {
363
				// discard tracker for the wrapper but keep the inner:
364
				disconnectedTracker.innerTracker.outerTracker = null;
365
				scope.pruneWrapperTrackingVar(disconnectedTracker);
366
			} else {
367
				int upstreamStatus = upstreamInfo.nullStatus(disconnectedTracker.binding);
368
				if (upstreamStatus != FlowInfo.NON_NULL)
369
					disconnectedTracker.recordErrorLocation(location, upstreamStatus);
370
			}
371
		}
372
	}
373
	/**
374
	 * Analyze structure of a closeable expression, matching (chained) resources against our white lists.
375
	 * @param flowInfo where to record close status
376
	 * @param local local variable to which the closeable is being assigned
377
	 * @param location where to flag errors/warnings against
378
	 * @param expression expression to be analyzed
379
	 * @param previousTracker when analyzing a re-assignment we may already have a tracking variable for local,
380
	 *  		which we should then re-use
381
	 * @return a tracking variable associated with local or null if no need to track
382
	 */
383
	private static FakedTrackingVariable analyseCloseableExpression(FlowInfo flowInfo, LocalVariableBinding local, 
384
									ASTNode location, Expression expression, FakedTrackingVariable previousTracker) 
385
	{
386
		// unwrap uninteresting nodes:
387
		while (true) {
388
			if (expression instanceof Assignment)
389
				expression = ((Assignment)expression).expression;
390
			else if (expression instanceof CastExpression)
391
				expression = ((CastExpression) expression).expression;
392
			else
393
				break;
394
		}
395
396
		// analyze by node type:
397
		if (expression instanceof AllocationExpression) {
398
			// allocation expressions already have their tracking variables analyzed by analyseCloseableAllocation(..)
399
			FakedTrackingVariable tracker = ((AllocationExpression) expression).closeTracker;
400
			if (tracker != null && tracker.originalBinding == null) {
401
				// tracker without original binding (unassigned closeable) shouldn't reach here but let's play safe
402
				return null;
403
			}
404
			return tracker;
405
		} else if (expression instanceof MessageSend 
406
				|| expression instanceof ArrayReference) 
407
		{
408
			// we *might* be responsible for the resource obtained
409
			FakedTrackingVariable tracker = new FakedTrackingVariable(local, location);
410
			tracker.globalClosingState |= SHARED_WITH_OUTSIDE;
411
			flowInfo.markPotentiallyNullBit(tracker.binding); // shed some doubt
412
			return tracker;			
413
		} else if ((expression.bits & RestrictiveFlagMASK) == Binding.FIELD) 
414
		{
415
			// responsibility for this resource probably lies at a higher level
416
			FakedTrackingVariable tracker = new FakedTrackingVariable(local, location);
417
			tracker.globalClosingState |= OWNED_BY_OUTSIDE;
418
			// leave state as UNKNOWN, the bit OWNED_BY_OUTSIDE will prevent spurious warnings
419
			return tracker;			
420
		}
421
422
		if (expression.resolvedType instanceof ReferenceBinding) {
423
			ReferenceBinding resourceType = (ReferenceBinding) expression.resolvedType;
424
			if (resourceType.hasTypeBit(TypeIds.BitResourceFreeCloseable)) {
425
				// (a) resource-free closeable: -> null
426
				return null;
154
			}
427
			}
155
		}
428
		}
429
		if (local.closeTracker != null)
430
			// (c): inner has already been analyzed: -> re-use track var
431
			return local.closeTracker;
432
		return new FakedTrackingVariable(local, location);
433
	}
434
435
	public static void cleanUpAfterAssignment(BlockScope currentScope, int lhsBits, Expression expression) {
436
		// remove all remaining track vars with no original binding
437
438
		// unwrap uninteresting nodes:
439
		while (true) {
440
			if (expression instanceof Assignment)
441
				expression = ((Assignment)expression).expression;
442
			else if (expression instanceof CastExpression)
443
				expression = ((CastExpression) expression).expression;
444
			else
445
				break;
446
		}
447
		if (expression instanceof AllocationExpression) {
448
			FakedTrackingVariable tracker = ((AllocationExpression) expression).closeTracker;
449
			if (tracker != null && tracker.originalBinding == null) {
450
				currentScope.removeTrackingVar(tracker);
451
				((AllocationExpression) expression).closeTracker = null;
452
			}
453
		} else {
454
			// assignment passing a local into a field?
455
			LocalVariableBinding local = expression.localVariableBinding();
456
			if (local != null && local.closeTracker != null && ((lhsBits & Binding.FIELD) != 0))
457
				currentScope.removeTrackingVar(local.closeTracker); // TODO: may want to use local.closeTracker.markPassedToOutside(..,true)
458
		}
156
	}
459
	}
157
460
158
	/** Answer wither the given type binding is a subtype of java.lang.AutoCloseable. */
461
	/** Answer wither the given type binding is a subtype of java.lang.AutoCloseable. */
159
	public static boolean isAutoCloseable(TypeBinding typeBinding) {
462
	public static boolean isAnyCloseable(TypeBinding typeBinding) {
160
		return typeBinding instanceof ReferenceBinding
463
		return typeBinding instanceof ReferenceBinding
161
			&& ((ReferenceBinding)typeBinding).hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable);
464
			&& ((ReferenceBinding)typeBinding).hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable);
162
	}
465
	}
163
466
467
	public int findMostSpecificStatus(FlowInfo flowInfo, BlockScope currentScope, BlockScope locationScope) {
468
		int status = FlowInfo.UNKNOWN;
469
		FakedTrackingVariable currentTracker = this;
470
		// loop as to consider wrappers (per white list) encapsulating an inner resource.
471
		while (currentTracker != null) {
472
			LocalVariableBinding currentVar = currentTracker.binding;
473
			int currentStatus = getNullStatusAggressively(currentVar, flowInfo);
474
			if (locationScope != null) // only check at method exit points
475
				currentStatus = mergeCloseStatus(locationScope, currentStatus, currentVar, currentScope);
476
			if (currentStatus == FlowInfo.NON_NULL) {
477
				status = currentStatus;
478
				break; // closed -> stop searching
479
			} else if (status == FlowInfo.NULL || status == FlowInfo.UNKNOWN) {
480
				status = currentStatus; // improved although not yet safe -> keep searching for better
481
			}
482
			currentTracker = currentTracker.innerTracker;
483
		}
484
		return status;
485
	}
486
487
	/**
488
	 * Get the null status looking even into unreachable flows
489
	 * @param local
490
	 * @param flowInfo
491
	 * @return one of the constants FlowInfo.{NULL,POTENTIALLY_NULL,POTENTIALLY_NON_NULL,NON_NULL}.
492
	 */
493
	private int getNullStatusAggressively(LocalVariableBinding local, FlowInfo flowInfo) {
494
		int reachMode = flowInfo.reachMode();
495
		int status = 0;
496
		try {
497
			// unreachable flowInfo is too shy in reporting null-issues, temporarily forget reachability:
498
			if (reachMode != FlowInfo.REACHABLE)
499
				flowInfo.tagBits &= ~FlowInfo.UNREACHABLE;
500
			status = flowInfo.nullStatus(local);
501
		} finally {
502
			// reset
503
			flowInfo.tagBits |= reachMode;
504
		}
505
		// at this point some combinations are not useful so flatten to a single bit:
506
		if ((status & FlowInfo.NULL) != 0) {
507
			if ((status & (FlowInfo.NON_NULL | FlowInfo.POTENTIALLY_NON_NULL)) != 0)
508
				return FlowInfo.POTENTIALLY_NULL; 	// null + doubt = pot null
509
			return FlowInfo.NULL;
510
		} else if ((status & FlowInfo.NON_NULL) != 0) {
511
			if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
512
				return FlowInfo.POTENTIALLY_NULL;	// non-null + doubt = pot null
513
			return FlowInfo.NON_NULL;
514
		} else if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
515
			return FlowInfo.POTENTIALLY_NULL;
516
		return status;
517
	}
518
519
	public int mergeCloseStatus(BlockScope currentScope, int status, LocalVariableBinding local, BlockScope outerScope) {
520
		// get the most suitable null status representing whether resource 'binding' has been closed
521
		// start at 'currentScope' and potentially travel out until 'outerScope'
522
		// at each scope consult any recorded 'finallyInfo'.
523
		if (status != FlowInfo.NON_NULL) {
524
			if (currentScope.finallyInfo != null) {
525
				int finallyStatus = currentScope.finallyInfo.nullStatus(local);
526
				if (finallyStatus == FlowInfo.NON_NULL)
527
					return finallyStatus;
528
				if (finallyStatus != FlowInfo.NULL) // neither is NON_NULL, but not both are NULL => call it POTENTIALLY_NULL
529
					status = FlowInfo.POTENTIALLY_NULL;
530
			}
531
			if (currentScope != outerScope && currentScope.parent instanceof BlockScope)
532
				return mergeCloseStatus(((BlockScope) currentScope.parent), status, local, outerScope);
533
		}
534
		return status;
535
	}
536
164
	/** Mark that this resource is closed locally. */
537
	/** Mark that this resource is closed locally. */
165
	public void markClose(FlowInfo flowInfo, FlowContext flowContext) {
538
	public void markClose(FlowInfo flowInfo, FlowContext flowContext) {
166
		flowInfo.markAsDefinitelyNonNull(this.binding);
539
		FakedTrackingVariable current = this;
167
		this.globalClosingState |= CLOSE_SEEN;
540
		do {
541
			flowInfo.markAsDefinitelyNonNull(current.binding);
542
			current.globalClosingState |= CLOSE_SEEN;
168
//TODO(stephan): this might be useful, but I could not find a test case for it: 
543
//TODO(stephan): this might be useful, but I could not find a test case for it: 
169
//		if (flowContext.initsOnFinally != null)
544
//			if (flowContext.initsOnFinally != null)
170
//			flowContext.initsOnFinally.markAsDefinitelyNonNull(this.binding);
545
//				flowContext.initsOnFinally.markAsDefinitelyNonNull(this.binding);
546
			current = current.innerTracker;
547
		} while (current != null);
171
	}
548
	}
172
549
173
	/** Mark that this resource is closed from a nested method (inside a local class). */
550
	/** Mark that this resource is closed from a nested method (inside a local class). */
Lines 179-237 public class FakedTrackingVariable extends LocalDeclaration { Link Here
179
	 * Mark that this resource is passed to some outside code
556
	 * Mark that this resource is passed to some outside code
180
	 * (as argument to a method/ctor call or as a return value from the current method), 
557
	 * (as argument to a method/ctor call or as a return value from the current method), 
181
	 * and thus should be considered as potentially closed.
558
	 * and thus should be considered as potentially closed.
559
	 * @param owned should the resource be considered owned by some outside?
182
	 */
560
	 */
183
	public static FlowInfo markPassedToOutside(BlockScope scope, Expression expression, FlowInfo flowInfo) {
561
	public static FlowInfo markPassedToOutside(BlockScope scope, Expression expression, FlowInfo flowInfo, boolean owned) {	
562
		
184
		FakedTrackingVariable trackVar = getCloseTrackingVariable(expression);
563
		FakedTrackingVariable trackVar = getCloseTrackingVariable(expression);
185
		if (trackVar != null) {
564
		if (trackVar != null) {
186
			trackVar.globalClosingState |= PASSED_TO_OUTSIDE;
565
			if (trackVar.originalBinding == null) {
187
			if (scope.methodScope() != trackVar.methodScope)
566
				// an allocation that never was assigned to a local variable -> drop it completely as we're not responsible
188
				trackVar.globalClosingState |= CLOSED_IN_NESTED_METHOD;
567
				scope.removeTrackingVar(trackVar);
568
				return flowInfo;
569
			}
189
			// insert info that the tracked resource *may* be closed (by the target method, i.e.)
570
			// insert info that the tracked resource *may* be closed (by the target method, i.e.)
190
			FlowInfo infoResourceIsClosed = flowInfo.copy();
571
			FlowInfo infoResourceIsClosed = flowInfo.copy();
191
			infoResourceIsClosed.markAsDefinitelyNonNull(trackVar.binding);
572
			int flag = owned ? OWNED_BY_OUTSIDE : SHARED_WITH_OUTSIDE;
573
			do {
574
				trackVar.globalClosingState |= flag;
575
				if (scope.methodScope() != trackVar.methodScope)
576
					trackVar.globalClosingState |= CLOSED_IN_NESTED_METHOD;
577
				infoResourceIsClosed.markAsDefinitelyNonNull(trackVar.binding);
578
			} while ((trackVar = trackVar.innerTracker) != null); 
192
			return FlowInfo.conditional(flowInfo, infoResourceIsClosed);
579
			return FlowInfo.conditional(flowInfo, infoResourceIsClosed);
193
		}
580
		}
194
		return flowInfo;
581
		return flowInfo;
195
	}
582
	}
196
	
583
584
	/** 
585
	 * Pick tracking variables from 'varsOfScope' to establish a proper order of processing:
586
	 * As much as possible pick wrapper resources before their inner resources.
587
	 * Also consider cases of wrappers and their inners being declared at different scopes.
588
	 */
589
	public static FakedTrackingVariable pickVarForReporting(Set varsOfScope, BlockScope scope, boolean atExit) {
590
		if (varsOfScope.isEmpty()) return null;
591
		FakedTrackingVariable trackingVar = (FakedTrackingVariable) varsOfScope.iterator().next();
592
		while (trackingVar.outerTracker != null) {
593
			// resource is wrapped, is wrapper defined in this scope?
594
			if (varsOfScope.contains(trackingVar.outerTracker)) {
595
				// resource from same scope, travel up the wrapper chain
596
				trackingVar = trackingVar.outerTracker;
597
			} else if (atExit) {
598
				// at an exit point we report against inner despite a wrapper that may/may not be closed later
599
				break;
600
			} else {
601
				BlockScope outerTrackerScope = trackingVar.outerTracker.binding.declaringScope;
602
				if (outerTrackerScope == scope) {
603
					// outerTracker is from same scope and already processed -> pick trackingVar now
604
					break;
605
				} else {
606
					// outer resource is from other (outer?) scope
607
					Scope currentScope = scope;
608
					while ((currentScope = currentScope.parent) instanceof BlockScope) {
609
						if (outerTrackerScope == currentScope) {
610
							// at end of block pass responsibility for inner resource to outer scope holding a wrapper
611
							varsOfScope.remove(trackingVar); // drop this one
612
							// pick a next candidate:
613
							return pickVarForReporting(varsOfScope, scope, atExit);
614
						}
615
					}
616
					break; // not parent owned -> pick this var
617
				}
618
			}
619
		}
620
		varsOfScope.remove(trackingVar);
621
		return trackingVar;
622
	}
623
624
	/** 
625
	 * If current is the same as 'returnedResource' or a wrapper thereof,
626
	 * mark as reported and return true, otherwise false.
627
	 */
628
	public boolean isResourceBeingReturned(FakedTrackingVariable returnedResource) {
629
		FakedTrackingVariable current = this;
630
		do {
631
			if (current == returnedResource) {
632
				this.globalClosingState |= REPORTED_DEFINITIVE_LEAK;
633
				return true;
634
			}
635
			current = current.innerTracker;
636
		} while (current != null);
637
		return false;
638
	}
639
197
	public void recordErrorLocation(ASTNode location, int nullStatus) {
640
	public void recordErrorLocation(ASTNode location, int nullStatus) {
198
		if (this.recordedLocations == null)
641
		if (this.recordedLocations == null)
199
			this.recordedLocations = new HashMap();
642
			this.recordedLocations = new HashMap();
200
		this.recordedLocations.put(location, new Integer(nullStatus));
643
		this.recordedLocations.put(location, new Integer(nullStatus));
201
	}
644
	}
202
645
203
	public boolean reportRecordedErrors(Scope scope) {
646
	public boolean reportRecordedErrors(Scope scope, int mergedStatus) {
204
		if (this.globalClosingState == 0) {
647
		FakedTrackingVariable current = this;
205
			reportError(scope.problemReporter(), null, FlowInfo.NULL);
648
		while (current.globalClosingState == 0) {
206
			return true;
649
			current = current.innerTracker;
650
			if (current == null) {
651
				// no relevant state found -> report:
652
				reportError(scope.problemReporter(), null, mergedStatus);
653
				return true;
654
			}
207
		}
655
		}
208
		boolean hasReported = false;
656
		boolean hasReported = false;
209
		if (this.recordedLocations != null) {
657
		if (this.recordedLocations != null) {
210
			Iterator locations = this.recordedLocations.entrySet().iterator();
658
			Iterator locations = this.recordedLocations.entrySet().iterator();
659
			int reportFlags = 0;
211
			while (locations.hasNext()) {
660
			while (locations.hasNext()) {
212
				Map.Entry entry = (Entry) locations.next();
661
				Map.Entry entry = (Entry) locations.next();
213
				reportError(scope.problemReporter(), (ASTNode)entry.getKey(), ((Integer)entry.getValue()).intValue());
662
				reportFlags |= reportError(scope.problemReporter(), (ASTNode)entry.getKey(), ((Integer)entry.getValue()).intValue());
214
				hasReported = true;
663
				hasReported = true;
215
			}
664
			}
665
			if (reportFlags != 0) {
666
				// after all locations have been reported, mark as reported to prevent duplicate report via an outer wrapper
667
				current = this;
668
				do {
669
					current.globalClosingState |= reportFlags;
670
				} while ((current = current.innerTracker) != null);
671
			}
216
		}
672
		}
217
		return hasReported;
673
		return hasReported;
218
	}
674
	}
219
	
675
	
220
	public void reportError(ProblemReporter problemReporter, ASTNode location, int nullStatus) {
676
	public int reportError(ProblemReporter problemReporter, ASTNode location, int nullStatus) {
677
		// which degree of problem?
678
		boolean isPotentialProblem = false;
221
		if (nullStatus == FlowInfo.NULL) {
679
		if (nullStatus == FlowInfo.NULL) {
222
			if ((this.globalClosingState & CLOSED_IN_NESTED_METHOD) != 0)
680
			if ((this.globalClosingState & CLOSED_IN_NESTED_METHOD) != 0)
223
				problemReporter.potentiallyUnclosedCloseable(this, location);
681
				isPotentialProblem = true;
224
			else
225
				problemReporter.unclosedCloseable(this, location);
226
		} else if (nullStatus == FlowInfo.POTENTIALLY_NULL) {
682
		} else if (nullStatus == FlowInfo.POTENTIALLY_NULL) {
227
			problemReporter.potentiallyUnclosedCloseable(this, location);
683
			isPotentialProblem = true;
228
		}		
684
		}
685
		// report:
686
		if (isPotentialProblem) {
687
			if ((this.globalClosingState & (REPORTED_POTENTIAL_LEAK|REPORTED_DEFINITIVE_LEAK)) != 0)
688
				return 0;
689
			problemReporter.potentiallyUnclosedCloseable(this, location);	
690
		} else {
691
			if ((this.globalClosingState & (REPORTED_DEFINITIVE_LEAK)) != 0)
692
				return 0;
693
			problemReporter.unclosedCloseable(this, location);			
694
		}
695
		// propagate flag to inners:
696
		int reportFlag = isPotentialProblem ? REPORTED_POTENTIAL_LEAK : REPORTED_DEFINITIVE_LEAK;
697
		if (location == null) { // if location != null flags will be set after the loop over locations 
698
			FakedTrackingVariable current = this;
699
			do {
700
				current.globalClosingState |= reportFlag;
701
			} while ((current = current.innerTracker) != null);
702
		}
703
		return reportFlag;
229
	}
704
	}
230
705
231
	public void reportExplicitClosing(ProblemReporter problemReporter) {
706
	public void reportExplicitClosing(ProblemReporter problemReporter) {
232
		if ((this.globalClosingState & REPORTED) == 0) {
707
		if ((this.globalClosingState & (OWNED_BY_OUTSIDE|REPORTED_EXPLICIT_CLOSE)) == 0) { // can't use t-w-r for OWNED_BY_OUTSIDE
233
			this.globalClosingState |= REPORTED;
708
			this.globalClosingState |= REPORTED_EXPLICIT_CLOSE;
234
			problemReporter.explicitlyClosedAutoCloseable(this);
709
			problemReporter.explicitlyClosedAutoCloseable(this);
235
		}
710
		}
236
	}
711
	}
712
713
	public void resetReportingBits() {
714
		FakedTrackingVariable current = this;
715
		do {
716
			current.globalClosingState &= ~(REPORTED_POTENTIAL_LEAK|REPORTED_DEFINITIVE_LEAK);
717
			current = current.innerTracker;
718
		} while (current != null);
719
	}
237
}
720
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java (-2 / +18 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 13-18 Link Here
13
 *							bug 335093 - [compiler][null] minimal hook for future null annotation support
13
 *							bug 335093 - [compiler][null] minimal hook for future null annotation support
14
 *							bug 349326 - [1.7] new warning for missing try-with-resources
14
 *							bug 349326 - [1.7] new warning for missing try-with-resources
15
 *							bug 186342 - [compiler][null] Using annotations for null checking
15
 *							bug 186342 - [compiler][null] Using annotations for null checking
16
 *							bug 358903 - Filter practically unimportant resource leak warnings
16
 *******************************************************************************/
17
 *******************************************************************************/
17
package org.eclipse.jdt.internal.compiler.ast;
18
package org.eclipse.jdt.internal.compiler.ast;
18
19
Lines 74-84 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl Link Here
74
		this.initialization.checkNPE(currentScope, flowContext, flowInfo);
75
		this.initialization.checkNPE(currentScope, flowContext, flowInfo);
75
	}
76
	}
76
	
77
	
78
	FlowInfo preInitInfo = null;
79
	boolean shouldAnalyseResource = this.binding != null 
80
			&& flowInfo.reachMode() == FlowInfo.REACHABLE 
81
			&& FakedTrackingVariable.isAnyCloseable(this.initialization.resolvedType);
82
	if (shouldAnalyseResource) {
83
		preInitInfo = flowInfo.unconditionalCopy();
84
		// analysis of resource leaks needs additional context while analyzing the RHS:
85
		FakedTrackingVariable.preConnectTrackerAcrossAssignment(this, this.binding, this.initialization);
86
	}
87
77
	flowInfo =
88
	flowInfo =
78
		this.initialization
89
		this.initialization
79
			.analyseCode(currentScope, flowContext, flowInfo)
90
			.analyseCode(currentScope, flowContext, flowInfo)
80
			.unconditionalInits();
91
			.unconditionalInits();
81
	FakedTrackingVariable.handleResourceAssignment(flowInfo, this, this.initialization, this.binding, null);
92
93
	if (shouldAnalyseResource)
94
		FakedTrackingVariable.handleResourceAssignment(currentScope, preInitInfo, flowInfo, this, this.initialization, this.binding);
95
	else
96
		FakedTrackingVariable.cleanUpAfterAssignment(currentScope, Binding.LOCAL, this.initialization);
97
82
	int nullStatus = this.initialization.nullStatus(flowInfo);
98
	int nullStatus = this.initialization.nullStatus(flowInfo);
83
	if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes
99
	if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes
84
		this.bits |= FirstAssignmentToLocal;
100
		this.bits |= FirstAssignmentToLocal;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (-3 / +4 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 12-17 Link Here
12
 *								bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
12
 *								bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
13
 *								bug 349326 - [1.7] new warning for missing try-with-resources
13
 *								bug 349326 - [1.7] new warning for missing try-with-resources
14
 *								bug 186342 - [compiler][null] Using annotations for null checking
14
 *								bug 186342 - [compiler][null] Using annotations for null checking
15
 *								bug 358903 - Filter practically unimportant resource leak warnings
15
 *******************************************************************************/
16
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.ast;
17
package org.eclipse.jdt.internal.compiler.ast;
17
18
Lines 96-104 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl Link Here
96
			if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
97
			if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
97
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
98
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
98
			}
99
			}
99
			// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
100
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
101
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
100
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
101
			// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
102
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, false);
102
		}
103
		}
103
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
104
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
104
	}
105
	}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java (-1 / +1 lines)
Lines 81-87 public class QualifiedAllocationExpression extends AllocationExpression { Link Here
81
		if (this.arguments != null) {
81
		if (this.arguments != null) {
82
			for (int i = 0, count = this.arguments.length; i < count; i++) {
82
			for (int i = 0, count = this.arguments.length; i < count; i++) {
83
				// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
83
				// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
84
				flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
84
				flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, false);
85
				flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo);
85
				flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo);
86
				if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
86
				if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
87
					this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
87
					this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java (-3 / +3 lines)
Lines 13-18 Link Here
13
 *     							bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
13
 *     							bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
14
 *								bug 186342 - [compiler][null] Using annotations for null checking
14
 *								bug 186342 - [compiler][null] Using annotations for null checking
15
 *								bug 365835 - [compiler][null] inconsistent error reporting.
15
 *								bug 365835 - [compiler][null] inconsistent error reporting.
16
 *								bug 358903 - Filter practically unimportant resource leak warnings
16
 *******************************************************************************/
17
 *******************************************************************************/
17
package org.eclipse.jdt.internal.compiler.ast;
18
package org.eclipse.jdt.internal.compiler.ast;
18
19
Lines 52-60 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl Link Here
52
		if (trackingVariable != null) {
53
		if (trackingVariable != null) {
53
			if (methodScope != trackingVariable.methodScope)
54
			if (methodScope != trackingVariable.methodScope)
54
				trackingVariable.markClosedInNestedMethod();
55
				trackingVariable.markClosedInNestedMethod();
55
			// don't report issues concerning this local, since by returning
56
			// by returning the method passes the responsibility to the caller:
56
			// the method passes the responsibility to the caller:
57
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.expression, flowInfo, true);
57
			currentScope.removeTrackingVar(trackingVariable);
58
		}
58
		}
59
	}
59
	}
60
	this.initStateIndex =
60
	this.initStateIndex =
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java (-2 / +3 lines)
Lines 12-17 Link Here
12
 *     							bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis
12
 *     							bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis
13
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
13
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
14
 *     							bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
14
 *     							bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
15
 *								bug 358903 - Filter practically unimportant resource leak warnings
15
 *******************************************************************************/
16
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.ast;
17
package org.eclipse.jdt.internal.compiler.ast;
17
18
Lines 134-140 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl Link Here
134
			if (resourceBinding.closeTracker != null) {
135
			if (resourceBinding.closeTracker != null) {
135
				// this was false alarm, we don't need to track the resource
136
				// this was false alarm, we don't need to track the resource
136
				this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker);
137
				this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker);
137
				resourceBinding.closeTracker = null;
138
				// keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block
138
			}
139
			}
139
			TypeBinding type = resourceBinding.type;
140
			TypeBinding type = resourceBinding.type;
140
			if (type != null && type.isValidBinding()) {
141
			if (type != null && type.isValidBinding()) {
Lines 276-282 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl Link Here
276
			if (resourceBinding.closeTracker != null) {
277
			if (resourceBinding.closeTracker != null) {
277
				// this was false alarm, we don't need to track the resource
278
				// this was false alarm, we don't need to track the resource
278
				this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker);
279
				this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker);
279
				resourceBinding.closeTracker = null;
280
				// keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block
280
			} 
281
			} 
281
			TypeBinding type = resourceBinding.type;
282
			TypeBinding type = resourceBinding.type;
282
			if (type != null && type.isValidBinding()) {
283
			if (type != null && type.isValidBinding()) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java (-3 / +6 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 11-16 Link Here
11
 *								bug 349326 - [1.7] new warning for missing try-with-resources
11
 *								bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *								bug 364890 - BinaryTypeBinding should use char constants from Util
13
 *								bug 364890 - BinaryTypeBinding should use char constants from Util
14
 *								bug 358903 - Filter practically unimportant resource leak warnings
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.internal.compiler.lookup;
16
package org.eclipse.jdt.internal.compiler.lookup;
16
17
Lines 1275-1281 public ReferenceBinding superclass() { Link Here
1275
			this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
1276
			this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
1276
		}
1277
		}
1277
	}
1278
	}
1278
	this.typeBits |= this.superclass.typeBits;
1279
	this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
1280
	if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) // avoid the side-effects of hasTypeBit()! 
1281
		this.typeBits |= applyCloseableWhitelists();
1279
	return this.superclass;
1282
	return this.superclass;
1280
}
1283
}
1281
// NOTE: superInterfaces of binary types are resolved when needed
1284
// NOTE: superInterfaces of binary types are resolved when needed
Lines 1298-1304 public ReferenceBinding[] superInterfaces() { Link Here
1298
				this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
1301
				this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
1299
			}	
1302
			}	
1300
		}
1303
		}
1301
		this.typeBits |= this.superInterfaces[i].typeBits;
1304
		this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits);
1302
	}
1305
	}
1303
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
1306
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
1304
	return this.superInterfaces;
1307
	return this.superInterfaces;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java (-59 / +38 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 10-20 Link Here
10
 *     Stephan Herrmann - Contributions for
10
 *     Stephan Herrmann - Contributions for
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
12
 *								bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
13
 *								bug 358903 - Filter practically unimportant resource leak warnings
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.lookup;
15
package org.eclipse.jdt.internal.compiler.lookup;
15
16
16
import java.util.ArrayList;
17
import java.util.ArrayList;
18
import java.util.HashSet;
17
import java.util.List;
19
import java.util.List;
20
import java.util.Set;
18
21
19
import org.eclipse.jdt.core.compiler.CharOperation;
22
import org.eclipse.jdt.core.compiler.CharOperation;
20
import org.eclipse.jdt.internal.compiler.ast.*;
23
import org.eclipse.jdt.internal.compiler.ast.*;
Lines 976-992 public int registerTrackingVariable(FakedTrackingVariable fakedTrackingVariable) Link Here
976
		this.trackingVariables = new ArrayList(3);
979
		this.trackingVariables = new ArrayList(3);
977
	this.trackingVariables.add(fakedTrackingVariable);
980
	this.trackingVariables.add(fakedTrackingVariable);
978
	MethodScope outerMethodScope = outerMostMethodScope();
981
	MethodScope outerMethodScope = outerMostMethodScope();
979
	return outerMethodScope.analysisIndex + (outerMethodScope.trackVarCount++);
982
	return outerMethodScope.analysisIndex++;
980
	
981
}
983
}
982
/** When are no longer interested in this tracking variable - remove it. */
984
/** When are no longer interested in this tracking variable - remove it. */
983
public void removeTrackingVar(FakedTrackingVariable trackingVariable) {
985
public void removeTrackingVar(FakedTrackingVariable trackingVariable) {
986
	if (trackingVariable.innerTracker != null) {
987
		removeTrackingVar(trackingVariable.innerTracker);
988
		trackingVariable.innerTracker = null;
989
	}
984
	if (this.trackingVariables != null)
990
	if (this.trackingVariables != null)
985
		if (this.trackingVariables.remove(trackingVariable))
991
		if (this.trackingVariables.remove(trackingVariable))
986
			return;
992
			return;
987
	if (this.parent instanceof BlockScope)
993
	if (this.parent instanceof BlockScope)
988
		((BlockScope)this.parent).removeTrackingVar(trackingVariable);
994
		((BlockScope)this.parent).removeTrackingVar(trackingVariable);
989
}
995
}
996
/** Unregister a wrapper resource without affecting its inner. */
997
public void pruneWrapperTrackingVar(FakedTrackingVariable trackingVariable) {
998
	this.trackingVariables.remove(trackingVariable);
999
}
990
/**
1000
/**
991
 * At the end of a block check the closing-status of all tracked closeables that are declared in this block.
1001
 * At the end of a block check the closing-status of all tracked closeables that are declared in this block.
992
 * Also invoked when entering unreachable code.
1002
 * Also invoked when entering unreachable code.
Lines 999-1012 public void checkUnclosedCloseables(FlowInfo flowInfo, ASTNode location, BlockSc Link Here
999
		return;
1009
		return;
1000
	}
1010
	}
1001
	if (location != null && flowInfo.reachMode() != 0) return;
1011
	if (location != null && flowInfo.reachMode() != 0) return;
1002
	for (int i=0; i<this.trackingVariables.size(); i++) {
1012
1003
		FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
1013
	FakedTrackingVariable returnVar = (location instanceof ReturnStatement) ?
1014
			FakedTrackingVariable.getCloseTrackingVariable(((ReturnStatement)location).expression) : null;
1015
1016
	Set varSet = new HashSet(this.trackingVariables);
1017
	FakedTrackingVariable trackingVar;
1018
	// pick one outer-most variable from the set at a time
1019
	while ((trackingVar = FakedTrackingVariable.pickVarForReporting(varSet, this, location != null)) != null) {
1020
1021
		if (returnVar != null && trackingVar.isResourceBeingReturned(returnVar)) {
1022
			continue;
1023
		}
1024
1004
		if (location != null && trackingVar.originalBinding != null && flowInfo.isDefinitelyNull(trackingVar.originalBinding))
1025
		if (location != null && trackingVar.originalBinding != null && flowInfo.isDefinitelyNull(trackingVar.originalBinding))
1005
			continue; // reporting against a specific location, resource is null at this flow, don't complain
1026
			continue; // reporting against a specific location, resource is null at this flow, don't complain
1006
		int status = getNullStatusAggressively(trackingVar.binding, flowInfo);
1027
		
1007
		// try to improve info if a close() inside finally was observed:
1028
		// compute the most specific null status for this resource,
1008
		if (locationScope != null) // only check at method exit points
1029
		int status = trackingVar.findMostSpecificStatus(flowInfo, this, locationScope);
1009
			status = locationScope.mergeCloseStatus(status, trackingVar.binding, this);
1030
		
1010
		if (status == FlowInfo.NULL) {
1031
		if (status == FlowInfo.NULL) {
1011
			// definitely unclosed: highest priority
1032
			// definitely unclosed: highest priority
1012
			reportResourceLeak(trackingVar, location, status);
1033
			reportResourceLeak(trackingVar, location, status);
Lines 1015-1021 public void checkUnclosedCloseables(FlowInfo flowInfo, ASTNode location, BlockSc Link Here
1015
		if (location == null) // at end of block and not definitely unclosed
1036
		if (location == null) // at end of block and not definitely unclosed
1016
		{
1037
		{
1017
			// problems at specific locations: medium priority
1038
			// problems at specific locations: medium priority
1018
			if (trackingVar.reportRecordedErrors(this)) // ... report previously recorded errors
1039
			if (trackingVar.reportRecordedErrors(this, status)) // ... report previously recorded errors
1019
				continue;
1040
				continue;
1020
		} 
1041
		} 
1021
		if (status == FlowInfo.POTENTIALLY_NULL) {
1042
		if (status == FlowInfo.POTENTIALLY_NULL) {
Lines 1032-1056 public void checkUnclosedCloseables(FlowInfo flowInfo, ASTNode location, BlockSc Link Here
1032
		for (int i=0; i<this.localIndex; i++)
1053
		for (int i=0; i<this.localIndex; i++)
1033
			this.locals[i].closeTracker = null;		
1054
			this.locals[i].closeTracker = null;		
1034
		this.trackingVariables = null;
1055
		this.trackingVariables = null;
1035
	}
1056
	} else {
1036
}
1057
		int size = this.trackingVariables.size();
1037
1058
		for (int i=0; i<size; i++) {
1038
private int mergeCloseStatus(int status, LocalVariableBinding binding, BlockScope outerScope) {
1059
			FakedTrackingVariable tracker = (FakedTrackingVariable) this.trackingVariables.get(0);
1039
	// get the most suitable null status representing whether resource 'binding' has been closed
1060
			tracker.resetReportingBits();
1040
	// start at this scope and potentially travel out until 'outerScope'
1041
	// at each scope consult any recorded 'finallyInfo'.
1042
	if (status != FlowInfo.NON_NULL) {
1043
		if (this.finallyInfo != null) {
1044
			int finallyStatus = this.finallyInfo.nullStatus(binding);
1045
			if (finallyStatus == FlowInfo.NON_NULL)
1046
				return finallyStatus;
1047
			if (finallyStatus != FlowInfo.NULL) // neither is NON_NULL, but not both are NULL => call it POTENTIALLY_NULL
1048
				status = FlowInfo.POTENTIALLY_NULL;
1049
		}
1061
		}
1050
		if (this != outerScope && this.parent instanceof BlockScope)
1051
			return ((BlockScope) this.parent).mergeCloseStatus(status, binding, outerScope);
1052
	}
1062
	}
1053
	return status;
1054
}
1063
}
1055
1064
1056
private void reportResourceLeak(FakedTrackingVariable trackingVar, ASTNode location, int nullStatus) {
1065
private void reportResourceLeak(FakedTrackingVariable trackingVar, ASTNode location, int nullStatus) {
Lines 1083-1088 public void correlateTrackingVarsIfElse(FlowInfo thenFlowInfo, FlowInfo elseFlow Link Here
1083
	if (this.trackingVariables != null) {
1092
	if (this.trackingVariables != null) {
1084
		for (int i=0; i<this.trackingVariables.size(); i++) {
1093
		for (int i=0; i<this.trackingVariables.size(); i++) {
1085
			FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
1094
			FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
1095
			if (trackingVar.originalBinding == null)
1096
				continue;
1086
			if (   thenFlowInfo.isDefinitelyNonNull(trackingVar.binding)			// closed in then branch
1097
			if (   thenFlowInfo.isDefinitelyNonNull(trackingVar.binding)			// closed in then branch
1087
				&& elseFlowInfo.isDefinitelyNull(trackingVar.originalBinding))		// null in else branch
1098
				&& elseFlowInfo.isDefinitelyNull(trackingVar.originalBinding))		// null in else branch
1088
			{
1099
			{
Lines 1098-1133 public void correlateTrackingVarsIfElse(FlowInfo thenFlowInfo, FlowInfo elseFlow Link Here
1098
	if (this.parent instanceof BlockScope)
1109
	if (this.parent instanceof BlockScope)
1099
		((BlockScope) this.parent).correlateTrackingVarsIfElse(thenFlowInfo, elseFlowInfo);
1110
		((BlockScope) this.parent).correlateTrackingVarsIfElse(thenFlowInfo, elseFlowInfo);
1100
}
1111
}
1101
1102
/**
1103
 * Get the null status looking even into unreachable flows
1104
 * @param local
1105
 * @param flowInfo
1106
 * @return one of the constants FlowInfo.{NULL,POTENTIALLY_NULL,POTENTIALLY_NON_NULL,NON_NULL}.
1107
 */
1108
private int getNullStatusAggressively(LocalVariableBinding local, FlowInfo flowInfo) {
1109
	int reachMode = flowInfo.reachMode();
1110
	int status = 0;
1111
	try {
1112
		// unreachable flowInfo is too shy in reporting null-issues, temporarily forget reachability:
1113
		if (reachMode != FlowInfo.REACHABLE)
1114
			flowInfo.tagBits &= ~FlowInfo.UNREACHABLE;
1115
		status = flowInfo.nullStatus(local);
1116
	} finally {
1117
		// reset
1118
		flowInfo.tagBits |= reachMode;
1119
	}
1120
	// at this point some combinations are not useful so flatten to a single bit:
1121
	if ((status & FlowInfo.NULL) != 0) {
1122
		if ((status & (FlowInfo.NON_NULL | FlowInfo.POTENTIALLY_NON_NULL)) != 0)
1123
			return FlowInfo.POTENTIALLY_NULL; 	// null + doubt = pot null
1124
		return FlowInfo.NULL;
1125
	} else if ((status & FlowInfo.NON_NULL) != 0) {
1126
		if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
1127
			return FlowInfo.POTENTIALLY_NULL;	// non-null + doubt = pot null
1128
		return FlowInfo.NON_NULL;
1129
	} else if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
1130
		return FlowInfo.POTENTIALLY_NULL;
1131
	return status;
1132
}
1133
}
1112
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java (-3 / +7 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 12-17 Link Here
12
 *     						Bug 300576 - NPE Computing type hierarchy when compliance doesn't match libraries
12
 *     						Bug 300576 - NPE Computing type hierarchy when compliance doesn't match libraries
13
 *     						Bug 354536 - compiling package-info.java still depends on the order of compilation units
13
 *     						Bug 354536 - compiling package-info.java still depends on the order of compilation units
14
 *     						Bug 349326 - [1.7] new warning for missing try-with-resources
14
 *     						Bug 349326 - [1.7] new warning for missing try-with-resources
15
 *     						Bug 358903 - Filter practically unimportant resource leak warnings
15
 *******************************************************************************/
16
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.lookup;
17
package org.eclipse.jdt.internal.compiler.lookup;
17
18
Lines 909-915 public class ClassScope extends Scope { Link Here
909
			} else {
910
			} else {
910
				// only want to reach here when no errors are reported
911
				// only want to reach here when no errors are reported
911
				sourceType.superclass = superclass;
912
				sourceType.superclass = superclass;
912
				sourceType.typeBits |= superclass.typeBits;
913
				sourceType.typeBits |= (superclass.typeBits & TypeIds.InheritableBits);
914
				// further analysis against white lists for the unlikely case we are compiling java.io.*:
915
				if ((sourceType.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0)
916
					sourceType.typeBits |= sourceType.applyCloseableWhitelists();
913
				return true;
917
				return true;
914
			}
918
			}
915
		}
919
		}
Lines 1025-1031 public class ClassScope extends Scope { Link Here
1025
				noProblems &= superInterfaceRef.resolvedType.isValidBinding();
1029
				noProblems &= superInterfaceRef.resolvedType.isValidBinding();
1026
			}
1030
			}
1027
			// only want to reach here when no errors are reported
1031
			// only want to reach here when no errors are reported
1028
			sourceType.typeBits |= superInterface.typeBits;
1032
			sourceType.typeBits |= (superInterface.typeBits & TypeIds.InheritableBits);
1029
			interfaceBindings[count++] = superInterface;
1033
			interfaceBindings[count++] = superInterface;
1030
		}
1034
		}
1031
		// hold onto all correctly resolved superinterfaces
1035
		// hold onto all correctly resolved superinterfaces
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java (-4 / +1 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 50-58 public class MethodScope extends BlockScope { Link Here
50
	// inner-emulation
50
	// inner-emulation
51
	public SyntheticArgumentBinding[] extraSyntheticArguments;
51
	public SyntheticArgumentBinding[] extraSyntheticArguments;
52
52
53
	// count number of tracking variables, see FakedTrackingVariable
54
	int trackVarCount = 0;
55
56
public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) {
53
public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) {
57
	super(METHOD_SCOPE, parent);
54
	super(METHOD_SCOPE, parent);
58
	this.locals = new LocalVariableBinding[5];
55
	this.locals = new LocalVariableBinding[5];
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java (+47 lines)
Lines 10-15 Link Here
10
 *     Stephan Herrmann - Contributions for
10
 *     Stephan Herrmann - Contributions for
11
 *								bug 349326 - [1.7] new warning for missing try-with-resources
11
 *								bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *								bug 358903 - Filter practically unimportant resource leak warnings
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.lookup;
15
package org.eclipse.jdt.internal.compiler.lookup;
15
16
Lines 1455-1458 MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't re Link Here
1455
public FieldBinding[] unResolvedFields() {
1456
public FieldBinding[] unResolvedFields() {
1456
	return Binding.NO_FIELDS;
1457
	return Binding.NO_FIELDS;
1457
}
1458
}
1459
1460
/*
1461
 * If a type - known to be a Closeable - is mentioned in one of our white lists
1462
 * answer the typeBit for the white list (BitWrapperCloseable or BitResourceFreeCloseable).
1463
 */
1464
protected int applyCloseableWhitelists() {
1465
	switch (this.compoundName.length) {
1466
		case 3:
1467
			if (CharOperation.equals(TypeConstants.JAVA, this.compoundName[0])) {
1468
				if (CharOperation.equals(TypeConstants.IO, this.compoundName[1])) {
1469
					char[] simpleName = this.compoundName[2];
1470
					int l = TypeConstants.JAVA_IO_WRAPPER_CLOSEABLES.length;
1471
					for (int i = 0; i < l; i++) {
1472
						if (CharOperation.equals(simpleName, TypeConstants.JAVA_IO_WRAPPER_CLOSEABLES[i]))
1473
							return TypeIds.BitWrapperCloseable;
1474
					}
1475
					l = TypeConstants.JAVA_IO_RESOURCE_FREE_CLOSEABLES.length;
1476
					for (int i = 0; i < l; i++) {
1477
						if (CharOperation.equals(simpleName, TypeConstants.JAVA_IO_RESOURCE_FREE_CLOSEABLES[i]))
1478
							return TypeIds.BitResourceFreeCloseable;
1479
					}
1480
				}
1481
			}
1482
			break;
1483
		case 4:
1484
			if (CharOperation.equals(TypeConstants.JAVA, this.compoundName[0])) {
1485
				if (CharOperation.equals(TypeConstants.UTIL, this.compoundName[1])) {
1486
					if (CharOperation.equals(TypeConstants.ZIP, this.compoundName[2])) {
1487
						char[] simpleName = this.compoundName[3];
1488
						int l = TypeConstants.JAVA_UTIL_ZIP_WRAPPER_CLOSEABLES.length;
1489
						for (int i = 0; i < l; i++) {
1490
							if (CharOperation.equals(simpleName, TypeConstants.JAVA_UTIL_ZIP_WRAPPER_CLOSEABLES[i]))
1491
								return TypeIds.BitWrapperCloseable;
1492
						}
1493
					}
1494
				}
1495
			}
1496
			break;
1497
	}
1498
	int l = TypeConstants.OTHER_WRAPPER_CLOSEABLES.length;
1499
	for (int i = 0; i < l; i++) {
1500
		if (CharOperation.equals(this.compoundName, TypeConstants.OTHER_WRAPPER_CLOSEABLES[i]))
1501
			return TypeIds.BitWrapperCloseable;
1502
	}	
1503
	return 0;
1504
}
1458
}
1505
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java (-1 / +57 lines)
Lines 7-13 Link Here
7
 * 
7
 * 
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
10
 *     Stephan Herrmann - Contributions for
11
 *								bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 358903 - Filter practically unimportant resource leak warnings
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.lookup;
14
package org.eclipse.jdt.internal.compiler.lookup;
13
15
Lines 19-24 public interface TypeConstants { Link Here
19
	char[] LANG = "lang".toCharArray(); //$NON-NLS-1$
21
	char[] LANG = "lang".toCharArray(); //$NON-NLS-1$
20
	char[] IO = "io".toCharArray(); //$NON-NLS-1$
22
	char[] IO = "io".toCharArray(); //$NON-NLS-1$
21
	char[] UTIL = "util".toCharArray(); //$NON-NLS-1$
23
	char[] UTIL = "util".toCharArray(); //$NON-NLS-1$
24
	char[] ZIP = "zip".toCharArray(); //$NON-NLS-1$
22
	char[] ANNOTATION = "annotation".toCharArray(); //$NON-NLS-1$
25
	char[] ANNOTATION = "annotation".toCharArray(); //$NON-NLS-1$
23
	char[] REFLECT = "reflect".toCharArray(); //$NON-NLS-1$
26
	char[] REFLECT = "reflect".toCharArray(); //$NON-NLS-1$
24
	char[] LENGTH = "length".toCharArray(); //$NON-NLS-1$
27
	char[] LENGTH = "length".toCharArray(); //$NON-NLS-1$
Lines 154-159 public interface TypeConstants { Link Here
154
	};
157
	};
155
	char[][] JAVA_LANG_AUTOCLOSEABLE =  {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$
158
	char[][] JAVA_LANG_AUTOCLOSEABLE =  {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$
156
	char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$
159
	char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$
160
	// white lists of closeables:
161
	char[][] JAVA_IO_WRAPPER_CLOSEABLES = new char[][] {
162
		"BufferedInputStream".toCharArray(), //$NON-NLS-1$
163
		"BufferedOutputStream".toCharArray(), //$NON-NLS-1$
164
		"BufferedReader".toCharArray(), //$NON-NLS-1$
165
		"BufferedWriter".toCharArray(), //$NON-NLS-1$
166
		"InputStreamReader".toCharArray(), //$NON-NLS-1$
167
		"PrintWriter".toCharArray(),  //$NON-NLS-1$
168
		"LineNumberReader".toCharArray(), //$NON-NLS-1$
169
		"DataInputStream".toCharArray(), //$NON-NLS-1$
170
		"DataOutputStream".toCharArray(), //$NON-NLS-1$
171
		"ObjectInputStream".toCharArray(), //$NON-NLS-1$
172
		"ObjectOutputStream".toCharArray(), //$NON-NLS-1$
173
		"FilterInputStream".toCharArray(), //$NON-NLS-1$
174
		"FilterOutputStream".toCharArray(), //$NON-NLS-1$
175
		"DataInputStream".toCharArray(), //$NON-NLS-1$
176
		"DataOutputStream".toCharArray(), //$NON-NLS-1$
177
		"PushbackInputStream".toCharArray(), //$NON-NLS-1$
178
		"SequenceInputStream".toCharArray(), //$NON-NLS-1$
179
		"PrintStream".toCharArray(), //$NON-NLS-1$
180
		"PushbackReader".toCharArray(), //$NON-NLS-1$
181
		"OutputStreamWriter".toCharArray(), //$NON-NLS-1$
182
	};
183
	char[][] JAVA_UTIL_ZIP_WRAPPER_CLOSEABLES = new char[][] {
184
		"GZIPInputStream".toCharArray(), //$NON-NLS-1$
185
		"InflaterInputStream".toCharArray(), //$NON-NLS-1$
186
		"DeflaterInputStream".toCharArray(), //$NON-NLS-1$
187
		"CheckedInputStream".toCharArray(), //$NON-NLS-1$
188
		"ZipInputStream".toCharArray(), //$NON-NLS-1$
189
		"JarInputStream".toCharArray(), //$NON-NLS-1$
190
		"GZIPOutputStream".toCharArray(), //$NON-NLS-1$
191
		"InflaterOutputStream".toCharArray(), //$NON-NLS-1$
192
		"DeflaterOutputStream".toCharArray(), //$NON-NLS-1$
193
		"CheckedOutputStream".toCharArray(), //$NON-NLS-1$
194
		"ZipOutputStream".toCharArray(), //$NON-NLS-1$
195
		"JarOutputStream".toCharArray(), //$NON-NLS-1$
196
	};
197
	char[][][] OTHER_WRAPPER_CLOSEABLES = new char[][][] {
198
		{JAVA, "security".toCharArray(), "DigestInputStream".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$
199
		{JAVA, "security".toCharArray(), "DigestOutputStream".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$
200
		{JAVA, "beans".toCharArray(), "XMLEncoder".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$
201
		{JAVA, "beans".toCharArray(), "XMLDecoder".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$
202
		{JAVAX, "sound".toCharArray(), "sampled".toCharArray(), "AudioInputStream".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
203
	};
204
	char[][] JAVA_IO_RESOURCE_FREE_CLOSEABLES = new char[][] {			
205
		"StringReader".toCharArray(), //$NON-NLS-1$
206
		"StringWriter".toCharArray(), //$NON-NLS-1$
207
		"ByteArrayInputStream".toCharArray(), //$NON-NLS-1$
208
		"ByteArrayOutputStream".toCharArray(), //$NON-NLS-1$
209
		"CharArrayReader".toCharArray(), //$NON-NLS-1$
210
		"CharArrayWriter".toCharArray(), //$NON-NLS-1$
211
		"StringBufferInputStream".toCharArray(), //$NON-NLS-1$
212
	};
157
213
158
	// Constraints for generic type argument inference
214
	// Constraints for generic type argument inference
159
	int CONSTRAINT_EQUAL = 0;		// Actual = Formal
215
	int CONSTRAINT_EQUAL = 0;		// Actual = Formal
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java (+16 lines)
Lines 11-16 Link Here
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
12
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
13
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *								bug 186342 - [compiler][null] Using annotations for null checking
14
 *								bug 358903 - Filter practically unimportant resource leak warnings
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.internal.compiler.lookup;
16
package org.eclipse.jdt.internal.compiler.lookup;
16
17
Lines 202-205 public interface TypeIds { Link Here
202
	 * @see ReferenceBinding#hasTypeBit(int)
203
	 * @see ReferenceBinding#hasTypeBit(int)
203
	 */
204
	 */
204
	final int BitCloseable = 2;
205
	final int BitCloseable = 2;
206
	/**
207
	 * Bit for members of a white list:
208
	 * Subtypes of Closeable that wrap another resource without directly holding any OS resources. 
209
	 */
210
	final int BitWrapperCloseable = 4;
211
	/**
212
	 * Bit for members of a white list:
213
	 * Subtypes of Closeable that do not hold an OS resource that needs to be released.
214
	 */
215
	final int BitResourceFreeCloseable = 8;
216
	
217
	/**
218
	 * Set of type bits that should be inherited by any sub types.
219
	 */
220
	final int InheritableBits = BitAutoCloseable | BitCloseable;
205
}
221
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java (-3 / +4 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 11-16 Link Here
11
 *     							bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac
11
 *     							bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
13
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
13
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
14
 *								bug 358903 - Filter practically unimportant resource leak warnings
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.internal.compiler.lookup;
16
package org.eclipse.jdt.internal.compiler.lookup;
16
17
Lines 316-326 public class TypeVariableBinding extends ReferenceBinding { Link Here
316
			// initialize from bounds
317
			// initialize from bounds
317
			this.typeBits = 0;
318
			this.typeBits = 0;
318
			if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
319
			if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
319
				this.typeBits |= this.superclass.typeBits;
320
				this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
320
			if (this.superInterfaces != null)
321
			if (this.superInterfaces != null)
321
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
322
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
322
					if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
323
					if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
323
						this.typeBits |= this.superInterfaces[i].typeBits;
324
						this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits);
324
		}
325
		}
325
		return (this.typeBits & bit) != 0;
326
		return (this.typeBits & bit) != 0;
326
	}
327
	}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java (-3 / +4 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2011 IBM Corporation and others.
2
 * Copyright (c) 2005, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 10-15 Link Here
10
 *     Stephan Herrmann - Contribution for
10
 *     Stephan Herrmann - Contribution for
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
12
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
13
 *								bug 358903 - Filter practically unimportant resource leak warnings
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.lookup;
15
package org.eclipse.jdt.internal.compiler.lookup;
15
16
Lines 429-439 public class WildcardBinding extends ReferenceBinding { Link Here
429
			// initialize from upper bounds
430
			// initialize from upper bounds
430
			this.typeBits = 0;
431
			this.typeBits = 0;
431
			if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
432
			if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
432
				this.typeBits |= this.superclass.typeBits;
433
				this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
433
			if (this.superInterfaces != null)
434
			if (this.superInterfaces != null)
434
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
435
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
435
					if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
436
					if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
436
						this.typeBits |= this.superInterfaces[i].typeBits;
437
						this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits);
437
		}
438
		}
438
		return (this.typeBits & bit) != 0;
439
		return (this.typeBits & bit) != 0;
439
	}
440
	}

Return to bug 358903