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

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/core/compiler/IProblem.java (+9 lines)
Lines 1392-1397 Link Here
1392
	int SwitchOnStringsNotBelow17 = TypeRelated + 881;	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=348492
1392
	int SwitchOnStringsNotBelow17 = TypeRelated + 881;	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=348492
1393
	/** @since 3.7 */
1393
	/** @since 3.7 */
1394
	int UnhandledExceptionOnAutoClose =  TypeRelated + 882;
1394
	int UnhandledExceptionOnAutoClose =  TypeRelated + 882;
1395
	/** @since 3.7 */
1396
	int PotentiallyUnclosedCloseable = Internal + 883;
1397
	/** @since 3.7 */
1398
	int PotentiallyUnclosedCloseableAtExit = Internal + 884;
1399
	/** @since 3.7 */
1400
	int UnclosedCloseable = Internal + 885;
1401
	/** @since 3.7 */
1402
	int UnclosedCloseableAtExit = Internal + 886;
1403
1395
	/**
1404
	/**
1396
	 * External problems -- These are problems defined by other plugins
1405
	 * External problems -- These are problems defined by other plugins
1397
	 */
1406
	 */
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java (+69 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2011 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
 *     GK Software AG - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
12
13
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
14
import org.eclipse.jdt.internal.compiler.impl.Constant;
15
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
16
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
17
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
18
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
20
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
21
22
/**
23
 * A faked local variable declaration used for keeping track of data flows of a
24
 * special variable. Certain events will be recorded by changing the null info
25
 * for this variable.
26
 * 
27
 * @author Stephan Herrmann
28
 */
29
public class FakedTrackingVariable extends LocalDeclaration {
30
31
	public FakedTrackingVariable(BlockScope currentScope, LocalDeclaration localDeclaration) {
32
		super(localDeclaration.name, localDeclaration.sourceStart, localDeclaration.sourceEnd);
33
		this.type = new SingleTypeReference(
34
				TypeConstants.OBJECT,
35
				((long)this.sourceStart <<32)+this.sourceEnd);
36
		currentScope.addTrackingVariable(this);
37
		resolve(currentScope);
38
	}
39
40
	public void generateCode(BlockScope currentScope, CodeStream codeStream)
41
	{ /* NOP - this variable is completely dummy, ie. for analysis only. */ }
42
43
	public void resolve (BlockScope scope) {
44
		// only need the binding, which is used as reference in FlowInfo methods.
45
		this.binding = new LocalVariableBinding(
46
				this.name,
47
				scope.getJavaLangObject(),  // dummy, just needs to be a reference type
48
				0,
49
				false);
50
		this.binding.setConstant(Constant.NotAConstant);
51
		this.binding.useFlag = LocalVariableBinding.USED;
52
		// use a free slot without assigning it:
53
		this.binding.id = scope.outerMostMethodScope().analysisIndex+1; // FIXME(SH): avoid conflicting index for several tracking vars within 1 method
54
	}
55
56
	public static boolean isAutoCloseable(TypeBinding typeBinding) {
57
		return typeBinding instanceof ReferenceBinding
58
			&& (((ReferenceBinding)typeBinding).typeBits & TypeIds.BitAutoCloseable) != 0;
59
	}
60
	
61
	public static FakedTrackingVariable getTrackingVariable(Expression expression) {
62
		if (expression instanceof SingleNameReference) {
63
			SingleNameReference returnName = (SingleNameReference) expression;
64
			if (returnName.binding instanceof LocalVariableBinding)
65
				return ((LocalVariableBinding)returnName.binding).closeTracker;
66
		}
67
		return null;
68
	}
69
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java (+4 lines)
Lines 71-76 Link Here
71
	if ((this.initialization.implicitConversion & TypeIds.UNBOXING) != 0) {
71
	if ((this.initialization.implicitConversion & TypeIds.UNBOXING) != 0) {
72
		this.initialization.checkNPE(currentScope, flowContext, flowInfo);
72
		this.initialization.checkNPE(currentScope, flowContext, flowInfo);
73
	}
73
	}
74
	if (FakedTrackingVariable.isAutoCloseable(this.initialization.resolvedType)) {
75
		this.binding.closeTracker = new FakedTrackingVariable(currentScope, this);
76
		flowInfo.markAsDefinitelyNull(this.binding.closeTracker.binding);
77
	}
74
	
78
	
75
	flowInfo =
79
	flowInfo =
76
		this.initialization
80
		this.initialization
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (+5 lines)
Lines 42-47 Link Here
42
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
42
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
43
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
43
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
44
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
44
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
45
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
45
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
46
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
46
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
47
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
47
48
Lines 64-69 Link Here
64
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
65
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
65
	boolean nonStatic = !this.binding.isStatic();
66
	boolean nonStatic = !this.binding.isStatic();
66
	flowInfo = this.receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits();
67
	flowInfo = this.receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits();
68
	FakedTrackingVariable trackingVariable = FakedTrackingVariable.getTrackingVariable(this.receiver);
69
	if (   trackingVariable != null 
70
		&& CharOperation.equals(TypeConstants.CLOSE, this.selector))
71
		flowInfo.markAsDefinitelyNonNull(trackingVariable.binding);
67
	if (nonStatic) {
72
	if (nonStatic) {
68
		this.receiver.checkNPE(currentScope, flowContext, flowInfo);
73
		this.receiver.checkNPE(currentScope, flowContext, flowInfo);
69
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
74
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java (+1 lines)
Lines 134-139 Link Here
134
				}
134
				}
135
					
135
					
136
			}
136
			}
