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/TryWithResourcesStatementTest.java (-2 / +373 lines)
Lines 14-21 Link Here
14
 *******************************************************************************/
14
 *******************************************************************************/
15
package org.eclipse.jdt.core.tests.compiler.regression;
15
package org.eclipse.jdt.core.tests.compiler.regression;
16
16
17
import java.io.IOException;
18
import java.net.URL;
17
import java.util.Map;
19
import java.util.Map;
18
20
21
import org.eclipse.core.runtime.FileLocator;
22
import org.eclipse.core.runtime.Path;
23
import org.eclipse.core.runtime.Platform;
19
import org.eclipse.jdt.core.JavaCore;
24
import org.eclipse.jdt.core.JavaCore;
20
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
25
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
21
26
Lines 23-29 Link Here
23
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
28
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
24
29
25
static {
30
static {
26
//	TESTS_NAMES = new String[] { "test056throw"};
31
//	TESTS_NAMES = new String[] { "test061"};
27
//	TESTS_NUMBERS = new int[] { 50 };
32
//	TESTS_NUMBERS = new int[] { 50 };
28
//	TESTS_RANGE = new int[] { 11, -1 };
33
//	TESTS_RANGE = new int[] { 11, -1 };
29
}
34
}
Lines 5354-5360 Link Here
5354
		"X::~X\n" + 
5359
		"X::~X\n" + 
5355
		"true");
5360
		"true");