137
			this.scope.checkUnclosedCloseables(flowInfo, null);
137
		} catch (AbortMethod e) {
138
		} catch (AbortMethod e) {
138
			this.ignoreFurtherInvestigation = true;
139
			this.ignoreFurtherInvestigation = true;
139
		}
140
		}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java (+4 lines)
Lines 40-45 Link Here
40
		if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
40
		if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
41
			this.expression.checkNPE(currentScope, flowContext, flowInfo);
41
			this.expression.checkNPE(currentScope, flowContext, flowInfo);
42
		}
42
		}
43
		FakedTrackingVariable trackingVariable = FakedTrackingVariable.getTrackingVariable(this.expression);
44
		if (trackingVariable != null)
45
			flowInfo.markAsDefinitelyNonNull(trackingVariable.binding);
43
	}
46
	}
44
	this.initStateIndex =
47
	this.initStateIndex =
45
		currentScope.methodScope().recordInitializationStates(flowInfo);
48
		currentScope.methodScope().recordInitializationStates(flowInfo);
Lines 104-109 Link Here
104
			this.expression.bits |= ASTNode.IsReturnedValue;
107
			this.expression.bits |= ASTNode.IsReturnedValue;
105
		}
108
		}
106
	}
109
	}
110
	currentScope.checkUnclosedCloseables(flowInfo, this);
107
	return FlowInfo.DEAD_END;
111
	return FlowInfo.DEAD_END;
108
}
112
}
109
113
(-)compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java (-2 / +5 lines)
Lines 120-127 Link Here
120
120
121
		for (int i = 0, max = this.resources.length; i < max; i++) {
121
		for (int i = 0, max = this.resources.length; i < max; i++) {
122
			flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
122
			flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
123
			this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
123
			LocalVariableBinding resourceBinding = this.resources[i].binding;
124
			TypeBinding type = this.resources[i].binding.type;
124
			resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
125
			if (resourceBinding.closeTracker != null)
126
				flowInfo.markAsDefinitelyNonNull(resourceBinding.closeTracker.binding); 
127
			TypeBinding type = resourceBinding.type;
125
			if (type != null && type.isValidBinding()) {
128
			if (type != null && type.isValidBinding()) {
126
				ReferenceBinding binding = (ReferenceBinding) type;
129
				ReferenceBinding binding = (ReferenceBinding) type;
127
				MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter
130
				MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java (+4 lines)
Lines 1141-1146 Link Here
1141
	this.tagBits &= ~TagBits.HasUnresolvedSuperclass;
1141
	this.tagBits &= ~TagBits.HasUnresolvedSuperclass;
1142
	if (this.superclass.problemId() == ProblemReasons.NotFound)
1142
	if (this.superclass.problemId() == ProblemReasons.NotFound)
1143
		this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency
1143
		this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency
1144
	this.typeBits |= (this.superclass.id & TypeIds.BitAutoCloseable);
1144
	return this.superclass;
1145
	return this.superclass;
1145
}
1146
}
1146
// NOTE: superInterfaces of binary types are resolved when needed
1147
// NOTE: superInterfaces of binary types are resolved when needed
Lines 1152-1157 Link Here
1152
		this.superInterfaces[i] = (ReferenceBinding) resolveType(this.superInterfaces[i], this.environment, true /* raw conversion */);
1153
		this.superInterfaces[i] = (ReferenceBinding) resolveType(this.superInterfaces[i], this.environment, true /* raw conversion */);
1153
		if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound)
1154
		if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound)
1154
			this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency
1155
			this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency
1156
		if (   this.superInterfaces[i].id == TypeIds.T_JavaLangAutoCloseable
1157
			|| (this.superInterfaces[i].typeBits & TypeIds.BitAutoCloseable) != 0)
1158
			this.typeBits |= TypeIds.BitAutoCloseable;
1155
	}
1159
	}
1156
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
1160
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
1157
	return this.superInterfaces;
1161
	return this.superInterfaces;
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java (+24 lines)
Lines 10-19 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
11
package org.eclipse.jdt.internal.compiler.lookup;
12
12
13
import java.util.ArrayList;
14
import java.util.List;
15
13
import org.eclipse.jdt.core.compiler.CharOperation;
16
import org.eclipse.jdt.core.compiler.CharOperation;
14
import org.eclipse.jdt.internal.compiler.ast.*;
17
import org.eclipse.jdt.internal.compiler.ast.*;
15
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
18
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
16
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.FlowInfo;
17
import org.eclipse.jdt.internal.compiler.impl.Constant;
21
import org.eclipse.jdt.internal.compiler.impl.Constant;
18
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
22
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
19
23
Lines 957-960 Link Here
957
		}
961
		}
958
	}
962
	}
959
}
963
}
964
965
// TODO: List or array?
966
// TODO: move these to FlowInfo? (beware of flowInfo copying!)
967
private List trackingVariables;
968
public void addTrackingVariable(FakedTrackingVariable fakedTrackingVariable) {
969
	if (this.trackingVariables == null)
970
		this.trackingVariables = new ArrayList();
971
	this.trackingVariables.add(fakedTrackingVariable);
972
}
973
974
public void checkUnclosedCloseables(FlowInfo flowInfo, ASTNode location) {
975
	if (this.trackingVariables == null) return;
976
	for (int i=0; i<this.trackingVariables.size(); i++) {
977
		FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(0);
978
		if (flowInfo.isDefinitelyNull(trackingVar.binding))
979
			problemReporter().unclosedCloseable(trackingVar, location);
980
		else if (flowInfo.isPotentiallyNull(trackingVar.binding))
981
			problemReporter().potentiallyUnclosedCloseable(trackingVar, location);
982
	}	
983
}
960
}
984
}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java (+4 lines)
Lines 907-912 Link Here
907
			} else {
907
			} else {
908
				// only want to reach here when no errors are reported
908
				// only want to reach here when no errors are reported
909
				sourceType.superclass = superclass;
909
				sourceType.superclass = superclass;
910
				sourceType.typeBits |= (superclass.typeBits & TypeIds.BitAutoCloseable);
910
				return true;
911
				return true;
911
			}