5356
}
5361
}
5357
5362
// Bug 358903 - Filter practically unimportant resource leak warnings
5363
// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
5364
// a resource wrapper is not closed but the underlying resource is
5365
public void test061a() {
5366
	Map options = getCompilerOptions();
5367
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5368
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5369
	this.runConformTest(
5370
		new String[] {
5371
			"X.java",
5372
			"import java.io.File;\n" +
5373
			"import java.io.BufferedInputStream;\n" +
5374
			"import java.io.FileInputStream;\n" +
5375
			"import java.io.IOException;\n" +
5376
			"public class X {\n" +
5377
			"    void foo() throws IOException {\n" +
5378
			"        File file = new File(\"somefile\");\n" +
5379
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
5380
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
5381
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
5382
			"        System.out.println(bis.available());\n" +
5383
			"        fileStream.close();\n" +
5384
			"    }\n" +
5385
			"    void inline() throws IOException {\n" +
5386
			"        File file = new File(\"somefile\");\n" +
5387
			"        FileInputStream fileStream;\n" +
5388
			"        BufferedInputStream bis = new BufferedInputStream(fileStream = new FileInputStream(file));\n" +
5389
			"        System.out.println(bis.available());\n" +
5390
			"        fileStream.close();\n" +
5391
			"    }\n" +
5392
			"    public static void main(String[] args) throws IOException {\n" +
5393
			"        try {\n" +
5394
			"            new X().foo();\n" +
5395
			"        } catch (IOException ex) {" +
5396
			"            System.out.println(\"Got IO Exception\");\n" +
5397
			"        }\n" +
5398
			"    }\n" +
5399
			"}\n"
5400
		},
5401
		"Got IO Exception",
5402
		null,
5403
		true,
5404
		null,
5405
		options,
5406
		null);
5407
}
5408
// Bug 358903 - Filter practically unimportant resource leak warnings
5409
// a closeable without OS resource is not closed
5410
public void test061b() {
5411
	Map options = getCompilerOptions();
5412
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5413
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5414
	this.runConformTest(
5415
		new String[] {
5416
			"X.java",
5417
			"import java.io.StringReader;\n" +
5418
			"import java.io.IOException;\n" +
5419
			"public class X {\n" +
5420
			"    void foo() throws IOException {\n" +
5421
			"        StringReader string  = new StringReader(\"content\");\n" +
5422
			"        System.out.println(string.read());\n" +
5423
			"    }\n" +
5424
			"    public static void main(String[] args) throws IOException {\n" +
5425
			"        new X().foo();\n" +
5426
			"    }\n" +
5427
			"}\n"
5428
		},
5429
		"99", // character 'c'
5430
		null,
5431
		true,
5432
		null,
5433
		options,
5434
		null);
5435
}
5436
// Bug 358903 - Filter practically unimportant resource leak warnings
5437
// a resource wrapper is not closed but the underlying closeable is resource-free
5438
public void test061c() {
5439
	Map options = getCompilerOptions();
5440
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5441
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5442
	this.runConformTest(
5443
		new String[] {
5444
			"X.java",
5445
			"import java.io.BufferedReader;\n" +
5446
			"import java.io.StringReader;\n" +
5447
			"import java.io.IOException;\n" +
5448
			"public class X {\n" +
5449
			"    void foo() throws IOException {\n" +
5450
			"        StringReader input = new StringReader(\"content\");\n" +
5451
			"        BufferedReader br = new BufferedReader(input);\n" +
5452
			"        BufferedReader doubleWrap = new BufferedReader(br);\n" +
5453
			"        System.out.println(br.read());\n" +
5454
			"    }\n" +
5455
			"    void inline() throws IOException {\n" +
5456
			"        BufferedReader br = new BufferedReader(new StringReader(\"content\"));\n" +
5457
			"        System.out.println(br.read());\n" +
5458
			"    }\n" +
5459
			"    public static void main(String[] args) throws IOException {\n" +
5460
			"        new X().foo();\n" +
5461
			"    }\n" +
5462
			"}\n"
5463
		},
5464
		"99",
5465
		null,
5466
		true,
5467
		null,
5468
		options,
5469
		null);
5470
}
5471
// Bug 358903 - Filter practically unimportant resource leak warnings
5472
// a resource wrapper is not closed neither is the underlying resource
5473
public void test061d() {
5474
	Map options = getCompilerOptions();
5475
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5476
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
5477
	this.runNegativeTest(
5478
		new String[] {
5479
			"X.java",
5480
			"import java.io.File;\n" +
5481
			"import java.io.BufferedInputStream;\n" +
5482
			"import java.io.FileInputStream;\n" +
5483
			"import java.io.IOException;\n" +
5484
			"public class X {\n" +
5485
			"    void foo() throws IOException {\n" +
5486
			"        File file = new File(\"somefile\");\n" +
5487
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
5488
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
5489
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
5490
			"        System.out.println(bis.available());\n" +
5491
			"    }\n" +
5492
			"    void inline() throws IOException {\n" +
5493
			"        File file = new File(\"somefile\");\n" +
5494
			"        BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(file));\n" +
5495
			"        System.out.println(bis2.available());\n" +
5496
			"    }\n" +
5497
			"    public static void main(String[] args) throws IOException {\n" +
5498
			"        try {\n" +
5499
			"            new X().foo();\n" +
5500
			"        } catch (IOException ex) {" +
5501
			"            System.out.println(\"Got IO Exception\");\n" +
5502
			"        }\n" +
5503
			"    }\n" +
5504
			"}\n"
5505
		},
5506
		"----------\n" + 
5507
		"1. ERROR in X.java (at line 10)\n" + 
5508
		"	BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" + 
5509
		"	                    ^^^^^^^^^^\n" + 
5510
		"Resource leak: \'doubleWrap\' is never closed\n" + 
5511
		"----------\n" + 
5512
		"2. ERROR in X.java (at line 15)\n" + 
5513
		"	BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(file));\n" + 
5514
		"	                    ^^^^\n" + 
5515
		"Resource leak: \'bis2\' is never closed\n" + 
5516
		"----------\n",
5517
		null,
5518
		true,
5519
		options);
5520
}
5521
// Bug 358903 - Filter practically unimportant resource leak warnings
5522
// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
5523
//a resource wrapper is closed closing also the underlying resource
5524
public void test061e() {
5525
	Map options = getCompilerOptions();
5526
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5527
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5528
	this.runConformTest(
5529
		new String[] {
5530
			"X.java",
5531
			"import java.io.File;\n" +
5532
			"import java.io.BufferedInputStream;\n" +
5533
			"import java.io.FileInputStream;\n" +
5534
			"import java.io.IOException;\n" +
5535
			"public class X {\n" +
5536
			"    FileInputStream fis;" +
5537
			"    void foo() throws IOException {\n" +
5538
			"        File file = new File(\"somefile\");\n" +
5539
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
5540
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
5541
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
5542
			"        System.out.println(bis.available());\n" +
5543
			"        bis.close();\n" +
5544
			"    }\n" +
5545
			"    void inline() throws IOException {\n" +
5546
			"        File file = new File(\"somefile\");\n" +
5547
			"        BufferedInputStream bis2 = new BufferedInputStream(fis = new FileInputStream(file));\n" + // field assignment
5548
			"        System.out.println(bis2.available());\n" +
5549
			"        bis2.close();\n" +
5550
			"        FileInputStream fileStream  = null;\n" +
5551
			"        BufferedInputStream bis3 = new BufferedInputStream(fileStream = new FileInputStream(file));\n" +
5552
			"        System.out.println(bis3.available());\n" +
5553
			"        bis3.close();\n" +
5554
			"    }\n" +
5555
			"    public static void main(String[] args) throws IOException {\n" +
5556
			"        try {\n" +
5557
			"            new X().foo();\n" +
5558
			"        } catch (IOException ex) {" +
5559
			"            System.out.println(\"Got IO Exception\");\n" +
5560
			"        }\n" +
5561
			"    }\n" +
5562
			"}\n"
5563
		},
5564
		"Got IO Exception",
5565
		null,
5566
		true,
5567
		null,
5568
		options,
5569
		null);
5570
}
5571
// Bug 358903 - Filter practically unimportant resource leak warnings
5572
// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
5573
// a resource wrapper is closed closing also the underlying resource - original test case
5574
public void test061f() throws IOException {
5575
	Map options = getCompilerOptions();
5576
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5577
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5578
	URL url = FileLocator.toFileURL(FileLocator.find(Platform.getBundle("org.eclipse.jdt.core.tests.compiler"), new Path("META-INF/MANIFEST.MF"), null));
5579
	this.runConformTest(
5580
		new String[] {
5581
			"X.java",
5582
			"import java.io.InputStream;\n" +
5583
			"import java.io.InputStreamReader;\n" +
5584
			"import java.io.BufferedReader;\n" +
5585
			"import java.io.IOException;\n" +
5586
			"import java.net.URL;\n" +
5587
			"public class X {\n" +
5588
			"    boolean loadURL(final URL url) throws IOException {\n" + 
5589
			"    InputStream stream = null;\n" + 
5590
			"        BufferedReader reader = null;\n" + 
5591
			"        try {\n" + 
5592
			"            stream = url.openStream();\n" + 
5593
			"            reader = new BufferedReader(new InputStreamReader(stream));\n" + 
5594
			"            System.out.println(reader.readLine());\n" +
5595
			"        } finally {\n" + 
5596
			"            try {\n" + 
5597
			"                if (reader != null)\n" + 
5598
			"                    reader.close();\n" + 
5599
			"            } catch (IOException x) {\n" + 
5600
			"            }\n" + 
5601
			"        }\n" + 
5602
			"        return false; // 'stream' may not be closed at this location\n" + 
5603
			"    }\n" + 
5604
			"    public static void main(String[] args) throws IOException {\n" +
5605
			"        try {\n" +
5606
			"            new X().loadURL(new URL(\""+url.toString()+"\"));\n" +
5607
			"        } catch (IOException ex) {\n" +
5608
			"            System.out.println(\"Got IO Exception\"+ex);\n" +
5609
			"        }\n" +
5610
			"    }\n" +
5611
			"}\n"
5612
		},
5613
		"Manifest-Version: 1.0",
5614
		null,
5615
		true,
5616
		null,
5617
		options,
5618
		null);
5619
}
5620
// Bug 358903 - Filter practically unimportant resource leak warnings
5621
// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
5622
// Different points in a resource chain are closed
5623
public void test061g() {
5624
	Map options = getCompilerOptions();
5625
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5626
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5627
	this.runNegativeTest(
5628
		new String[] {
5629
			"X.java",
5630
			"import java.io.File;\n" +
5631
			"import java.io.BufferedInputStream;\n" +
5632
			"import java.io.FileInputStream;\n" +
5633
			"import java.io.IOException;\n" +
5634
			"public class X {\n" +
5635
			"    void closeMiddle() throws IOException {\n" +
5636
			"        File file = new File(\"somefile\");\n" +
5637
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
5638
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
5639
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
5640
			"        System.out.println(bis.available());\n" +
5641
			"        bis.close();\n" +
5642
			"    }\n" +
5643
			"    void closeOuter() throws IOException {\n" +
5644
			"        File file2 = new File(\"somefile\");\n" +
5645
			"        FileInputStream fileStream2  = new FileInputStream(file2);\n" +
5646
			"        BufferedInputStream bis2 = new BufferedInputStream(fileStream2);\n" +
5647
			"        BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" +
5648
			"        System.out.println(bis2.available());\n" +
5649
			"        doubleWrap2.close();\n" +
5650
			"    }\n" +
5651
			"    void neverClosed() throws IOException {\n" +
5652
			"        File file3 = new File(\"somefile\");\n" +
5653
			"        FileInputStream fileStream3  = new FileInputStream(file3);\n" +
5654
			"        BufferedInputStream bis3 = new BufferedInputStream(fileStream3);\n" +
5655
			"        BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" +
5656
			"        System.out.println(doubleWrap3.available());\n" +
5657
			"    }\n" +
5658
			"}\n"
5659
		},
5660
		"----------\n" + 
5661
		"1. ERROR in X.java (at line 26)\n" + 
5662
		"	BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" + 
5663
		"	                    ^^^^^^^^^^^\n" + 
5664
		"Resource leak: \'doubleWrap3\' is never closed\n" + 
5665
		"----------\n",
5666
		null,
5667
		true,
5668
		options);
5669
}
5670
// Bug 358903 - Filter practically unimportant resource leak warnings
5671
// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
5672
// Different points in a resource chain are potentially closed
5673
public void test061h() {
5674
	Map options = getCompilerOptions();
5675
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5676
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5677
	this.runNegativeTest(
5678
		new String[] {
5679
			"X.java",
5680
			"import java.io.File;\n" +
5681
			"import java.io.BufferedInputStream;\n" +
5682
			"import java.io.FileInputStream;\n" +
5683
			"import java.io.IOException;\n" +
5684
			"public class X {\n" +
5685
			"    void closeMiddle(boolean b) throws IOException {\n" +
5686
			"        File file = new File(\"somefile\");\n" +
5687
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
5688
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
5689
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
5690
			"        System.out.println(bis.available());\n" +
5691
			"        if (b)\n" +
5692
			"            bis.close();\n" +
5693
			"    }\n" +
5694
			"    void closeOuter(boolean b) throws IOException {\n" +
5695
			"        File file2 = new File(\"somefile\");\n" +
5696
			"        FileInputStream fileStream2  = new FileInputStream(file2);\n" +
5697
			"        BufferedInputStream bis2 = new BufferedInputStream(fileStream2);\n" +
5698
			"        BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" +
5699
			"        System.out.println(bis2.available());\n" +
5700
			"        if (b)\n" +
5701
			"            doubleWrap2.close();\n" +
5702
			"    }\n" +
5703
			"    void potAndDef(boolean b) throws IOException {\n" +
5704
			"        File file3 = new File(\"somefile\");\n" +
5705
			"        FileInputStream fileStream3  = new FileInputStream(file3);\n" +
5706
			"        BufferedInputStream bis3 = new BufferedInputStream(fileStream3);\n" +
5707
			"        BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" +
5708
			"        System.out.println(doubleWrap3.available());\n" +
5709
			"        if (b) bis3.close();\n" +
5710
			"        fileStream3.close();\n" +
5711
			"    }\n" +
5712
			"}\n"
5713
		},
5714
		"----------\n" + 
5715
		"1. ERROR in X.java (at line 10)\n" + 
5716
		"	BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" + 
5717
		"	                    ^^^^^^^^^^\n" + 
5718
		"Potential resource leak: \'doubleWrap\' may not be closed\n" + 
5719
		"----------\n" + 
5720
		"2. ERROR in X.java (at line 19)\n" + 
5721
		"	BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" + 
5722
		"	                    ^^^^^^^^^^^\n" + 
5723
		"Potential resource leak: \'doubleWrap2\' may not be closed\n" + 
5724
		"----------\n",
5725
		null,
5726
		true,
5727
		options);
5728
}
5358
public static Class testClass() {
5729
public static Class testClass() {
5359
	return TryWithResourcesStatementTest.class;
5730
	return TryWithResourcesStatementTest.class;
5360
}
5731
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java (-2 / +2 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 45-51 Link Here
45
	if (this.arguments != null) {
45
	if (this.arguments != null) {
46
		for (int i = 0, count = this.arguments.length; i < count; i++) {
46
		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.)
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);
48
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, this.resolvedType);
49
			flowInfo =
49
			flowInfo =
50
				this.arguments[i]
50
				this.arguments[i]
51
					.analyseCode(currentScope, flowContext, flowInfo)
51
					.analyseCode(currentScope, flowContext, flowInfo)
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java (-5 / +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 50-63 Link Here
50
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
50
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
51
		.unconditionalInits();
51
		.unconditionalInits();
52
	if (local != null) {
52
	if (local != null) {
53
		LocalVariableBinding previousTrackerBinding = null;
53
		FakedTrackingVariable previousTracker = null;
54
		if (local.closeTracker != null) {
54
		if (local.closeTracker != null) {
55
			// Assigning to a variable already holding an AutoCloseable, has it been closed before?
55
			// Assigning to a variable already holding an AutoCloseable, has it been closed before?
56
			previousTrackerBinding = local.closeTracker.binding;
56
			previousTracker = local.closeTracker;
57
			if (!flowInfo.isDefinitelyNull(local)) // only if previous value may be non-null
57
			if (!flowInfo.isDefinitelyNull(local)) // only if previous value may be non-null
58
				local.closeTracker.recordErrorLocation(this, flowInfo.nullStatus(previousTrackerBinding));
58
				local.closeTracker.recordErrorLocation(this, flowInfo.nullStatus(previousTracker.binding));
59
		}
59
		}
60
		FakedTrackingVariable.handleResourceAssignment(flowInfo, this, this.expression, local, previousTrackerBinding);
60
		FakedTrackingVariable.handleResourceAssignment(flowInfo, this, this.expression, local, previousTracker);
61
	}
61
	}
62
	int nullStatus = this.expression.nullStatus(flowInfo);
62
	int nullStatus = this.expression.nullStatus(flowInfo);
63
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
63
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java (-13 / +141 lines)
Lines 48-56 Link Here
48
	private static final int CLOSED_IN_NESTED_METHOD = 4;
48
	private static final int CLOSED_IN_NESTED_METHOD = 4;
49
	// a location independent issue has been reported already against this resource:
49
	// a location independent issue has been reported already against this resource:
50
	private static final int REPORTED = 8;
50
	private static final int REPORTED = 8;
51
	// a resource is wrapped in another resource:
52
	private static final int WRAPPED = 16;
51
	
53
	
52
	/**
54
	/**
53
	 * Bitset of {@link #CLOSE_SEEN}, {@link #PASSED_TO_OUTSIDE}, {@link #CLOSED_IN_NESTED_METHOD} and {@link #REPORTED}.
55
	 * Bitset of {@link #CLOSE_SEEN}, {@link #PASSED_TO_OUTSIDE}, {@link #CLOSED_IN_NESTED_METHOD}, {@link #REPORTED} and {@link #WRAPPED}.
54
	 */
56
	 */
55
	private int globalClosingState = 0;
57
	private int globalClosingState = 0;
56
58
Lines 58-67 Link Here
58
	
60
	
59
	public LocalVariableBinding originalBinding; // the real local being tracked
61
	public LocalVariableBinding originalBinding; // the real local being tracked
60
	
62
	
61
	HashMap recordedLocations; // initially null, ASTNode -> Integer 
63
	HashMap recordedLocations; // initially null, ASTNode -> Integer
64
65
	public FakedTrackingVariable innerTracker; // chained tracking variable of a chained (wrapped) resource
62
66
63
67
64
	public FakedTrackingVariable(LocalVariableBinding original, Statement location) {
68
	public FakedTrackingVariable(LocalVariableBinding original, ASTNode location) {
65
		super(original.name, location.sourceStart, location.sourceEnd);
69
		super(original.name, location.sourceStart, location.sourceEnd);
66
		this.type = new SingleTypeReference(
70
		this.type = new SingleTypeReference(
67
				TypeConstants.OBJECT,
71
				TypeConstants.OBJECT,
Lines 131-138 Link Here
131
	 * Check if the rhs of an assignment or local declaration is an (Auto)Closeable.
135
	 * 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. 
136
	 * If so create or re-use a tracking variable, and wire and initialize everything. 
133
	 */
137
	 */
134
	public static void handleResourceAssignment(FlowInfo flowInfo, Statement location, Expression rhs, LocalVariableBinding local,
138
	public static void handleResourceAssignment(FlowInfo flowInfo, ASTNode location, Expression rhs, LocalVariableBinding local,
135
				LocalVariableBinding previousTrackerBinding) 
139
				FakedTrackingVariable previousTracker) 
136
	{
140
	{
137
		if (isAutoCloseable(rhs.resolvedType)) {
141
		if (isAutoCloseable(rhs.resolvedType)) {
138
			// new value is AutoCloseable, start tracking, possibly re-using existing tracker var:
142
			// new value is AutoCloseable, start tracking, possibly re-using existing tracker var:
Lines 141-151 Link Here
141
			if (rhsTrackVar != null) {								// 1. share tracking variable with RHS?
145
			if (rhsTrackVar != null) {								// 1. share tracking variable with RHS?
142
				local.closeTracker = rhsTrackVar;
146
				local.closeTracker = rhsTrackVar;
143
				// keep null-status unchanged across this assignment
147
				// keep null-status unchanged across this assignment
144
			} else if (previousTrackerBinding != null) {			// 2. re-use tracking variable from the LHS?
148
			} else if (previousTracker != null) {					// 2. re-use tracking variable from the LHS?
145
				// re-assigning from a fresh, mark as not-closed again:
149
				// re-assigning from a fresh, mark as not-closed again:
146
				flowInfo.markAsDefinitelyNull(previousTrackerBinding);
150
				flowInfo.markAsDefinitelyNull(previousTracker.binding);
151
				local.closeTracker = analyseCloseableExpression(flowInfo, local, location, rhs, previousTracker);
147
			} else {												// 3. no re-use, create a fresh tracking variable:
152
			} else {												// 3. no re-use, create a fresh tracking variable:
148
				local.closeTracker = new FakedTrackingVariable(local, location);
153
				rhsTrackVar = analyseCloseableExpression(flowInfo, local, location, rhs, null);
154
				if (rhsTrackVar == null)
155
					return;
156
				local.closeTracker = rhsTrackVar;
149
				// a fresh resource, mark as not-closed:
157
				// a fresh resource, mark as not-closed:
150
				flowInfo.markAsDefinitelyNull(local.closeTracker.binding);
158
				flowInfo.markAsDefinitelyNull(local.closeTracker.binding);
151
// TODO(stephan): this might be useful, but I could not find a test case for it: 
159
// TODO(stephan): this might be useful, but I could not find a test case for it: 
Lines 153-158 Link Here
153
//					flowContext.initsOnFinally.markAsDefinitelyNonNull(trackerBinding);
161
//					flowContext.initsOnFinally.markAsDefinitelyNonNull(trackerBinding);
154
			}
162
			}
155
		}
163
		}
164
	}
165
	/**
166
	 * analyze structure of a closeable expression, matching (chained) resources against our white lists.
167
	 * See  Bug 358903 - Filter practically unimportant resource leak warnings
168
	 * @param flowInfo used when recursing back into {@link #handleResourceAssignment}
169
	 * @param local local variable to which the closeable is being assigned
170
	 * @param location where to flag errors/warnings against
171
	 * @param expression expression to be analyzed
172
	 * @param previousTracker when analyzing a re-assignment we may already have a tracking variable for local,
173
	 *  		which we should then re-use
174
	 * @return a tracking variable associated with local or null if no need to track
175
	 */
176
	private static FakedTrackingVariable analyseCloseableExpression(FlowInfo flowInfo, 
177
				LocalVariableBinding local, ASTNode location, Expression expression, FakedTrackingVariable previousTracker) 
178
	{
179
		if (expression.resolvedType instanceof ReferenceBinding) {
180
			ReferenceBinding resourceType = (ReferenceBinding) expression.resolvedType;
181
			
182
			if (resourceType.hasTypeBit(TypeIds.BitResourceFreeCloseable)) {
183
				// (a) resource-free closeable: -> null
184
				return null;
185
			}					
186
			
187
			if (resourceType.hasTypeBit(TypeIds.BitWrapperCloseable)) {
188
				// (b) wrapper
189
				Expression innerExpression = expression; 
190
				if (innerExpression instanceof Assignment)
191
					innerExpression = ((Assignment)innerExpression).expression;
192
				if (innerExpression instanceof AllocationExpression) {
193
					Expression[] args = ((AllocationExpression) innerExpression).arguments;
194
					if (args != null && args.length == 1) {
195
						// (b.1) wrapper allocation with argument
196
						return analyseCloseableAllocationArgument(flowInfo, local, location, args[0], previousTracker);
197
					}
198
				}
199
				LocalVariableBinding innerLocal = innerExpression.localVariableBinding();
200
				if (innerLocal != null && innerLocal.closeTracker != null) {
201
					FakedTrackingVariable outerTracker = previousTracker != null ? previousTracker : new FakedTrackingVariable(local, location); 
202
					outerTracker.innerTracker = innerLocal.closeTracker;
203
					innerLocal.closeTracker.globalClosingState |= WRAPPED;
204
					return outerTracker;
205
				}
206
				// (b.2) wrapper with irrelevant inner: -> null
207
				return null;
208
			}
209
		}
210
		if (local.closeTracker != null)
211
			// (c): inner has already been analysed: -> re-use track var
212
			return local.closeTracker;
213
		// (d): normal resource: -> normal tracking var
214
		if (previousTracker != null)
215
			return previousTracker; // (d.1): re-use existing tracking var
216
		return new FakedTrackingVariable(local, location);
217
	}
218
219
	// an outer allocation expression has an argument, recursively analyze whether the arg is closeable 
220
	// return (1) a possible nested tracker for the outer expression or (2) null signaling no relevant resource contained  
221
	static FakedTrackingVariable analyseCloseableAllocationArgument(FlowInfo flowInfo, LocalVariableBinding outerLocal, ASTNode outerLocation, 
222
			Expression arg, FakedTrackingVariable previousTracker)
223
	{
224
		if (arg instanceof Assignment) {
225
			Assignment assign = (Assignment)arg;
226
			LocalVariableBinding innerLocal = assign.localVariableBinding();
227
			if (innerLocal != null) {
228
				// recurse from the top for nested assignment:
229
				handleResourceAssignment(flowInfo, assign, assign.expression, innerLocal, innerLocal.closeTracker);
230
				return innerLocal.closeTracker; // FIXME do we need a nested tracker here?
231
			} else {
232
				arg = assign.expression; // unwrap assignment and fall through
233
			}
234
		}
235
		if (arg instanceof SingleNameReference) {
236
			SingleNameReference ref = (SingleNameReference) arg;
237
			if (ref.binding instanceof LocalVariableBinding) {
238
				// allocation arg is a reference to an existing closeable?
239
				return getTrackingVarForNested(flowInfo, outerLocal, outerLocation, (LocalVariableBinding)ref.binding, ref, ref, previousTracker);
240
			}
241
		} else if (arg instanceof AllocationExpression && arg.resolvedType instanceof ReferenceBinding) {
242
			// nested allocation
243
			ReferenceBinding innerType = (ReferenceBinding)arg.resolvedType;
244
			if (innerType.hasTypeBit(TypeIds.BitResourceFreeCloseable)) {
245
				return null; // leaf of wrapper-chain is irrelevant
246
			} else if (innerType.hasTypeBit(TypeIds.BitWrapperCloseable)) {
247
				// nested wrapper, nested tracking variables may skip this level as it is not bound to a local variable
248
				Expression[] args = ((AllocationExpression) arg).arguments;
249
				if (args != null && args.length > 0)
250
					return analyseCloseableAllocationArgument(flowInfo, outerLocal, arg, args[0], previousTracker);
251
				return null; // wrapper with no arg? shouldn't occur actually
252
			} else {
253
				// (c) wrapper alloc with direct nested alloc of regular: -> normal track var (no local represents inner)
254
				return previousTracker != null ? previousTracker : new FakedTrackingVariable(outerLocal, outerLocation);
255
			}
256
		}
257
		return null;
258
	}
259
	
260
	// an outer allocation expression has an argument, create/link outer and inner tracking variable and return the outer
261
	// return null if inner is not tracked
262
	private static FakedTrackingVariable getTrackingVarForNested(FlowInfo flowInfo, LocalVariableBinding outerLocal, ASTNode outerLocation, 
263
			LocalVariableBinding innerLocal, ASTNode innerLocation, Expression innerExpression, FakedTrackingVariable previousTracker)
264
	{
265
		FakedTrackingVariable innerTracker = analyseCloseableExpression(flowInfo, innerLocal, innerLocation, innerExpression, null);
266
		if (innerTracker != null) {
267
			FakedTrackingVariable outerTracker = previousTracker != null ? previousTracker : new FakedTrackingVariable(outerLocal, outerLocation); 
268
			outerTracker.innerTracker = innerTracker;
269
			innerTracker.globalClosingState |= WRAPPED;
270
			return outerTracker;
271
		}
272
		return null;
156
	}
273
	}
157
274
158
	/** Answer wither the given type binding is a subtype of java.lang.AutoCloseable. */
275
	/** Answer wither the given type binding is a subtype of java.lang.AutoCloseable. */
Lines 180-186 Link Here
180
	 * (as argument to a method/ctor call or as a return value from the current method), 
297
	 * (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.
298
	 * and thus should be considered as potentially closed.
182
	 */
299
	 */
183
	public static FlowInfo markPassedToOutside(BlockScope scope, Expression expression, FlowInfo flowInfo) {
300
	public static FlowInfo markPassedToOutside(BlockScope scope, Expression expression, FlowInfo flowInfo, TypeBinding allocatedType) {	
301
		if ((allocatedType instanceof ReferenceBinding) 
302
				&& ((ReferenceBinding) allocatedType).hasTypeBit(TypeIds.BitWrapperCloseable))
303
			return flowInfo; // wrapped closeables are analyzed separately:
304
		
184
		FakedTrackingVariable trackVar = getCloseTrackingVariable(expression);
305
		FakedTrackingVariable trackVar = getCloseTrackingVariable(expression);
185
		if (trackVar != null) {
306
		if (trackVar != null) {
186
			trackVar.globalClosingState |= PASSED_TO_OUTSIDE;
307
			trackVar.globalClosingState |= PASSED_TO_OUTSIDE;
Lines 201-209 Link Here
201
	}
322
	}
202
323
203
	public boolean reportRecordedErrors(Scope scope) {
324
	public boolean reportRecordedErrors(Scope scope) {
204
		if (this.globalClosingState == 0) {
325
		FakedTrackingVariable current = this;
205
			reportError(scope.problemReporter(), null, FlowInfo.NULL);
326
		while (current.globalClosingState == 0) {
206
			return true;
327
			current = current.innerTracker;
328
			if (current == null) {
329
				// no relevant state found -> report:
330
				reportError(scope.problemReporter(), null, FlowInfo.NULL);
331
				return true;
332
			}
207
		}
333
		}
208
		boolean hasReported = false;
334
		boolean hasReported = false;
209
		if (this.recordedLocations != null) {
335
		if (this.recordedLocations != null) {
Lines 218-223 Link Here
218
	}
344
	}
219
	
345
	
220
	public void reportError(ProblemReporter problemReporter, ASTNode location, int nullStatus) {
346
	public void reportError(ProblemReporter problemReporter, ASTNode location, int nullStatus) {
347
		if ((this.globalClosingState & WRAPPED) != 0)
348
			return;
221
		if (nullStatus == FlowInfo.NULL) {
349
		if (nullStatus == FlowInfo.NULL) {
222
			if ((this.globalClosingState & CLOSED_IN_NESTED_METHOD) != 0)
350
			if ((this.globalClosingState & CLOSED_IN_NESTED_METHOD) != 0)
223
				problemReporter.potentiallyUnclosedCloseable(this, location);
351
				problemReporter.potentiallyUnclosedCloseable(this, location);
Lines 225-231 Link Here
225
				problemReporter.unclosedCloseable(this, location);
353
				problemReporter.unclosedCloseable(this, location);
226
		} else if (nullStatus == FlowInfo.POTENTIALLY_NULL) {
354
		} else if (nullStatus == FlowInfo.POTENTIALLY_NULL) {
227
			problemReporter.potentiallyUnclosedCloseable(this, location);
355
			problemReporter.potentiallyUnclosedCloseable(this, location);
228
		}		
356
		}
229
	}
357
	}
230
358
231
	public void reportExplicitClosing(ProblemReporter problemReporter) {
359
	public void reportExplicitClosing(ProblemReporter problemReporter) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (-1 / +1 lines)
Lines 97-103 Link Here
97
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
97
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
98
			}
98
			}
99
			// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
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);
100
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, null);
101
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
101
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
102
		}
102
		}
103
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
103
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java (-1 / +1 lines)
Lines 81-87 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, null);
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/lookup/BinaryTypeBinding.java (-3 / +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 1275-1281 Link Here
1275
			this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
1275
			this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
1276
		}
1276
		}
1277
	}
1277
	}
1278
	this.typeBits |= this.superclass.typeBits;
1278
	this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
1279
	if (this.hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable))
1280
		this.typeBits |= applyCloseableWhitelists();
1279
	return this.superclass;
1281
	return this.superclass;
1280
}
1282
}
1281
// NOTE: superInterfaces of binary types are resolved when needed
1283
// NOTE: superInterfaces of binary types are resolved when needed
Lines 1298-1304 Link Here
1298
				this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
1300
				this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
1299
			}	
1301
			}	
1300
		}
1302
		}
1301
		this.typeBits |= this.superInterfaces[i].typeBits;
1303
		this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits);
1302
	}
1304
	}
1303
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
1305
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
1304
	return this.superInterfaces;
1306
	return this.superInterfaces;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java (-5 / +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 1003-1012 Link Here
1003
		FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
1003
		FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
1004
		if (location != null && trackingVar.originalBinding != null && flowInfo.isDefinitelyNull(trackingVar.originalBinding))
1004
		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
1005
			continue; // reporting against a specific location, resource is null at this flow, don't complain
1006
		int status = getNullStatusAggressively(trackingVar.binding, flowInfo);
1006
		
1007
		// try to improve info if a close() inside finally was observed:
1007
		// compute the most specific null status for this resource,
1008
		if (locationScope != null) // only check at method exit points
1008
		// consider wrappers (per white list) encapsulating an inner resource.
1009
			status = locationScope.mergeCloseStatus(status, trackingVar.binding, this);
1009
		int status = FlowInfo.UNKNOWN;
1010
		FakedTrackingVariable currentTracker = trackingVar;
1011
		while (currentTracker != null) {
1012
			LocalVariableBinding currentVar = currentTracker.binding;
1013
			int currentStatus = getNullStatusAggressively(currentVar, flowInfo);
1014
			if (locationScope != null) // only check at method exit points
1015
				currentStatus = locationScope.mergeCloseStatus(currentStatus, currentVar, this);
1016
			if (currentStatus == FlowInfo.NON_NULL) {
1017
				status = currentStatus;
1018
				break; // closed -> stop searching
1019
			} else if (status == FlowInfo.NULL || status == FlowInfo.UNKNOWN) {
1020
				status = currentStatus; // improved although not yet safe -> keep searching for better
1021
			}
1022
			currentTracker = currentTracker.innerTracker;
1023
		}
1024
		
1010
		if (status == FlowInfo.NULL) {
1025
		if (status == FlowInfo.NULL) {
1011
			// definitely unclosed: highest priority
1026
			// definitely unclosed: highest priority
1012
			reportResourceLeak(trackingVar, location, status);
1027
			reportResourceLeak(trackingVar, location, status);
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.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 909-915 Link Here
909
			} else {
909
			} else {
910
				// only want to reach here when no errors are reported
910
				// only want to reach here when no errors are reported
911
				sourceType.superclass = superclass;
911
				sourceType.superclass = superclass;
912
				sourceType.typeBits |= superclass.typeBits;
912
				sourceType.typeBits |= (superclass.typeBits & TypeIds.InheritableBits);
913
				// further analysis against white lists for the unlikely case we are compiling java.io.*:
914
				if (sourceType.hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable))
915
					sourceType.typeBits |= sourceType.applyCloseableWhitelists();
913
				return true;
916
				return true;
914
			}
917
			}