912
			}
912
		}
913
		}
Lines 1017-1022 Link Here
1017
				noProblems &= superInterfaceRef.resolvedType.isValidBinding();
1018
				noProblems &= superInterfaceRef.resolvedType.isValidBinding();
1018
			}
1019
			}
1019
			// only want to reach here when no errors are reported
1020
			// only want to reach here when no errors are reported
1021
			if (   superInterface.id == TypeIds.T_JavaLangAutoCloseable
1022
				|| (superInterface.typeBits & TypeIds.BitAutoCloseable) != 0)
1023
				superInterface.typeBits |= TypeIds.BitAutoCloseable;
1020
			interfaceBindings[count++] = superInterface;
1024
			interfaceBindings[count++] = superInterface;
1021
		}
1025
		}
1022
		// hold onto all correctly resolved superinterfaces
1026
		// hold onto all correctly resolved superinterfaces
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java (+3 lines)
Lines 19-24 Link Here
19
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
19
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
20
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
20
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
21
import org.eclipse.jdt.internal.compiler.ast.Annotation;
21
import org.eclipse.jdt.internal.compiler.ast.Annotation;
22
import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable;
22
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
23
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
23
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
24
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
24
import org.eclipse.jdt.internal.compiler.impl.Constant;
25
import org.eclipse.jdt.internal.compiler.impl.Constant;
Lines 39-44 Link Here
39
	public int[] initializationPCs;
40
	public int[] initializationPCs;
40
	public int initializationCount = 0;
41
	public int initializationCount = 0;
41
42
43
	public FakedTrackingVariable closeTracker;
44
42
	// for synthetic local variables
45
	// for synthetic local variables
43
	// if declaration slot is not positionned, the variable will not be listed in attribute
46
	// if declaration slot is not positionned, the variable will not be listed in attribute
44
	// note that the name of a variable should be chosen so as not to conflict with user ones (usually starting with a space char is all needed)
47
	// note that the name of a variable should be chosen so as not to conflict with user ones (usually starting with a space char is all needed)
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java (+2 lines)
Lines 45-50 Link Here
45
45
46
	private SimpleLookupTable compatibleCache;
46
	private SimpleLookupTable compatibleCache;
47
47
48
	public int typeBits;
49
48
	public static final ReferenceBinding LUB_GENERIC = new ReferenceBinding() { /* used for lub computation */};
50
	public static final ReferenceBinding LUB_GENERIC = new ReferenceBinding() { /* used for lub computation */};
49
51
50
	private static final Comparator FIELD_COMPARATOR = new Comparator() {
52
	private static final Comparator FIELD_COMPARATOR = new Comparator() {
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java (+1 lines)
Lines 148-153 Link Here
148
			"PolymorphicSignature".toCharArray() //$NON-NLS-1$
148
			"PolymorphicSignature".toCharArray() //$NON-NLS-1$
149
	};
149
	};
150
	char[][] JAVA_LANG_AUTOCLOSEABLE =  {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$
150
	char[][] JAVA_LANG_AUTOCLOSEABLE =  {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$
151
	char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$
151
152
152
	// Constraints for generic type argument inference
153
	// Constraints for generic type argument inference
153
	int CONSTRAINT_EQUAL = 0;		// Actual = Formal
154
	int CONSTRAINT_EQUAL = 0;		// Actual = Formal
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java (+2 lines)
Lines 173-176 Link Here
173
	final int Object2Object = T_JavaLangObject + (T_JavaLangObject << 4);
173
	final int Object2Object = T_JavaLangObject + (T_JavaLangObject << 4);
174
	final int BOXING = 0x200;
174
	final int BOXING = 0x200;
175
	final int UNBOXING = 0x400;
175
	final int UNBOXING = 0x400;
176
177
	final int BitAutoCloseable = 1;
176
}
178
}
(-)compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java (+37 lines)
Lines 55-60 Link Here
55
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
55
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
56
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
56
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
57
import org.eclipse.jdt.internal.compiler.ast.Expression;
57
import org.eclipse.jdt.internal.compiler.ast.Expression;
58
import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable;
58
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
59
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
59
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
60
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
60
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
61
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
Lines 7863-7866 Link Here
7863
			type.sourceStart, 
7864
			type.sourceStart, 
7864
			type.sourceEnd);
7865
			type.sourceEnd);
7865
}
7866
}
7867
public void potentiallyUnclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) {
7868
	if (location == null) {
7869
		this.handle(
7870
			IProblem.PotentiallyUnclosedCloseable,
7871
			NoArgument,
7872
			NoArgument,
7873
			trackVar.sourceStart,
7874
			trackVar.sourceEnd);
7875
	} else {
7876
		String[] args = { String.valueOf(trackVar.name) };
7877
		this.handle(
7878
			IProblem.PotentiallyUnclosedCloseableAtExit,
7879
			args,
7880
			args,
7881
			location.sourceStart,
7882
			location.sourceEnd);
7883
	}
7884
}
7885
public void unclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) {
7886
	if (location == null) {
7887
		this.handle(
7888
			IProblem.UnclosedCloseable,
7889
			NoArgument,
7890
			NoArgument,
7891
			trackVar.sourceStart,
7892
			trackVar.sourceEnd);
7893
	} else {
7894
		String[] args = { String.valueOf(trackVar.name) };
7895
		this.handle(
7896
			IProblem.UnclosedCloseableAtExit,
7897
			args,
7898
			args,
7899
			location.sourceStart,
7900
			location.sourceEnd);
7901
	}
7902
}
7866
}
7903
}
(-)compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties (+4 lines)
Lines 645-650 Link Here
645
880 = '<>' cannot be used with anonymous classes
645
880 = '<>' cannot be used with anonymous classes
646
881 = Cannot switch on a value of type String for source level below 1.7. Only convertible int values or enum constants are permitted
646
881 = Cannot switch on a value of type String for source level below 1.7. Only convertible int values or enum constants are permitted
647
882 = Unhandled exception type {0} thrown by automatic close() invocation on {1}
647
882 = Unhandled exception type {0} thrown by automatic close() invocation on {1}
648
883 = Value of type AutoCloseable is not closed on all paths.
649
884 = Instance '{0}' of type AutoCloseable may be unclosed at this point.
650
885 = Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.
651
886 = Instance '{0}' of type AutoCloseable is not closed at this point.
648
652
649
### ELABORATIONS
653
### ELABORATIONS
650
## Access restrictions
654
## Access restrictions
(-)src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java (-1 / +179 lines)
Lines 22-28 Link Here
22
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
22
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
23
23
24
static {
24
static {
25
//	TESTS_NAMES = new String[] { "test053" };
25
	TESTS_NAMES = new String[] { "test055" };
26
//	TESTS_NUMBERS = new int[] { 50 };
26
//	TESTS_NUMBERS = new int[] { 50 };
27
//	TESTS_RANGE = new int[] { 11, -1 };
27
//	TESTS_RANGE = new int[] { 11, -1 };
28
}
28
}
Lines 3341-3346 Link Here
3341
		"Object.Integer cannot be resolved to a type\n" + 
3341
		"Object.Integer cannot be resolved to a type\n" + 
3342
		"----------\n");
3342
		"----------\n");