915
		}
918
		}
Lines 1025-1031 Link Here
1025
				noProblems &= superInterfaceRef.resolvedType.isValidBinding();
1028
				noProblems &= superInterfaceRef.resolvedType.isValidBinding();
1026
			}
1029
			}
1027
			// only want to reach here when no errors are reported
1030
			// only want to reach here when no errors are reported
1028
			sourceType.typeBits |= superInterface.typeBits;
1031
			sourceType.typeBits |= (superInterface.typeBits & TypeIds.InheritableBits);
1029
			interfaceBindings[count++] = superInterface;
1032
			interfaceBindings[count++] = superInterface;
1030
		}
1033
		}
1031
		// hold onto all correctly resolved superinterfaces
1034
		// hold onto all correctly resolved superinterfaces
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java (+27 lines)
Lines 1469-1472 Link Here
1469
public FieldBinding[] unResolvedFields() {
1469
public FieldBinding[] unResolvedFields() {
1470
	return Binding.NO_FIELDS;
1470
	return Binding.NO_FIELDS;
1471
}
1471
}
1472
1473
/*
1474
 * If a type - known to be a Closeable - is mentioned in one of our white lists
1475
 * answer the typeBit for the white list (BitWrapperCloseable or BitResourceFreeCloseable).
1476
 */