3343
}
3343
}
3344
// Bug 349326 - [1.7] new warning for missing try-with-resources
3345
// a method uses an AutoCloseable without ever closing it.
3346
public void test055() {
3347
	Map options = getCompilerOptions();
3348
// FIXME(SH): make configurable
3349
//	options.put(CompilerOptions.OPTION_ReportUnclosedAutocloseable, CompilerOptions.ERROR);
3350
	this.runNegativeTest(
3351
		new String[] {
3352
			"X.java",
3353
			"import java.io.File;\n" +
3354
			"import java.io.FileReader;\n" +
3355
			"import java.io.IOException;\n" +
3356
			"public class X {\n" +
3357
			"    void foo() throws IOException {\n" +
3358
			"        File file = new File(\"somefile\");\n" +
3359
			"        FileReader fileReader = new FileReader(file);\n" +
3360
			"        char[] in = new char[50];\n" +
3361
			"        fileReader.read(in);\n" +
3362
			"    }\n" +
3363
			"    public static void main(String[] args) throws IOException {\n" +
3364
			"        new X().foo();\n" +
3365
			"    }\n" +
3366
			"}\n"
3367
		},
3368
		"----------\n" + 
3369
		"1. ERROR in X.java (at line 7)\n" + 
3370
		"	FileReader fileReader = new FileReader(file);\n" + 
3371
		"	           ^^^^^^^^^^\n" + 
3372
		"Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.\n" + 
3373
		"----------\n",
3374
		null,
3375
		true,
3376
		options);
3377
}
3378
// Bug 349326 - [1.7] new warning for missing try-with-resources
3379
// a method uses an AutoCloseable and closes it properly.
3380
public void test055a() {
3381
	Map options = getCompilerOptions();
3382
//	options.put(CompilerOptions.OPTION_ReportUnclosedAutocloseable, CompilerOptions.ERROR);
3383
	this.runConformTest(
3384
		new String[] {
3385
			"X.java",
3386
			"import java.io.File;\n" +
3387
			"import java.io.FileReader;\n" +
3388
			"import java.io.IOException;\n" +
3389
			"public class X {\n" +
3390
			"    void foo() throws IOException {\n" +
3391
			"        File file = new File(\"somefile\");\n" +
3392
			"        FileReader fileReader = new FileReader(file);\n" +
3393
			"        char[] in = new char[50];\n" +
3394
			"        fileReader.read(in);\n" +
3395
			"		 fileReader.close();\n" +
3396
			"    }\n" +
3397
			"    public static void main(String[] args) {\n" +
3398
			"        try {\n" +
3399
			"            new X().foo();\n" +
3400
			"        } catch (IOException ioex) {\n" +
3401
			"            System.out.println(\"caught\");\n" +
3402
			"        }\n" +
3403
			"    }\n" +
3404
			"}\n"
3405
		},
3406
		"caught", /*output*/
3407
		null/*classLibs*/,
3408
		true/*shouldFlush*/,
3409
		null/*vmargs*/,
3410
		options,
3411
		null/*requestor*/);
3412
}
3413
// Bug 349326 - [1.7] new warning for missing try-with-resources
3414
// a method uses an AutoCloseable properly within try-with-resources.
3415
public void test055b() {
3416
	Map options = getCompilerOptions();
3417
//	options.put(CompilerOptions.OPTION_ReportUnclosedAutocloseable, CompilerOptions.ERROR);
3418
	this.runConformTest(
3419
		new String[] {
3420
			"X.java",
3421
			"import java.io.File;\n" +
3422
			"import java.io.FileReader;\n" +
3423
			"import java.io.IOException;\n" +
3424
			"public class X {\n" +
3425
			"    void foo() throws IOException {\n" +
3426
			"        File file = new File(\"somefile\");\n" +
3427
			"        try (FileReader fileReader = new FileReader(file)) {\n" +
3428
			"            char[] in = new char[50];\n" +
3429
			"            fileReader.read(in);\n" +
3430
			"		 }\n" +
3431
			"    }\n" +
3432
			"    public static void main(String[] args) {\n" +
3433
			"        try {\n" +
3434
			"            new X().foo();\n" +
3435
			"        } catch (IOException ioex) {\n" +
3436
			"            System.out.println(\"caught\");\n" +
3437
			"        }\n" +
3438
			"    }\n" +
3439
			"}\n"
3440
		},
3441
		"caught", /*output*/
3442
		null/*classLibs*/,
3443
		true/*shouldFlush*/,
3444
		null/*vmargs*/,
3445
		options,
3446
		null/*requestor*/);
3447
}
3448
// Bug 349326 - [1.7] new warning for missing try-with-resources
3449
// a method uses an AutoCloseable but may return without closing it.
3450
public void test055c() {
3451
	Map options = getCompilerOptions();
3452
//	options.put(CompilerOptions.OPTION_ReportUnclosedAutocloseable, CompilerOptions.ERROR);
3453
	this.runNegativeTest(
3454
		new String[] {
3455
			"X.java",
3456
			"import java.io.File;\n" +
3457
			"import java.io.FileReader;\n" +
3458
			"import java.io.IOException;\n" +
3459
			"public class X {\n" +
3460
			"    void foo(boolean flag) throws IOException {\n" +
3461
			"        File file = new File(\"somefile\");\n" +
3462
			"        FileReader fileReader = new FileReader(file);\n" +
3463
			"        char[] in = new char[50];\n" +
3464
			"        fileReader.read(in);\n" +
3465
			"        if (flag)\n" +
3466
			"            return;\n" +
3467
			"        fileReader.close();\n" +
3468
			"    }\n" +
3469
			"    public static void main(String[] args) throws IOException {\n" +
3470
			"        new X().foo(false);\n" +
3471
			"    }\n" +
3472
			"}\n"
3473
		},
3474
		"----------\n" + 
3475
		"1. ERROR in X.java (at line 11)\n" + 
3476
		"	return;\n" + 
3477
		"	^^^^^^^\n" + 
3478
		"Instance \'fileReader\' of type AutoCloseable is not closed at this point.\n" + 
3479
		"----------\n",
3480
		null,
3481
		true,
3482
		options);
3483
}
3484
// Bug 349326 - [1.7] new warning for missing try-with-resources
3485
// one method returns an AutoCleasble, a second method uses this object without ever closing it.
3486
public void test055d() {
3487
	Map options = getCompilerOptions();
3488
//FIXME(SH): make configurable
3489
//	options.put(CompilerOptions.OPTION_ReportUnclosedAutocloseable, CompilerOptions.ERROR);
3490
	this.runNegativeTest(
3491
		new String[] {
3492
			"X.java",
3493
			"import java.io.File;\n" +
3494
			"import java.io.FileReader;\n" +
3495
			"import java.io.IOException;\n" +
3496
			"public class X {\n" +
3497
			"    FileReader getReader(String filename) throws IOException {\n" +
3498
			"        File file = new File(\"somefile\");\n" +
3499
			"        FileReader fileReader = new FileReader(file);\n" +
3500
			"        return fileReader;\n" + 		// don't complain here, pass responsibility to caller
3501
			"    }\n" +
3502
			"    void foo() throws IOException {\n" +
3503
			"        FileReader reader = getReader(\"somefile\");\n" +
3504
			"        char[] in = new char[50];\n" +
3505
			"        reader.read(in);\n" +
3506
			"    }\n" +
3507
			"    public static void main(String[] args) throws IOException {\n" +
3508
			"        new X().foo();\n" +
3509
			"    }\n" +
3510
			"}\n"
3511
		},
3512
		"----------\n" + 
3513
		"1. ERROR in X.java (at line 11)\n" + 
3514
		"	FileReader reader = getReader(\"somefile\");\n" + 
3515
		"	           ^^^^^^\n" + 
3516
		"Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.\n" + 
3517
		"----------\n",
3518
		null,
3519
		true,
3520
		options);
3521
}
3344
public static Class testClass() {
3522
public static Class testClass() {
3345
	return TryWithResourcesStatementTest.class;
3523
	return TryWithResourcesStatementTest.class;
3346
}
3524
}

Return to bug 349326