1477
protected int applyCloseableWhitelists() {
1478
	switch (this.compoundName.length) {
1479
		case 3:
1480
			if (CharOperation.equals(TypeConstants.JAVA, this.compoundName[0])) {
1481
				if (CharOperation.equals(TypeConstants.IO, this.compoundName[1])) {
1482
					char[] simpleName = this.compoundName[2];
1483
					int l = TypeConstants.JAVA_IO_WRAPPER_CLOSEABLES.length;
1484
					for (int i = 0; i < l; i++) {
1485
						if (CharOperation.equals(simpleName, TypeConstants.JAVA_IO_WRAPPER_CLOSEABLES[i]))
1486
							return TypeIds.BitWrapperCloseable;
1487
					}
1488
					l = TypeConstants.JAVA_IO_RESOURCE_FREE_CLOSEABLES.length;
1489
					for (int i = 0; i < l; i++) {
1490
						if (CharOperation.equals(simpleName, TypeConstants.JAVA_IO_RESOURCE_FREE_CLOSEABLES[i]))
1491
							return TypeIds.BitResourceFreeCloseable;
1492
					}
1493
				}
1494
			}
1495
			break;
1496
	}
1497
	return 0;
1498
}
1472
}
1499
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java (-1 / +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 154-159 Link Here
154
	};
154
	};
155
	char[][] JAVA_LANG_AUTOCLOSEABLE =  {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$
155
	char[][] JAVA_LANG_AUTOCLOSEABLE =  {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$
156
	char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$
156
	char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$
157
	// white lists of closeables:
158
	char[][] JAVA_IO_WRAPPER_CLOSEABLES = new char[][] {
159
		"BufferedInputStream".toCharArray(), //$NON-NLS-1$
160
		"BufferedOutputStream".toCharArray(), //$NON-NLS-1$
161
		"BufferedReader".toCharArray(), //$NON-NLS-1$
162
		"BufferedWriter".toCharArray(), //$NON-NLS-1$
163
		"InputStreamReader".toCharArray(), //$NON-NLS-1$
164
		"PrintWriter".toCharArray(),  //$NON-NLS-1$
165
	};
166
	char[][] JAVA_IO_RESOURCE_FREE_CLOSEABLES = new char[][] {			
167
		"StringReader".toCharArray(), //$NON-NLS-1$
168
		"StringWriter".toCharArray(), //$NON-NLS-1$
169
		"ByteArrayInputStream".toCharArray(), //$NON-NLS-1$
170
		"ByteArrayOutputStream".toCharArray(), //$NON-NLS-1$
171
		"CharArrayReader".toCharArray(), //$NON-NLS-1$
172
		"CharArrayWriter".toCharArray(), //$NON-NLS-1$
173
	};
157
174
158
	// Constraints for generic type argument inference
175
	// Constraints for generic type argument inference
159
	int CONSTRAINT_EQUAL = 0;		// Actual = Formal
176
	int CONSTRAINT_EQUAL = 0;		// Actual = Formal
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java (-1 / +16 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 207-210 Link Here
207
	 * @see ReferenceBinding#hasTypeBit(int)
207
	 * @see ReferenceBinding#hasTypeBit(int)
208
	 */
208
	 */
209
	final int BitCloseable = 2;
209
	final int BitCloseable = 2;
210
	/**
211
	 * Bit for members of a white list:
212
	 * Subtypes of Closeable that wrap another resource without directly holding any OS resources. 
213
	 */
214
	final int BitWrapperCloseable = 4;
215
	/**
216
	 * Bit for members of a white list:
217
	 * Subtypes of Closeable that do not hold an OS resource that needs to be released.
218
	 */
219
	final int BitResourceFreeCloseable = 8;
220
	
221
	/**
222
	 * Set of type bits that should be inherited by any sub types.
223
	 */
224
	final int InheritableBits = BitAutoCloseable | BitCloseable;
210
}
225
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java (-3 / +3 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 316-326 Link Here
316
			// initialize from bounds
316
			// initialize from bounds
317
			this.typeBits = 0;
317
			this.typeBits = 0;
318
			if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
318
			if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
319
				this.typeBits |= this.superclass.typeBits;
319
				this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
320
			if (this.superInterfaces != null)
320
			if (this.superInterfaces != null)
321
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
321
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
322
					if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
322
					if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
323
						this.typeBits |= this.superInterfaces[i].typeBits;
323
						this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits);
324
		}
324
		}
325
		return (this.typeBits & bit) != 0;
325
		return (this.typeBits & bit) != 0;
326
	}
326
	}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java (-3 / +3 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 429-439 Link Here
429
			// initialize from upper bounds
429
			// initialize from upper bounds
430
			this.typeBits = 0;
430
			this.typeBits = 0;
431
			if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
431
			if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
432
				this.typeBits |= this.superclass.typeBits;
432
				this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
433
			if (this.superInterfaces != null)
433
			if (this.superInterfaces != null)
434
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
434
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
435
					if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
435
					if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
436
						this.typeBits |= this.superInterfaces[i].typeBits;
436
						this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits);
437
		}
437
		}
438
		return (this.typeBits & bit) != 0;
438
		return (this.typeBits & bit) != 0;
439
	}
439
	}

Return to bug 358903