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 (+11 lines)
Lines 1394-1399 Link Here
1394
	int UnhandledExceptionOnAutoClose =  TypeRelated + 882;
1394
	int UnhandledExceptionOnAutoClose =  TypeRelated + 882;
1395
	/** @since 3.7 */
1395
	/** @since 3.7 */
1396
	int DiamondNotBelow17 =  TypeRelated + 883;
1396
	int DiamondNotBelow17 =  TypeRelated + 883;
1397
	/** @since 3.7 */
1398
	int PotentiallyUnclosedCloseable = Internal + 884;
1399
	/** @since 3.7 */
1400
	int PotentiallyUnclosedCloseableAtExit = Internal + 885;
1401
	/** @since 3.7 */
1402
	int UnclosedCloseable = Internal + 886;
1403
	/** @since 3.7 */
1404
	int UnclosedCloseableAtExit = Internal + 887;
1405
	/** @since 3.7 */
1406
	int ExplicitlyClosedAutoCloseable = Internal + 888;
1407
1397
	/**
1408
	/**
1398
	 * External problems -- These are problems defined by other plugins
1409
	 * External problems -- These are problems defined by other plugins
1399
	 */
1410
	 */
(-)compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java (+7 lines)
Lines 43-48 Link Here
43
	// process arguments
43
	// process arguments
44
	if (this.arguments != null) {
44
	if (this.arguments != null) {
45
		for (int i = 0, count = this.arguments.length; i < count; i++) {
45
		for (int i = 0, count = this.arguments.length; i < count; i++) {
46
			FakedTrackingVariable trackVar = FakedTrackingVariable.getCloseTrackingVariable(this.arguments[i]);
47
			if (trackVar != null) {
48
				// insert info that the tracked resource *may* be closed (by the target method, i.e.)
49
				FlowInfo infoResourceIsClosed = flowInfo.copy();
50
				infoResourceIsClosed.markAsDefinitelyNonNull(trackVar.binding);
51
				flowInfo = FlowInfo.conditional(flowInfo, infoResourceIsClosed);
52
			}
46
			flowInfo =
53
			flowInfo =
47
				this.arguments[i]
54
				this.arguments[i]
48
					.analyseCode(currentScope, flowContext, flowInfo)
55
					.analyseCode(currentScope, flowContext, flowInfo)
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java (+25 lines)
Lines 51-56 Link Here
51
	flowInfo = ((Reference) this.lhs)
51
	flowInfo = ((Reference) this.lhs)
52
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
52
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
53
		.unconditionalInits();
53
		.unconditionalInits();
54
	if (local != null) {
55
		LocalVariableBinding trackerBinding = null;
56
		if (local.closeTracker != null) {
57
			// Assigning to a variable already holding an AutoCloseable, has it been closed before?
58
			trackerBinding = local.closeTracker.binding;
59
			if (!flowInfo.isDefinitelyNull(local)) { // only if previous value may be non-null
60
				if (flowInfo.isDefinitelyNull(trackerBinding)) 
61
					currentScope.problemReporter().unclosedCloseable(local.closeTracker, this);
62
				else if (flowInfo.isPotentiallyNull(trackerBinding)) 
63
					currentScope.problemReporter().potentiallyUnclosedCloseable(local.closeTracker, this);
64
			}
65
		}
66
		if (FakedTrackingVariable.isAutoCloseable(this.expression.resolvedType)) {
67
			if (local.closeTracker != null && local.closeTracker.isInsideTryWithResources) { 
68
				// re-assigning resource of try-with-resources is a different error
69
			} else {
70
				// new value is AutoCloseable, start tracking, possibly re-using existing tracker var:
71
				if (trackerBinding == null) {
72
					local.closeTracker = new FakedTrackingVariable(local, this);
73
					trackerBinding = local.closeTracker.binding;
74
				}
75
				flowInfo.markAsDefinitelyNull(trackerBinding);
76
			}
77
		}
78
	}
54
	int nullStatus = this.expression.nullStatus(flowInfo);
79
	int nullStatus = this.expression.nullStatus(flowInfo);
55
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
80
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
56
		if (nullStatus == FlowInfo.NULL) {
81
		if (nullStatus == FlowInfo.NULL) {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Block.java (+2 lines)
Lines 36-41 Link Here
36
			flowInfo = stat.analyseCode(this.scope, flowContext, flowInfo);
36
			flowInfo = stat.analyseCode(this.scope, flowContext, flowInfo);
37
		}
37
		}
38
	}
38
	}
39
	if (this.explicitDeclarations > 0) // if block has its own scope analyze tracking vars now:
40
		this.scope.checkUnclosedCloseables(flowInfo, flowContext, null);
39
	return flowInfo;
41
	return flowInfo;
40
}
42
}
41
/**
43
/**
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java (+104 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.MethodScope;
18
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
20
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
21
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
22
23
/**
24
 * A faked local variable declaration used for keeping track of data flows of a
25
 * special variable. Certain events will be recorded by changing the null info
26
 * for this variable.
27
 * 
28
 * @author Stephan Herrmann
29
 */
30
public class FakedTrackingVariable extends LocalDeclaration {
31
32
	/** If resource is already managed by try-with-resources don't complain. */
33
	public boolean isInsideTryWithResources;
34
35
	/** 
36
	 * If close() is invoked from a nested method (inside a local type) 
37
	 * report remaining problems only as potential.
38
	 */
39
	public boolean closedInNestedMethod; 
40
41
	/** If a problem has already been reported don't complain again. */
42
	public boolean hasReportedProblem;
43
44
	MethodScope methodScope; // designates the method declaring this variable
45
	
46
	public LocalVariableBinding originalBinding; // the real local being tracked
47
48
	public FakedTrackingVariable(LocalVariableBinding original, Statement location) {
49
		super(original.name, location.sourceStart, location.sourceEnd);
50
		this.type = new SingleTypeReference(
51
				TypeConstants.OBJECT,
52
				((long)this.sourceStart <<32)+this.sourceEnd);
53
		this.methodScope = original.declaringScope.methodScope();
54
		this.originalBinding = original;
55
		resolve(original.declaringScope);
56
	}
57
	
58
	public void generateCode(BlockScope currentScope, CodeStream codeStream)
59
	{ /* NOP - this variable is completely dummy, ie. for analysis only. */ }
60
61
	public void resolve (BlockScope scope) {
62
		// only need the binding, which is used as reference in FlowInfo methods.
63
		this.binding = new LocalVariableBinding(
64
				this.name,
65
				scope.getJavaLangObject(),  // dummy, just needs to be a reference type
66
				0,
67
				false);
68
		this.binding.setConstant(Constant.NotAConstant);
69
		this.binding.useFlag = LocalVariableBinding.USED;
70
		// use a free slot without assigning it:
71
		this.binding.id = scope.registerTrackingVariable(this);
72
	}
73
74
	/**
75
	 * If expression resolves to a local variable binding of type AutoCloseable,
76
	 * answer the variable that tracks closing of that local, creating it if needed.
77
	 * @param expression
78
	 * @return a new {@link FakedTrackingVariable} or null.
79
	 */
80
	public static FakedTrackingVariable getCloseTrackingVariable(Expression expression) {
81
		if (expression instanceof SingleNameReference) {
82
			SingleNameReference name = (SingleNameReference) expression;
83
			if (name.binding instanceof LocalVariableBinding) {
84
				LocalVariableBinding local = (LocalVariableBinding)name.binding;
85
				if (local.closeTracker != null)
86
					return local.closeTracker;
87
				if (local.isParameter() || !isAutoCloseable(expression.resolvedType))
88
					return null;
89
				// tracking var doesn't yet exist. This happens in finally block
90
				// which is analyzed before the corresponding try block
91
				Statement location = local.declaration;
92
				return local.closeTracker
93
						= new FakedTrackingVariable(local, location);
94
			}
95
		}
96
		return null;
97
	}
98
99
	/** Answer wither the given type binding is a subtype of java.lang.AutoCloseable. */
100
	public static boolean isAutoCloseable(TypeBinding typeBinding) {
101
		return typeBinding instanceof ReferenceBinding
102
			&& ((ReferenceBinding)typeBinding).hasTypeBit(TypeIds.BitAutoCloseable);
103
	}
104
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java (-2 / +5 lines)
Lines 70-81 Link Here
70
	}
70
	}
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
	
75
	flowInfo =
74
	flowInfo =
76
		this.initialization
75
		this.initialization
77
			.analyseCode(currentScope, flowContext, flowInfo)
76
			.analyseCode(currentScope, flowContext, flowInfo)
78
			.unconditionalInits();
77
			.unconditionalInits();
78
	if (FakedTrackingVariable.isAutoCloseable(this.initialization.resolvedType)) {
79
		this.binding.closeTracker = new FakedTrackingVariable(this.binding, this);
80
		flowInfo.markAsDefinitelyNull(this.binding.closeTracker.binding);
81
	}
79
	int nullStatus = this.initialization.nullStatus(flowInfo);
82
	int nullStatus = this.initialization.nullStatus(flowInfo);
80
	if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes
83
	if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes
81
		this.bits |= FirstAssignmentToLocal;
84
		this.bits |= FirstAssignmentToLocal;
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (+22 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
	// recording the closing of AutoCloseable resources:
69
	if (CharOperation.equals(TypeConstants.CLOSE, this.selector)) 
70
	{
71
		FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.receiver);
72
		if (trackingVariable != null) { // null happens if receiver is not a local variable or not an AutoCloseable
73
			if (trackingVariable.methodScope == currentScope.methodScope()) {
74
				flowInfo.markAsDefinitelyNonNull(trackingVariable.binding);
75
				if (flowContext.initsOnFinally != null)
76
					flowContext.initsOnFinally.markAsDefinitelyNonNull(trackingVariable.binding);
77
			} else {
78
				trackingVariable.closedInNestedMethod = true;
79
			}
80
		}
81
	}
67
	if (nonStatic) {
82
	if (nonStatic) {
68
		this.receiver.checkNPE(currentScope, flowContext, flowInfo);
83
		this.receiver.checkNPE(currentScope, flowContext, flowInfo);
69
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
84
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
Lines 84-89 Link Here
84
			if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
99
			if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
85
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
100
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
86
			}
101
			}
102
			FakedTrackingVariable trackVar = FakedTrackingVariable.getCloseTrackingVariable(this.arguments[i]);
103
			if (trackVar != null) {
104
				// insert info that the tracked resource *may* be closed (by the target method, i.e.)
105
				FlowInfo infoResourceIsClosed = flowInfo.copy();
106
				infoResourceIsClosed.markAsDefinitelyNonNull(trackVar.binding);
107
				flowInfo = FlowInfo.conditional(flowInfo, infoResourceIsClosed);
108
			}
87
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
109
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
88
		}
110
		}
89
	}
111
	}
(-)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, methodContext, 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/QualifiedAllocationExpression.java (+7 lines)
Lines 76-81 Link Here
76
		// process arguments
76
		// process arguments
77
		if (this.arguments != null) {
77
		if (this.arguments != null) {
78
			for (int i = 0, count = this.arguments.length; i < count; i++) {
78
			for (int i = 0, count = this.arguments.length; i < count; i++) {
79
				FakedTrackingVariable trackVar = FakedTrackingVariable.getCloseTrackingVariable(this.arguments[i]);
80
				if (trackVar != null) {
81
					// insert info that the tracked resource *may* be closed (by the target method, i.e.)
82
					FlowInfo infoResourceIsClosed = flowInfo.copy();
83
					infoResourceIsClosed.markAsDefinitelyNonNull(trackVar.binding);
84
					flowInfo = FlowInfo.conditional(flowInfo, infoResourceIsClosed);
85
				}
79
				flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo);
86
				flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo);
80
				if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
87
				if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
81
					this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
88
					this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java (+8 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.getCloseTrackingVariable(this.expression);
44
		if (trackingVariable != null) {
45
			// don't report issues concerning this local, since by returning
46
			// the method passes the responsibility to the caller:
47
			flowInfo.markAsDefinitelyNonNull(trackingVariable.binding);
48
			trackingVariable.hasReportedProblem = true;
49
		}
43
	}
50
	}
44
	this.initStateIndex =
51
	this.initStateIndex =
45
		currentScope.methodScope().recordInitializationStates(flowInfo);
52
		currentScope.methodScope().recordInitializationStates(flowInfo);
Lines 104-109 Link Here
104
			this.expression.bits |= ASTNode.IsReturnedValue;
111
			this.expression.bits |= ASTNode.IsReturnedValue;
105
		}
112
		}
106
	}
113
	}
114
	currentScope.checkUnclosedCloseables(flowInfo, null/*ignore exception exits from flowContext*/, this);
107
	return FlowInfo.DEAD_END;
115
	return FlowInfo.DEAD_END;
108
}
116
}
109
117
(-)compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java (-4 / +25 lines)
Lines 15-20 Link Here
15
 *******************************************************************************/
15
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.ast;
16
package org.eclipse.jdt.internal.compiler.ast;
17
17
18
import java.util.ArrayList;
19
import java.util.List;
20
18
import org.eclipse.jdt.core.compiler.CharOperation;
21
import org.eclipse.jdt.core.compiler.CharOperation;
19
import org.eclipse.jdt.internal.compiler.ASTVisitor;
22
import org.eclipse.jdt.internal.compiler.ASTVisitor;
20
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
23
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
Lines 120-127 Link Here
120
123
121
		for (int i = 0, max = this.resources.length; i < max; i++) {
124
		for (int i = 0, max = this.resources.length; i < max; i++) {
122
			flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
125
			flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
123
			this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
126
			LocalVariableBinding resourceBinding = this.resources[i].binding;
124
			TypeBinding type = this.resources[i].binding.type;
127
			resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
128
			if (resourceBinding.closeTracker != null) {
129
				resourceBinding.closeTracker.isInsideTryWithResources = true;
130
				flowInfo.markAsDefinitelyNonNull(resourceBinding.closeTracker.binding);
131
			} 
132
			TypeBinding type = resourceBinding.type;
125
			if (type != null && type.isValidBinding()) {
133
			if (type != null && type.isValidBinding()) {
126
				ReferenceBinding binding = (ReferenceBinding) type;
134
				ReferenceBinding binding = (ReferenceBinding) type;
127
				MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter
135
				MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter
Lines 227-232 Link Here
227
			this.scope.problemReporter().finallyMustCompleteNormally(this.finallyBlock);
235
			this.scope.problemReporter().finallyMustCompleteNormally(this.finallyBlock);
228
		}
236
		}
229
		this.subRoutineInits = subInfo;
237
		this.subRoutineInits = subInfo;
238
230
		// process the try block in a context handling the local exceptions.
239
		// process the try block in a context handling the local exceptions.
231
		ExceptionHandlingFlowContext handlingContext =
240
		ExceptionHandlingFlowContext handlingContext =
232
			new ExceptionHandlingFlowContext(
241
			new ExceptionHandlingFlowContext(
Lines 245-252 Link Here
245
254
246
		for (int i = 0, max = this.resources.length; i < max; i++) {
255
		for (int i = 0, max = this.resources.length; i < max; i++) {
247
			flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
256
			flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
248
			this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
257
			LocalVariableBinding resourceBinding = this.resources[i].binding;
249
			TypeBinding type = this.resources[i].binding.type;
258
			resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
259
			if (resourceBinding.closeTracker != null) {
260
				resourceBinding.closeTracker.isInsideTryWithResources = true;
261
				flowInfo.markAsDefinitelyNonNull(resourceBinding.closeTracker.binding);
262
			} 
263
			TypeBinding type = resourceBinding.type;
250
			if (type != null && type.isValidBinding()) {
264
			if (type != null && type.isValidBinding()) {
251
				ReferenceBinding binding = (ReferenceBinding) type;
265
				ReferenceBinding binding = (ReferenceBinding) type;
252
				MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter
266
				MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter
Lines 267-272 Link Here
267
				this.bits |= ASTNode.IsTryBlockExiting;
281
				this.bits |= ASTNode.IsTryBlockExiting;
268
		}
282
		}
269
283
284
		// superimpose status for tracking variables:
285
		//   don't complain on initsOnException if finally has a better state.
286
		List moreTrackVars = new ArrayList();
287
		long trackVarsMask = currentScope.getTrackVars(moreTrackVars, subInfo);
288
		if (trackVarsMask != 0 || moreTrackVars.size() > 0)
289
			flowContext.replaceNullInfoForExceptionExits(trackVarsMask, moreTrackVars, subInfo);
290
270
		// check unreachable catch blocks
291
		// check unreachable catch blocks
271
		handlingContext.complainIfUnusedExceptionHandlers(this.scope, this);
292
		handlingContext.complainIfUnusedExceptionHandlers(this.scope, this);
272
293
(-)compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java (-3 / +46 lines)
Lines 15-32 Link Here
15
package org.eclipse.jdt.internal.compiler.flow;
15
package org.eclipse.jdt.internal.compiler.flow;
16
16
17
import java.util.ArrayList;
17
import java.util.ArrayList;
18
import java.util.List;
18
19
19
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
20
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
20
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
21
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
21
import org.eclipse.jdt.internal.compiler.ast.Argument;
22
import org.eclipse.jdt.internal.compiler.ast.Argument;
22
import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
23
import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable;
23
import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement;
24
import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement;
24
import org.eclipse.jdt.internal.compiler.ast.TryStatement;
25
import org.eclipse.jdt.internal.compiler.ast.TryStatement;
25
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
26
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
27
import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
26
import org.eclipse.jdt.internal.compiler.codegen.ObjectCache;
28
import org.eclipse.jdt.internal.compiler.codegen.ObjectCache;
27
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
29
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
28
import org.eclipse.jdt.internal.compiler.lookup.CatchParameterBinding;
30
import org.eclipse.jdt.internal.compiler.lookup.CatchParameterBinding;
29
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
31
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
32
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
30
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
33
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
31
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
34
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
32
import org.eclipse.jdt.internal.compiler.lookup.Scope;
35
import org.eclipse.jdt.internal.compiler.lookup.Scope;
Lines 184-190 Link Here
184
	return node;
187
	return node;
185
}
188
}
186
189
187
190
public int getNullStatusAfter(LocalVariableBinding local, FlowInfo flowInfo) {
191
	// collect info from normal flow and exceptional flows:
192
	int status = flowInfo.nullStatus(local);
193
	if (this.initsOnExceptions != null)
194
		for (int i = 0; i < this.initsOnExceptions.length; i++)
195
			status |= (this.initsOnExceptions[i].nullStatus(local) & (FlowInfo.NULL|FlowInfo.POTENTIALLY_NULL));
196
	// merge collected info:
197
	return mergeNullStatus(status);
198
}
188
199
189
public String individualToString() {
200
public String individualToString() {
190
	StringBuffer buffer = new StringBuffer("Exception flow context"); //$NON-NLS-1$
201
	StringBuffer buffer = new StringBuffer("Exception flow context"); //$NON-NLS-1$
Lines 302-305 Link Here
302
	}
313
	}
303
	return null;
314
	return null;
304
}
315
}
316
/**
317
 * {@inheritDoc}
318
 */
319
public void replaceNullInfoForExceptionExits(long mask, List moreTrackVars, FlowInfo otherInfo) {
320
	if (this.initsOnExceptions == null) return;
321
	// vars with low id:
322
	if (mask != 0)
323
		for (int i = 0; i < this.initsOnExceptions.length; i++)
324
			this.initsOnExceptions[i].replaceNullInfo(mask, otherInfo.unconditionalCopy());
325
	// vars with high id:
326
	for (int j = 0; j < this.initsOnExceptions.length; j++) {
327
		UnconditionalFlowInfo copy = null;
328
		for (int i = 0; i < moreTrackVars.size(); i++) {
329
			LocalVariableBinding trackVar = ((FakedTrackingVariable) moreTrackVars.get(i)).binding;
330
			int status = otherInfo.nullStatus(trackVar);
331
			if ((status & FlowInfo.NULL) == 0) {
332
				if ((status & FlowInfo.NON_NULL) != 0) {
333
					this.initsOnExceptions[j].markAsDefinitelyNonNull(trackVar);
334
				} else if ((status & FlowInfo.POTENTIALLY_NON_NULL) != 0) {
335
					if (this.initsOnExceptions[j].isDefinitelyNull(trackVar)) {
336
						// cannot directly set to pot.nn, need to construct and merge infos for this task:
337
						if (copy == null)
338
							copy = this.initsOnExceptions[j].unconditionalCopy();
339
						copy.markAsDefinitelyNonNull(trackVar);
340
					}
341
				}
342
			}
343
		}
344
		if (copy != null)
345
			this.initsOnExceptions[j] = this.initsOnExceptions[j].mergedWith(copy);
346
	}
347
}
305
}
348
}
(-)compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java (-1 / +58 lines)
Lines 15-23 Link Here
15
package org.eclipse.jdt.internal.compiler.flow;
15
package org.eclipse.jdt.internal.compiler.flow;
16
16
17
import java.util.ArrayList;
17
import java.util.ArrayList;
18
import java.util.List;
19
18
import org.eclipse.jdt.core.compiler.CharOperation;
20
import org.eclipse.jdt.core.compiler.CharOperation;
19
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
20
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
21
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
22
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
21
import org.eclipse.jdt.internal.compiler.ast.Expression;
23
import org.eclipse.jdt.internal.compiler.ast.Expression;
22
import org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
24
import org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
23
import org.eclipse.jdt.internal.compiler.ast.Reference;
25
import org.eclipse.jdt.internal.compiler.ast.Reference;
Lines 395-400 Link Here
395
	return null;
397
	return null;
396
}
398
}
397
399
400
/** 
401
 * Answer the combined null status that local will have after this flow context.
402
 * Subclasses will respect break and exception exits.
403
 */
404
public int getNullStatusAfter(LocalVariableBinding local, FlowInfo flowInfo) {
405
	return flowInfo.nullStatus(local);
406
}
407
398
/*
408
/*
399
 * lookup through break labels
409
 * lookup through break labels
400
 */
410
 */
Lines 736-739 Link Here
736
	buffer.append(individualToString()).append('\n');
746
	buffer.append(individualToString()).append('\n');
737
	return buffer.toString();
747
	return buffer.toString();
738
}
748
}
749
/** 
750
 * For all tracking variables as identified by the given mask plus the given list
751
 * replace the null info in initsOnException (if existent) with those given in finallyInfo.
752
 */
753
public void replaceNullInfoForExceptionExits(long trackVarsMask, List moreTrackVars, FlowInfo flowInfo) { 
754
	// nothing here, overridden in ExceptionHandlingFlowContext
755
}
756
757
/**
758
 * Get the null status that local will have after the current point as indicated by flowInfo and flowContext
759
 * @param local
760
 * @param flowInfo
761
 * @param flowContext may be null
762
 * @return a bitset from the constants FlowInfo.{NULL,POTENTIALLY_NULL,POTENTIALLY_NON_NULL,NON_NULL}.
763
 */
764
public static int getNullStatusAfter(LocalVariableBinding local, FlowInfo flowInfo, FlowContext flowContext) {
765
	int NULL_MASK = FlowInfo.NULL | FlowInfo.POTENTIALLY_NULL | FlowInfo.POTENTIALLY_NON_NULL;
766
	int status = 0;
767
	if (flowContext != null) {
768
		// if we have info for finally use that:
769
		NullInfoRegistry finallyInfo = flowContext.initsOnFinally;
770
		if (finallyInfo != null) {
771
			int finallyStatus = finallyInfo.nullStatus(local);
772
			if ((finallyStatus & NULL_MASK) != 0)
773
				return mergeNullStatus(finallyStatus);			
774
		}
775
		status = flowContext.getNullStatusAfter(local, flowInfo);
776
	} else {
777
		status = flowInfo.nullStatus(local);
778
	}
779
	return mergeNullStatus(status);
780
}
781
782
/** Merge the bits NULL, NON_NULL, POTENTIALLY_NULL, POTENTIALLY_NON_NULL to a one-bit answer. */
783
protected static int mergeNullStatus(int status) {
784
	if ((status & FlowInfo.NULL) != 0) {
785
		if ((status & (FlowInfo.NON_NULL | FlowInfo.POTENTIALLY_NON_NULL)) != 0)
786
			return FlowInfo.POTENTIALLY_NULL; 	// null + doubt = pot null
787
		return FlowInfo.NULL;
788
	} else if ((status & FlowInfo.NON_NULL) != 0) {
789
		if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
790
			return FlowInfo.POTENTIALLY_NULL;	// non-null + doubt = pot null
791
		return FlowInfo.NON_NULL;
792
	} else if ((status & FlowInfo.POTENTIALLY_NON_NULL) != 0)
793
		return FlowInfo.POTENTIALLY_NON_NULL;
794
	return status;
795
}
739
}
796
}
(-)compiler/org/eclipse/jdt/internal/compiler/flow/SwitchFlowContext.java (+10 lines)
Lines 12-17 Link Here
12
12
13
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
13
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
14
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
14
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
15
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
15
16
16
/**
17
/**
17
 * Reflects the context of code analysis, keeping track of enclosing
18
 * Reflects the context of code analysis, keeping track of enclosing
Lines 31-36 Link Here
31
	return this.breakLabel;
32
	return this.breakLabel;
32
}
33
}
33
34
35
public int getNullStatusAfter(LocalVariableBinding local, FlowInfo flowInfo) {
36
	// collect info from normal flow and breaks flows:
37
	int status = flowInfo.nullStatus(local);
38
	if (this.initsOnBreak != null)
39
		status |= this.initsOnBreak.nullStatus(local);
40
	// merge collected info:
41
	return mergeNullStatus(status);
42
}
43
34
public String individualToString() {
44
public String individualToString() {
35
	StringBuffer buffer = new StringBuffer("Switch flow context"); //$NON-NLS-1$
45
	StringBuffer buffer = new StringBuffer("Switch flow context"); //$NON-NLS-1$
36
	buffer.append("[initsOnBreak -").append(this.initsOnBreak.toString()).append(']'); //$NON-NLS-1$
46
	buffer.append("[initsOnBreak -").append(this.initsOnBreak.toString()).append(']'); //$NON-NLS-1$
(-)compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java (-7 / +17 lines)
Lines 770-776 Link Here
770
	}
770
	}
771
	int vectorIndex;
771
	int vectorIndex;
772
	if ((vectorIndex = (position / BitCacheSize) - 1)
772
	if ((vectorIndex = (position / BitCacheSize) - 1)
773
			>= this.extra[0].length) {
773
			>= this.extra[2].length) {
774
		return false; // if not enough room in vector, then not initialized
774
		return false; // if not enough room in vector, then not initialized
775
	}
775
	}
776
	return ((this.extra[2][vectorIndex] & this.extra[4][vectorIndex]
776
	return ((this.extra[2][vectorIndex] & this.extra[4][vectorIndex]
Lines 797-803 Link Here
797
	}
797
	}
798
	int vectorIndex;
798
	int vectorIndex;
799
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
799
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
800
			this.extra[0].length) {
800
			this.extra[2].length) {
801
		return false; // if not enough room in vector, then not initialized
801
		return false; // if not enough room in vector, then not initialized
802
	}
802
	}
803
	return ((this.extra[2][vectorIndex] & this.extra[3][vectorIndex]
803
	return ((this.extra[2][vectorIndex] & this.extra[3][vectorIndex]
Lines 822-828 Link Here
822
	}
822
	}
823
	int vectorIndex;
823
	int vectorIndex;
824
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
824
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
825
			this.extra[0].length) {
825
			this.extra[2].length) {
826
		return false; // if not enough room in vector, then not initialized
826
		return false; // if not enough room in vector, then not initialized
827
	}
827
	}
828
	return ((this.extra[2][vectorIndex] & this.extra[5][vectorIndex]
828
	return ((this.extra[2][vectorIndex] & this.extra[5][vectorIndex]
Lines 882-888 Link Here
882
	}
882
	}
883
	int vectorIndex;
883
	int vectorIndex;
884
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
884
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
885
			this.extra[0].length) {
885
			this.extra[2].length) {
886
		return false; // if not enough room in vector, then not initialized
886
		return false; // if not enough room in vector, then not initialized
887
	}
887
	}
888
	return ((this.extra[4][vectorIndex]
888
	return ((this.extra[4][vectorIndex]
Lines 908-914 Link Here
908
	}
908
	}
909
	int vectorIndex;
909
	int vectorIndex;
910
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
910
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
911
			this.extra[0].length) {
911
			this.extra[2].length) {
912
		return false; // if not enough room in vector, then not initialized
912
		return false; // if not enough room in vector, then not initialized
913
	}
913
	}
914
	return ((this.extra[3][vectorIndex]
914
	return ((this.extra[3][vectorIndex]
Lines 934-940 Link Here
934
	}
934
	}
935
	int vectorIndex;
935
	int vectorIndex;
936
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
936
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
937
			this.extra[0].length) {
937
			this.extra[2].length) {
938
		return false; // if not enough room in vector, then not initialized
938
		return false; // if not enough room in vector, then not initialized
939
	}
939
	}
940
	return (this.extra[5][vectorIndex]
940
	return (this.extra[5][vectorIndex]
Lines 1889-1895 Link Here
1889
	}
1889
	}
1890
	return count;
1890
	return count;
1891
}
1891
}
1892
1892
/** Replace the null info for all variables in mask by values from otherInfo. */
1893
public void replaceNullInfo(long mask, UnconditionalFlowInfo otherInfo) {
1894
	this.nullBit1 &= ~mask;
1895
	this.nullBit1 |= (otherInfo.nullBit1 & mask);
1896
	this.nullBit2 &= ~mask;
1897
	this.nullBit2 |= (otherInfo.nullBit2 & mask);
1898
	this.nullBit3 &= ~mask;
1899
	this.nullBit3 |= (otherInfo.nullBit3 & mask);
1900
	this.nullBit4 &= ~mask;
1901
	this.nullBit4 |= (otherInfo.nullBit4 & mask);
1902
}
1893
public UnconditionalFlowInfo nullInfoLessUnconditionalCopy() {
1903
public UnconditionalFlowInfo nullInfoLessUnconditionalCopy() {
1894
	if (this == DEAD_END) {
1904
	if (this == DEAD_END) {
1895
		return this;
1905
		return this;
(-)compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java (+21 lines)
Lines 136-141 Link Here
136
	public static final String OPTION_IncludeNullInfoFromAsserts = "org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts";  //$NON-NLS-1$
136
	public static final String OPTION_IncludeNullInfoFromAsserts = "org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts";  //$NON-NLS-1$
137
	public static final String OPTION_ReportMethodCanBeStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic";  //$NON-NLS-1$
137
	public static final String OPTION_ReportMethodCanBeStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic";  //$NON-NLS-1$
138
	public static final String OPTION_ReportMethodCanBePotentiallyStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic";  //$NON-NLS-1$
138
	public static final String OPTION_ReportMethodCanBePotentiallyStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic";  //$NON-NLS-1$
139
	public static final String OPTION_ReportUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.unclosedCloseable"; //$NON-NLS-1$
140
	public static final String OPTION_ReportPotentiallyUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable"; //$NON-NLS-1$
141
	public static final String OPTION_ReportExplicitlyClosedAutoCloseable = "org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$
139
	/**
142
	/**
140
	 * Possible values for configurable options
143
	 * Possible values for configurable options
141
	 */
144
	 */
Lines 238-243 Link Here
238
	public static final int UnusedObjectAllocation = IrritantSet.GROUP2 | ASTNode.Bit4;
241
	public static final int UnusedObjectAllocation = IrritantSet.GROUP2 | ASTNode.Bit4;
239
	public static final int MethodCanBeStatic = IrritantSet.GROUP2 | ASTNode.Bit5;
242
	public static final int MethodCanBeStatic = IrritantSet.GROUP2 | ASTNode.Bit5;
240
	public static final int MethodCanBePotentiallyStatic = IrritantSet.GROUP2 | ASTNode.Bit6;
243
	public static final int MethodCanBePotentiallyStatic = IrritantSet.GROUP2 | ASTNode.Bit6;
244
	public static final int UnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit7;
245
	public static final int PotentiallyUnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit8;
246
	public static final int ExplicitlyClosedAutoCloseable = IrritantSet.GROUP2 | ASTNode.Bit9;
241
247
242
	// Severity level for handlers
248
	// Severity level for handlers
243
	/** 
249
	/** 
Lines 547-552 Link Here
547
				return OPTION_ReportMethodCanBeStatic;
553
				return OPTION_ReportMethodCanBeStatic;
548
			case MethodCanBePotentiallyStatic :
554
			case MethodCanBePotentiallyStatic :
549
				return OPTION_ReportMethodCanBePotentiallyStatic;
555
				return OPTION_ReportMethodCanBePotentiallyStatic;
556
			case UnclosedCloseable :
557
				return OPTION_ReportUnclosedCloseable;
558
			case PotentiallyUnclosedCloseable :
559
				return OPTION_ReportPotentiallyUnclosedCloseable;
560
			case ExplicitlyClosedAutoCloseable :
561
				return OPTION_ReportExplicitlyClosedAutoCloseable;
550
		}
562
		}
551
		return null;
563
		return null;
552
	}
564
	}
Lines 709-714 Link Here
709
			OPTION_ReportUnusedTypeArgumentsForMethodInvocation,
721
			OPTION_ReportUnusedTypeArgumentsForMethodInvocation,
710
			OPTION_ReportUnusedWarningToken,
722
			OPTION_ReportUnusedWarningToken,
711
			OPTION_ReportVarargsArgumentNeedCast,
723
			OPTION_ReportVarargsArgumentNeedCast,
724
			OPTION_ReportUnclosedCloseable,
725
			OPTION_ReportPotentiallyUnclosedCloseable,
726
			OPTION_ReportExplicitlyClosedAutoCloseable,
712
		};
727
		};
713
		return result;
728
		return result;
714
	}
729
	}
Lines 973-978 Link Here
973
		optionsMap.put(OPTION_IncludeNullInfoFromAsserts, this.includeNullInfoFromAsserts ? ENABLED : DISABLED);
988
		optionsMap.put(OPTION_IncludeNullInfoFromAsserts, this.includeNullInfoFromAsserts ? ENABLED : DISABLED);
974
		optionsMap.put(OPTION_ReportMethodCanBeStatic, getSeverityString(MethodCanBeStatic));
989
		optionsMap.put(OPTION_ReportMethodCanBeStatic, getSeverityString(MethodCanBeStatic));
975
		optionsMap.put(OPTION_ReportMethodCanBePotentiallyStatic, getSeverityString(MethodCanBePotentiallyStatic));
990
		optionsMap.put(OPTION_ReportMethodCanBePotentiallyStatic, getSeverityString(MethodCanBePotentiallyStatic));
991
		optionsMap.put(OPTION_ReportUnclosedCloseable, getSeverityString(UnclosedCloseable));
992
		optionsMap.put(OPTION_ReportPotentiallyUnclosedCloseable, getSeverityString(PotentiallyUnclosedCloseable));
993
		optionsMap.put(OPTION_ReportExplicitlyClosedAutoCloseable, getSeverityString(ExplicitlyClosedAutoCloseable));
976
		return optionsMap;
994
		return optionsMap;
977
	}
995
	}
978
996
Lines 1402-1407 Link Here
1402
		if ((optionValue = optionsMap.get(OPTION_ReportUnusedObjectAllocation)) != null) updateSeverity(UnusedObjectAllocation, optionValue);
1420
		if ((optionValue = optionsMap.get(OPTION_ReportUnusedObjectAllocation)) != null) updateSeverity(UnusedObjectAllocation, optionValue);
1403
		if ((optionValue = optionsMap.get(OPTION_ReportMethodCanBeStatic)) != null) updateSeverity(MethodCanBeStatic, optionValue);
1421
		if ((optionValue = optionsMap.get(OPTION_ReportMethodCanBeStatic)) != null) updateSeverity(MethodCanBeStatic, optionValue);
1404
		if ((optionValue = optionsMap.get(OPTION_ReportMethodCanBePotentiallyStatic)) != null) updateSeverity(MethodCanBePotentiallyStatic, optionValue);
1422
		if ((optionValue = optionsMap.get(OPTION_ReportMethodCanBePotentiallyStatic)) != null) updateSeverity(MethodCanBePotentiallyStatic, optionValue);
1423
		if ((optionValue = optionsMap.get(OPTION_ReportUnclosedCloseable)) != null) updateSeverity(UnclosedCloseable, optionValue);
1424
		if ((optionValue = optionsMap.get(OPTION_ReportPotentiallyUnclosedCloseable)) != null) updateSeverity(PotentiallyUnclosedCloseable, optionValue);
1425
		if ((optionValue = optionsMap.get(OPTION_ReportExplicitlyClosedAutoCloseable)) != null) updateSeverity(ExplicitlyClosedAutoCloseable, optionValue);
1405
1426
1406
		// Javadoc options
1427
		// Javadoc options
1407
		if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) {
1428
		if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) {
(-)compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java (-1 / +2 lines)
Lines 99-105 Link Here
99
			// group-2 warnings enabled by default
99
			// group-2 warnings enabled by default
100
			.set(
100
			.set(
101
				CompilerOptions.DeadCode
101
				CompilerOptions.DeadCode
102
				|CompilerOptions.Tasks);
102
				|CompilerOptions.Tasks
103
				|CompilerOptions.UnclosedCloseable);
103
			
104
			
104
		ALL.setAll();
105
		ALL.setAll();
105
		HIDING
106
		HIDING
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java (-2 / +18 lines)
Lines 971-976 Link Here
971
	variable.resolve();
971
	variable.resolve();
972
	return variable;
972
	return variable;
973
}
973
}
974
public boolean hasTypeBit(int bit) {
975
	// ensure hierarchy is resolved
976
	superclass();
977
	superInterfaces();
978
	return (this.typeBits & bit) != 0;
979
}
974
private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper, char[][][] missingTypeNames) {
980
private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper, char[][][] missingTypeNames) {
975
	// ParameterSignature = Identifier ':' TypeSignature
981
	// ParameterSignature = Identifier ':' TypeSignature
976
	//   or Identifier ':' TypeSignature(optional) InterfaceBound(s)
982
	//   or Identifier ':' TypeSignature(optional) InterfaceBound(s)
Lines 1139-1146 Link Here
1139
	// finish resolving the type
1145
	// finish resolving the type
1140
	this.superclass = (ReferenceBinding) resolveType(this.superclass, this.environment, true /* raw conversion */);
1146
	this.superclass = (ReferenceBinding) resolveType(this.superclass, this.environment, true /* raw conversion */);
1141
	this.tagBits &= ~TagBits.HasUnresolvedSuperclass;
1147
	this.tagBits &= ~TagBits.HasUnresolvedSuperclass;
1142
	if (this.superclass.problemId() == ProblemReasons.NotFound)
1148
	if (this.superclass.problemId() == ProblemReasons.NotFound) {
1143
		this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency
1149
		this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency
1150
	} else {
1151
		this.superclass.superclass();
1152
		this.superclass.superInterfaces();
1153
	}
1154
	this.typeBits |= this.superclass.typeBits;
1144
	return this.superclass;
1155
	return this.superclass;
1145
}
1156
}
1146
// NOTE: superInterfaces of binary types are resolved when needed
1157
// NOTE: superInterfaces of binary types are resolved when needed
Lines 1150-1157 Link Here
1150
1161
1151
	for (int i = this.superInterfaces.length; --i >= 0;) {
1162
	for (int i = this.superInterfaces.length; --i >= 0;) {
1152
		this.superInterfaces[i] = (ReferenceBinding) resolveType(this.superInterfaces[i], this.environment, true /* raw conversion */);
1163
		this.superInterfaces[i] = (ReferenceBinding) resolveType(this.superInterfaces[i], this.environment, true /* raw conversion */);
1153
		if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound)
1164
		if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound) {
1154
			this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency
1165
			this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency
1166
		} else {
1167
			this.superInterfaces[i].superclass();
1168
			this.superInterfaces[i].superInterfaces();
1169
		}
1170
		this.typeBits |= this.superInterfaces[i].typeBits;
1155
	}
1171
	}
1156
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
1172
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
1157
	return this.superInterfaces;
1173
	return this.superInterfaces;
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java (+62 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.FlowContext;
21
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
17
import org.eclipse.jdt.internal.compiler.impl.Constant;
22
import org.eclipse.jdt.internal.compiler.impl.Constant;
18
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
23
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
19
24
Lines 957-960 Link Here
957
		}
962
		}
958
	}
963
	}
959
}
964
}
965
966
private List trackingVariables;
967
public int registerTrackingVariable(FakedTrackingVariable fakedTrackingVariable) {
968
	if (this.trackingVariables == null)
969
		this.trackingVariables = new ArrayList();
970
	this.trackingVariables.add(fakedTrackingVariable);
971
	MethodScope outerMethodScope = outerMostMethodScope();
972
	return outerMethodScope.analysisIndex + (++outerMethodScope.trackVarCount);
973
	
974
}
975
public void checkUnclosedCloseables(FlowInfo flowInfo, FlowContext flowContext, ASTNode location) {
976
	if (this.trackingVariables == null) return;
977
	for (int i=0; i<this.trackingVariables.size(); i++) {
978
		FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
979
		if (trackingVar.hasReportedProblem)
980
			continue;
981
		if (trackingVar.originalBinding != null && flowInfo.isDefinitelyNull(trackingVar.originalBinding))
982
			continue; // resource is null at this flow, don't complain
983
		int status = FlowContext.getNullStatusAfter(trackingVar.binding, flowInfo, flowContext);
984
		if (status == FlowInfo.NULL) {
985
			if (trackingVar.closedInNestedMethod)
986
				problemReporter().potentiallyUnclosedCloseable(trackingVar, location);
987
			else
988
				problemReporter().unclosedCloseable(trackingVar, location);
989
		} else if (status != FlowInfo.NON_NULL) {
990
			problemReporter().potentiallyUnclosedCloseable(trackingVar, location);
991
		} else { // status == FlowInfo.NON_NULL
992
			if (environment().globalOptions.complianceLevel >= ClassFileConstants.JDK1_7 
993
					&& !trackingVar.isInsideTryWithResources)
994
				problemReporter().explicitlyClosedAutoCloseable(trackingVar);
995
		}
996
	}
997
}
998
/**
999
 * Find all tracking variables in scope that have relevant null status.
1000
 * Answer a mask of ids for those vars with id < 64 and store those
1001
 * with a high id in the given list.
1002
 * @param moreTrackVars list for collecting tracking variables with high id
1003
 * @param flowInfo 
1004
 * @return a bitset of variable ids
1005
 */
1006
public long getTrackVars(List moreTrackVars, FlowInfo flowInfo) {
1007
	if (this.trackingVariables == null) return 0;
1008
	long mask = 0;
1009
	for (int i=0; i<this.trackingVariables.size(); i++) {
1010
		FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
1011
		if (flowInfo.nullStatus(trackingVar.binding) == FlowInfo.UNKNOWN)
1012
			continue;
1013
		if (trackingVar.binding.id < 64)
1014
			mask |= (1 << trackingVar.binding.id);
1015
		else
1016
			moreTrackVars.add(trackingVar);
1017
	}
1018
	if (this.parent instanceof BlockScope)
1019
		mask |= ((BlockScope) this.parent).getTrackVars(moreTrackVars, flowInfo);
1020
	return mask;
1021
}
960
}
1022
}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java (+2 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;
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
			sourceType.typeBits |= superInterface.typeBits;
1020
			interfaceBindings[count++] = superInterface;
1022
			interfaceBindings[count++] = superInterface;
1021
		}
1023
		}
1022
		// hold onto all correctly resolved superinterfaces
1024
		// 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; // track closing of instances of type AutoCloseable
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/MethodScope.java (+3 lines)
Lines 49-54 Link Here
49
	// inner-emulation
49
	// inner-emulation
50
	public SyntheticArgumentBinding[] extraSyntheticArguments;
50
	public SyntheticArgumentBinding[] extraSyntheticArguments;
51
51
52
	// count number of tracking variables, see FakedTrackingVariable
53
	int trackVarCount;
54
52
public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) {
55
public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) {
53
	super(METHOD_SCOPE, parent);
56
	super(METHOD_SCOPE, parent);
54
	this.locals = new LocalVariableBinding[5];
57
	this.locals = new LocalVariableBinding[5];
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java (+7 lines)
Lines 629-634 Link Here
629
	    return this.type.hasMemberTypes();
629
	    return this.type.hasMemberTypes();
630
	}
630
	}
631
631
632
	public boolean hasTypeBit(int bit) {
633
		TypeBinding erasure = erasure();
634
		if (erasure instanceof ReferenceBinding)
635
			return ((ReferenceBinding) erasure).hasTypeBit(bit);
636
		return false;
637
	}
638
632
	/**
639
	/**
633
	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#implementsMethod(MethodBinding)
640
	 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#implementsMethod(MethodBinding)
634
	 */
641
	 */
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java (+6 lines)
Lines 40-45 Link Here
40
	return this.closestMatch;
40
	return this.closestMatch;
41
}
41
}
42
42
43
public boolean hasTypeBit(int bit) {
44
	if (this.closestMatch != null)
45
		return this.closestMatch.hasTypeBit(bit);
46
	return false;
47
}
48
43
/* API
49
/* API
44
* Answer the problem id associated with the receiver.
50
* Answer the problem id associated with the receiver.
45
* NoError if the receiver is a valid binding.
51
* NoError if the receiver is a valid binding.
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java (-1 / +12 lines)
Lines 17-22 Link Here
17
import java.util.Arrays;
17
import java.util.Arrays;
18
import java.util.Comparator;
18
import java.util.Comparator;
19
19
20
import org.eclipse.core.runtime.Assert;
20
import org.eclipse.jdt.core.compiler.CharOperation;
21
import org.eclipse.jdt.core.compiler.CharOperation;
21
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
22
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
22
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
23
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
Lines 45-50 Link Here
45
46
46
	private SimpleLookupTable compatibleCache;
47
	private SimpleLookupTable compatibleCache;
47
48
49
	int typeBits;
50
48
	public static final ReferenceBinding LUB_GENERIC = new ReferenceBinding() { /* used for lub computation */};
51
	public static final ReferenceBinding LUB_GENERIC = new ReferenceBinding() { /* used for lub computation */};
49
52
50
	private static final Comparator FIELD_COMPARATOR = new Comparator() {
53
	private static final Comparator FIELD_COMPARATOR = new Comparator() {
Lines 428-435 Link Here
428
				case 'A' :
431
				case 'A' :
429
					switch(typeName.length) {
432
					switch(typeName.length) {
430
						case 13 :
433
						case 13 :
431
							if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_AUTOCLOSEABLE[2]))
434
							if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_AUTOCLOSEABLE[2])) {
432
								this.id = TypeIds.T_JavaLangAutoCloseable;
435
								this.id = TypeIds.T_JavaLangAutoCloseable;
436
								this.typeBits |= TypeIds.BitAutoCloseable; 
437
							}
433
							return;
438
							return;
434
						case 14:
439
						case 14:
435
							if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ASSERTIONERROR[2]))
440
							if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ASSERTIONERROR[2]))
Lines 928-933 Link Here
928
	return (this.modifiers & ExtraCompilerModifiers.AccRestrictedAccess) != 0;
933
	return (this.modifiers & ExtraCompilerModifiers.AccRestrictedAccess) != 0;
929
}
934
}
930
935
936
public boolean hasTypeBit(int bit) {
937
	// overridden in relevant subclasses
938
	Assert.isTrue(false, "Unsupported query for type "+getClass().getName()); //$NON-NLS-1$
939
	return false; // never reached
940
}
941
931
/** Answer true if the receiver implements anInterface or is identical to anInterface.
942
/** Answer true if the receiver implements anInterface or is identical to anInterface.
932
* If searchHierarchy is true, then also search the receiver's superclasses.
943
* If searchHierarchy is true, then also search the receiver's superclasses.
933
*
944
*
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java (+8 lines)
Lines 18-23 Link Here
18
import java.util.HashMap;
18
import java.util.HashMap;
19
import java.util.Iterator;
19
import java.util.Iterator;
20
20
21
import org.eclipse.core.runtime.Assert;
21
import org.eclipse.jdt.core.compiler.CharOperation;
22
import org.eclipse.jdt.core.compiler.CharOperation;
22
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
23
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
23
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
24
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
Lines 1066-1071 Link Here
1066
	return accessors[1];
1067
	return accessors[1];
1067
}
1068
}
1068
1069
1070
public boolean hasTypeBit(int bit) {
1071
	// source types initialize type bits during connectSuperclass/interfaces()
1072
	if (!isLocalType())
1073
		Assert.isTrue((this.tagBits & TagBits.EndHierarchyCheck) != 0, "Hierarchy should be connected"); //$NON-NLS-1$
1074
	return (this.typeBits & bit) != 0;
1075
}
1076
1069
/**
1077
/**
1070
 * @see org.eclipse.jdt.internal.compiler.lookup.Binding#initializeDeprecatedAnnotationTagBits()
1078
 * @see org.eclipse.jdt.internal.compiler.lookup.Binding#initializeDeprecatedAnnotationTagBits()
1071
 */
1079
 */
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java (+1 lines)
Lines 154-159 Link Here
154
			"MethodHandle$PolymorphicSignature".toCharArray() //$NON-NLS-1$
154
			"MethodHandle$PolymorphicSignature".toCharArray() //$NON-NLS-1$
155
	};
155
	};
156
	char[][] JAVA_LANG_AUTOCLOSEABLE =  {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$
156
	char[][] JAVA_LANG_AUTOCLOSEABLE =  {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$
157
	char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$
157
158
158
	// Constraints for generic type argument inference
159
	// Constraints for generic type argument inference
159
	int CONSTRAINT_EQUAL = 0;		// Actual = Formal
160
	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/lookup/TypeVariableBinding.java (+14 lines)
Lines 42-47 Link Here
42
		this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; // treat type var as public
42
		this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; // treat type var as public
43
		this.tagBits |= TagBits.HasTypeVariable;
43
		this.tagBits |= TagBits.HasTypeVariable;
44
		this.environment = environment;
44
		this.environment = environment;
45
		this.typeBits = -1;
45
	}
46
	}
46
47
47
	/**
48
	/**
Lines 307-312 Link Here
307
		return true;
308
		return true;
308
	}
309
	}
309
310
311
	public boolean hasTypeBit(int bit) {
312
		if (this.typeBits == -1) {
313
			// initialize from bounds
314
			this.typeBits = 0;
315
			if (this.superclass != null)
316
				this.typeBits |= this.superclass.typeBits;
317
			if (this.superInterfaces != null)
318
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
319
					this.typeBits |= this.superInterfaces[i].typeBits;
320
		}
321
		return (this.typeBits & bit) != 0;
322
	}
323
310
	/**
324
	/**
311
	 * Returns true if the type variable is directly bound to a given type
325
	 * Returns true if the type variable is directly bound to a given type
312
	 */
326
	 */
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java (+14 lines)
Lines 54-59 Link Here
54
		if (bound instanceof UnresolvedReferenceBinding)
54
		if (bound instanceof UnresolvedReferenceBinding)
55
			((UnresolvedReferenceBinding) bound).addWrapper(this, environment);
55
			((UnresolvedReferenceBinding) bound).addWrapper(this, environment);
56
		this.tagBits |=  TagBits.HasUnresolvedTypeVariables; // cleared in resolve()
56
		this.tagBits |=  TagBits.HasUnresolvedTypeVariables; // cleared in resolve()
57
		this.typeBits = -1;
57
	}
58
	}
58
59
59
	public int kind() {
60
	public int kind() {
Lines 420-425 Link Here
420
		return this.genericType.hashCode();
421
		return this.genericType.hashCode();
421
	}
422
	}
422
423
424
	public boolean hasTypeBit(int bit) {
425
		if (this.typeBits == -1) {
426
			// initialize from upper bounds
427
			this.typeBits = 0;
428
			if (this.superclass != null)
429
				this.typeBits |= this.superclass.typeBits;
430
			if (this.superInterfaces != null)
431
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
432
					this.typeBits |= this.superInterfaces[i].typeBits;
433
		}
434
		return (this.typeBits & bit) != 0;
435
	}
436
423
	void initialize(ReferenceBinding someGenericType, TypeBinding someBound, TypeBinding[] someOtherBounds) {
437
	void initialize(ReferenceBinding someGenericType, TypeBinding someBound, TypeBinding[] someOtherBounds) {
424
		this.genericType = someGenericType;
438
		this.genericType = someGenericType;
425
		this.bound = someBound;
439
		this.bound = someBound;
(-)compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java (+60 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 430-435 Link Here
430
			
431
			
431
		case IProblem.MethodCanBePotentiallyStatic:
432
		case IProblem.MethodCanBePotentiallyStatic:
432
			return CompilerOptions.MethodCanBePotentiallyStatic;
433
			return CompilerOptions.MethodCanBePotentiallyStatic;
434
			
435
		case IProblem.UnclosedCloseable:
436
		case IProblem.UnclosedCloseableAtExit:
437
			return CompilerOptions.UnclosedCloseable;
438
		case IProblem.PotentiallyUnclosedCloseable:
439
		case IProblem.PotentiallyUnclosedCloseableAtExit:
440
			return CompilerOptions.PotentiallyUnclosedCloseable;
441
		case IProblem.ExplicitlyClosedAutoCloseable:
442
			return CompilerOptions.ExplicitlyClosedAutoCloseable;
433
	}
443
	}
434
	return 0;
444
	return 0;
435
}
445
}
Lines 462-467 Link Here
462
			case CompilerOptions.ParameterAssignment :
472
			case CompilerOptions.ParameterAssignment :
463
			case CompilerOptions.MethodCanBeStatic :
473
			case CompilerOptions.MethodCanBeStatic :
464
			case CompilerOptions.MethodCanBePotentiallyStatic :
474
			case CompilerOptions.MethodCanBePotentiallyStatic :
475
			case CompilerOptions.ExplicitlyClosedAutoCloseable :
465
				return CategorizedProblem.CAT_CODE_STYLE;
476
				return CategorizedProblem.CAT_CODE_STYLE;
466
477
467
			case CompilerOptions.MaskedCatchBlock :
478
			case CompilerOptions.MaskedCatchBlock :
Lines 483-488 Link Here
483
			case CompilerOptions.ShouldImplementHashcode :
494
			case CompilerOptions.ShouldImplementHashcode :
484
			case CompilerOptions.DeadCode :
495
			case CompilerOptions.DeadCode :
485
			case CompilerOptions.UnusedObjectAllocation :
496
			case CompilerOptions.UnusedObjectAllocation :
497
			case CompilerOptions.UnclosedCloseable :
498
			case CompilerOptions.PotentiallyUnclosedCloseable :
486
				return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM;
499
				return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM;
487
			
500
			
488
			case CompilerOptions.OverriddenPackageDefaultMethod :
501
			case CompilerOptions.OverriddenPackageDefaultMethod :
Lines 7884-7887 Link Here
7884
			type.sourceStart, 
7897
			type.sourceStart, 
7885
			type.sourceEnd);
7898
			type.sourceEnd);
7886
}
7899
}
7900
public void potentiallyUnclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) {
7901
	if (location == null) {
7902
		this.handle(
7903
			IProblem.PotentiallyUnclosedCloseable,
7904
			NoArgument,
7905
			NoArgument,
7906
			trackVar.sourceStart,
7907
			trackVar.sourceEnd);
7908
	} else {
7909
		String[] args = { String.valueOf(trackVar.name) };
7910
		this.handle(
7911
			IProblem.PotentiallyUnclosedCloseableAtExit,
7912
			args,
7913
			args,
7914
			location.sourceStart,
7915
			location.sourceEnd);
7916
	}
7917
	trackVar.hasReportedProblem = true;
7918
}
7919
public void unclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) {
7920
	if (location == null) {
7921
		this.handle(
7922
			IProblem.UnclosedCloseable,
7923
			NoArgument,
7924
			NoArgument,
7925
			trackVar.sourceStart,
7926
			trackVar.sourceEnd);
7927
	} else {
7928
		String[] args = { String.valueOf(trackVar.name) };
7929
		this.handle(
7930
			IProblem.UnclosedCloseableAtExit,
7931
			args,
7932
			args,
7933
			location.sourceStart,
7934
			location.sourceEnd);
7935
	}
7936
	trackVar.hasReportedProblem = true;
7937
}
7938
public void explicitlyClosedAutoCloseable(FakedTrackingVariable trackVar) {
7939
	String[] args = { String.valueOf(trackVar.name) };
7940
	this.handle(
7941
		IProblem.ExplicitlyClosedAutoCloseable,
7942
		args,
7943
		args,
7944
		trackVar.sourceStart,
7945
		trackVar.sourceEnd);	
7946
}
7887
}
7947
}
(-)compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties (+5 lines)
Lines 646-651 Link Here
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 = '<>' operator is not allowed for source level below 1.7
648
883 = '<>' operator is not allowed for source level below 1.7
649
884 = Value of type AutoCloseable is not closed on all paths.
650
885 = Instance '{0}' of type AutoCloseable may be unclosed at this point.
651
886 = Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.
652
887 = Instance '{0}' of type AutoCloseable is not closed at this point.
653
888 = Instance '{0}' should be managed by try-with-resource.
649
654
650
### ELABORATIONS
655
### ELABORATIONS
651
## Access restrictions
656
## Access restrictions
(-)model/org/eclipse/jdt/core/JavaCore.java (+46 lines)
Lines 1357-1362 Link Here
1357
	 */
1357
	 */
1358
	public static final String COMPILER_PB_POTENTIALLY_MISSING_STATIC_ON_METHOD = PLUGIN_ID + ".compiler.problem.reportMethodCanBePotentiallyStatic"; //$NON-NLS-1$
1358
	public static final String COMPILER_PB_POTENTIALLY_MISSING_STATIC_ON_METHOD = PLUGIN_ID + ".compiler.problem.reportMethodCanBePotentiallyStatic"; //$NON-NLS-1$
1359
	/**
1359
	/**
1360
	 * Compiler option ID: Reporting a resource that is not closed properly.
1361
	 * <p>When enabled, that compiler will issue an error or a warning if a local variable 
1362
	 * 	  holds a value of type AutoCloseable (or Closeable if compliance is &lt; 1.7)
1363
	 *    and if flow analysis shows that the method <code>close()</code> is not invoked locally on that value.
1364
	 * <dl>
1365
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.reportUnclosedCloseable"</code></dd>
1366
	 * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
1367
	 * <dt>Default:</dt><dd><code>"warning"</code></dd>
1368
	 * </dl>
1369
	 * @since 3.7
1370
	 * @category CompilerOptionID
1371
	 */
1372
	public static final String COMPILER_PB_UNCLOSED_CLOSEABLE = PLUGIN_ID + ".compiler.problem.unclosedCloseable"; //$NON-NLS-1$
1373
	/**
1374
	 * Compiler option ID: Reporting a resource that may not be closed properly.
1375
	 * <p>When enabled, that compiler will issue an error or a warning if a local variable 
1376
	 * 	  holds a value of type AutoCloseable (or Closeable if compliance is &lt; 1.7)
1377
	 *    and if flow analysis shows that the method <code>close()</code> is not invoked locally 
1378
	 *    on that value for all execution paths.
1379
	 * <dl>
1380
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.reportPotentiallyUnclosedCloseable"</code></dd>
1381
	 * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
1382
	 * <dt>Default:</dt><dd><code>"ignore"</code></dd>
1383
	 * </dl>
1384
	 * @since 3.7
1385
	 * @category CompilerOptionID
1386
	 */
1387
	public static final String COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE = PLUGIN_ID + ".compiler.problem.potentiallyUnclosedCloseable"; //$NON-NLS-1$
1388
	/**
1389
	 * Compiler option ID: Reporting a resource that is not managed by try-with-resources.
1390
	 * <p>When enabled, that compiler will issue an error or a warning if a local variable 
1391
	 * 	  holds a value of type AutoCloseable, and if the method <code>close()</code> is
1392
	 * 	  explicitly invoked on that resource, but the resource is not managed by a
1393
	 * 	  try-with-resources block.
1394
	 * <p>Note that this option is not surfaced in the UI, as it is intended only for internal 
1395
	 * 	  use for computing quick assists / cleanups. 
1396
	 * <dl>
1397
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.reportPotentiallyUnclosedCloseable"</code></dd>
1398
	 * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
1399
	 * <dt>Default:</dt><dd><code>"ignore"</code></dd>
1400
	 * </dl>
1401
	 * @since 3.7
1402
	 * @category CompilerOptionID
1403
	 */
1404
	public static final String COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE = PLUGIN_ID + ".compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$
1405
	/**
1360
	 * Compiler option ID: Setting Source Compatibility Mode.
1406
	 * Compiler option ID: Setting Source Compatibility Mode.
1361
	 * <p>Specify whether which source level compatibility is used. From 1.4 on, <code>'assert'</code> is a keyword
1407
	 * <p>Specify whether which source level compatibility is used. From 1.4 on, <code>'assert'</code> is a keyword
1362
	 *    reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
1408
	 *    reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
(-)src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java (+3 lines)
Lines 1816-1821 Link Here
1816
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.discouragedReference\" value=\"warning\"/>\n" + 
1816
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.discouragedReference\" value=\"warning\"/>\n" + 
1817
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.emptyStatement\" value=\"ignore\"/>\n" + 
1817
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.emptyStatement\" value=\"ignore\"/>\n" + 
1818
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.enumIdentifier\" value=\"warning\"/>\n" + 
1818
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.enumIdentifier\" value=\"warning\"/>\n" + 
1819
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable\" value=\"ignore\"/>\n" + 
1819
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.fallthroughCase\" value=\"ignore\"/>\n" + 
1820
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.fallthroughCase\" value=\"ignore\"/>\n" + 
1820
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.fatalOptionalError\" value=\"disabled\"/>\n" + 
1821
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.fatalOptionalError\" value=\"disabled\"/>\n" + 
1821
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.fieldHiding\" value=\"ignore\"/>\n" + 
1822
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.fieldHiding\" value=\"ignore\"/>\n" + 
Lines 1857-1862 Link Here
1857
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.parameterAssignment\" value=\"ignore\"/>\n" + 
1858
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.parameterAssignment\" value=\"ignore\"/>\n" + 
1858
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment\" value=\"ignore\"/>\n" + 
1859
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment\" value=\"ignore\"/>\n" + 
1859
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullReference\" value=\"ignore\"/>\n" + 
1860
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullReference\" value=\"ignore\"/>\n" + 
1861
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable\" value=\"ignore\"/>\n" + 
1860
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.rawTypeReference\" value=\"warning\"/>\n" + 
1862
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.rawTypeReference\" value=\"warning\"/>\n" + 
1861
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantNullCheck\" value=\"ignore\"/>\n" + 
1863
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantNullCheck\" value=\"ignore\"/>\n" + 
1862
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantSuperinterface\" value=\"ignore\"/>\n" + 
1864
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantSuperinterface\" value=\"ignore\"/>\n" + 
Lines 1871-1876 Link Here
1871
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.typeParameterHiding\" value=\"warning\"/>\n" + 
1873
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.typeParameterHiding\" value=\"warning\"/>\n" + 
1872
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems\" value=\"enabled\"/>\n" +
1874
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems\" value=\"enabled\"/>\n" +
1873
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation\" value=\"warning\"/>\n" + 
1875
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation\" value=\"warning\"/>\n" + 
1876
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.unclosedCloseable\" value=\"warning\"/>\n" + 
1874
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock\" value=\"ignore\"/>\n" + 
1877
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock\" value=\"ignore\"/>\n" + 
1875
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.unhandledWarningToken\" value=\"warning\"/>\n" + 
1878
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.unhandledWarningToken\" value=\"warning\"/>\n" + 
1876
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.unnecessaryElse\" value=\"ignore\"/>\n" + 
1879
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.unnecessaryElse\" value=\"ignore\"/>\n" + 
(-)src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java (+10 lines)
Lines 444-449 Link Here
444
		expectedProblemAttributes.put("ExceptionTypeInternalNameProvided", DEPRECATED);
444
		expectedProblemAttributes.put("ExceptionTypeInternalNameProvided", DEPRECATED);
445
		expectedProblemAttributes.put("ExceptionTypeNotFound", DEPRECATED);
445
		expectedProblemAttributes.put("ExceptionTypeNotFound", DEPRECATED);
446
		expectedProblemAttributes.put("ExceptionTypeNotVisible", DEPRECATED);
446
		expectedProblemAttributes.put("ExceptionTypeNotVisible", DEPRECATED);
447
		expectedProblemAttributes.put("ExplicitlyClosedAutoCloseable", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
447
		expectedProblemAttributes.put("ExpressionShouldBeAVariable", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
448
		expectedProblemAttributes.put("ExpressionShouldBeAVariable", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
448
		expectedProblemAttributes.put("ExternalProblemFixable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
449
		expectedProblemAttributes.put("ExternalProblemFixable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
449
		expectedProblemAttributes.put("ExternalProblemNotFixable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
450
		expectedProblemAttributes.put("ExternalProblemNotFixable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
Lines 768-773 Link Here
768
		expectedProblemAttributes.put("PolymorphicMethodNotBelow17", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
769
		expectedProblemAttributes.put("PolymorphicMethodNotBelow17", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
769
		expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
770
		expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
770
		expectedProblemAttributes.put("PotentialHeapPollutionFromVararg", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
771
		expectedProblemAttributes.put("PotentialHeapPollutionFromVararg", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
772
		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
773
		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
771
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
774
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
772
		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
775
		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
773
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
776
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
Lines 830-835 Link Here
830
		expectedProblemAttributes.put("TypeMissingDeprecatedAnnotation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
833
		expectedProblemAttributes.put("TypeMissingDeprecatedAnnotation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
831
		expectedProblemAttributes.put("TypeParameterHidingType", new ProblemAttributes(CategorizedProblem.CAT_NAME_SHADOWING_CONFLICT));
834
		expectedProblemAttributes.put("TypeParameterHidingType", new ProblemAttributes(CategorizedProblem.CAT_NAME_SHADOWING_CONFLICT));
832
		expectedProblemAttributes.put("UnboxingConversion", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
835
		expectedProblemAttributes.put("UnboxingConversion", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
836
		expectedProblemAttributes.put("UnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
837
		expectedProblemAttributes.put("UnclosedCloseableAtExit", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
833
		expectedProblemAttributes.put("UndefinedAnnotationMember", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
838
		expectedProblemAttributes.put("UndefinedAnnotationMember", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
834
		expectedProblemAttributes.put("UndefinedConstructor", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
839
		expectedProblemAttributes.put("UndefinedConstructor", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
835
		expectedProblemAttributes.put("UndefinedConstructorInDefaultConstructor", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
840
		expectedProblemAttributes.put("UndefinedConstructorInDefaultConstructor", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
Lines 1110-1115 Link Here
1110
		expectedProblemAttributes.put("ExceptionTypeInternalNameProvided", SKIP);
1115
		expectedProblemAttributes.put("ExceptionTypeInternalNameProvided", SKIP);
1111
		expectedProblemAttributes.put("ExceptionTypeNotFound", SKIP);
1116
		expectedProblemAttributes.put("ExceptionTypeNotFound", SKIP);
1112
		expectedProblemAttributes.put("ExceptionTypeNotVisible", SKIP);
1117
		expectedProblemAttributes.put("ExceptionTypeNotVisible", SKIP);
1118
		expectedProblemAttributes.put("ExplicitlyClosedAutoCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE));
1113
		expectedProblemAttributes.put("ExpressionShouldBeAVariable", SKIP);
1119
		expectedProblemAttributes.put("ExpressionShouldBeAVariable", SKIP);
1114
		expectedProblemAttributes.put("ExternalProblemFixable", SKIP);
1120
		expectedProblemAttributes.put("ExternalProblemFixable", SKIP);
1115
		expectedProblemAttributes.put("ExternalProblemNotFixable", SKIP);
1121
		expectedProblemAttributes.put("ExternalProblemNotFixable", SKIP);
Lines 1434-1439 Link Here
1434
		expectedProblemAttributes.put("PolymorphicMethodNotBelow17", SKIP);
1440
		expectedProblemAttributes.put("PolymorphicMethodNotBelow17", SKIP);
1435
		expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT));
1441
		expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT));
1436
		expectedProblemAttributes.put("PotentialHeapPollutionFromVararg", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
1442
		expectedProblemAttributes.put("PotentialHeapPollutionFromVararg", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
1443
		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
1444
		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
1437
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1445
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1438
		expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
1446
		expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
1439
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP);
1447
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP);
Lines 1496-1501 Link Here
1496
		expectedProblemAttributes.put("TypeMissingDeprecatedAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_DEPRECATED_ANNOTATION));
1504
		expectedProblemAttributes.put("TypeMissingDeprecatedAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_DEPRECATED_ANNOTATION));
1497
		expectedProblemAttributes.put("TypeParameterHidingType", new ProblemAttributes(JavaCore.COMPILER_PB_TYPE_PARAMETER_HIDING));
1505
		expectedProblemAttributes.put("TypeParameterHidingType", new ProblemAttributes(JavaCore.COMPILER_PB_TYPE_PARAMETER_HIDING));
1498
		expectedProblemAttributes.put("UnboxingConversion", new ProblemAttributes(JavaCore.COMPILER_PB_AUTOBOXING));
1506
		expectedProblemAttributes.put("UnboxingConversion", new ProblemAttributes(JavaCore.COMPILER_PB_AUTOBOXING));
1507
		expectedProblemAttributes.put("UnclosedCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE));
1508
		expectedProblemAttributes.put("UnclosedCloseableAtExit", new ProblemAttributes(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE));
1499
		expectedProblemAttributes.put("UndefinedAnnotationMember", SKIP);
1509
		expectedProblemAttributes.put("UndefinedAnnotationMember", SKIP);
1500
		expectedProblemAttributes.put("UndefinedConstructor", SKIP);
1510
		expectedProblemAttributes.put("UndefinedConstructor", SKIP);
1501
		expectedProblemAttributes.put("UndefinedConstructorInDefaultConstructor", SKIP);
1511
		expectedProblemAttributes.put("UndefinedConstructorInDefaultConstructor", SKIP);
(-)src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java (-5 / +607 lines)
Lines 16-28 Link Here
16
16
17
import java.util.Map;
17
import java.util.Map;
18
18
19
import org.eclipse.jdt.core.JavaCore;
19
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
20
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
20
21
21
import junit.framework.Test;
22
import junit.framework.Test;
22
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
23
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
23
24
24
static {
25
static {
25
//	TESTS_NAMES = new String[] { "test053" };
26
//	TESTS_NAMES = new String[] { "test055" };
26
//	TESTS_NUMBERS = new int[] { 50 };
27
//	TESTS_NUMBERS = new int[] { 50 };
27
//	TESTS_RANGE = new int[] { 11, -1 };
28
//	TESTS_RANGE = new int[] { 11, -1 };
28
}
29
}
Lines 489-500 Link Here
489
		"	               ^^\n" + 
490
		"	               ^^\n" + 
490
		"Dead code\n" + 
491
		"Dead code\n" + 
491
		"----------\n" + 
492
		"----------\n" + 
492
		"3. ERROR in X.java (at line 5)\n" + 
493
		"3. WARNING in X.java (at line 5)\n" + 
494
		"	Y why = new Y();\n" + 
495
		"	  ^^^\n" + 
496
		"Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.\n" + 
497
		"----------\n" + 
498
		"4. ERROR in X.java (at line 5)\n" + 
493
		"	Y why = new Y();\n" + 
499
		"	Y why = new Y();\n" + 
494
		"	        ^^^^^^^\n" + 
500
		"	        ^^^^^^^\n" + 
495
		"Unhandled exception type WeirdException\n" + 
501
		"Unhandled exception type WeirdException\n" + 
496
		"----------\n" + 
502
		"----------\n" + 
497
		"4. WARNING in X.java (at line 22)\n" + 
503
		"5. WARNING in X.java (at line 22)\n" + 
498
		"	class WeirdException extends Throwable {}\n" + 
504
		"	class WeirdException extends Throwable {}\n" + 
499
		"	      ^^^^^^^^^^^^^^\n" + 
505
		"	      ^^^^^^^^^^^^^^\n" + 
500
		"The serializable class WeirdException does not declare a static final serialVersionUID field of type long\n" + 
506
		"The serializable class WeirdException does not declare a static final serialVersionUID field of type long\n" + 
Lines 562-573 Link Here
562
		"	               ^^\n" + 
568
		"	               ^^\n" + 
563
		"Dead code\n" + 
569
		"Dead code\n" + 
564
		"----------\n" + 
570
		"----------\n" + 
565
		"3. ERROR in X.java (at line 5)\n" + 
571
		"3. WARNING in X.java (at line 5)\n" + 
572
		"	Y why = new Y();\n" + 
573
		"	  ^^^\n" + 
574
		"Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.\n" + 
575
		"----------\n" + 
576
		"4. ERROR in X.java (at line 5)\n" + 
566
		"	Y why = new Y();\n" + 
577
		"	Y why = new Y();\n" + 
567
		"	        ^^^^^^^\n" + 
578
		"	        ^^^^^^^\n" + 
568
		"Unhandled exception type WeirdException\n" + 
579
		"Unhandled exception type WeirdException\n" + 
569
		"----------\n" + 
580
		"----------\n" + 
570
		"4. WARNING in X.java (at line 20)\n" + 
581
		"5. WARNING in X.java (at line 20)\n" + 
571
		"	class WeirdException extends Throwable {}\n" + 
582
		"	class WeirdException extends Throwable {}\n" + 
572
		"	      ^^^^^^^^^^^^^^\n" + 
583
		"	      ^^^^^^^^^^^^^^\n" + 
573
		"The serializable class WeirdException does not declare a static final serialVersionUID field of type long\n" + 
584
		"The serializable class WeirdException does not declare a static final serialVersionUID field of type long\n" + 
Lines 3341-3346 Link Here
3341
		"Object.Integer cannot be resolved to a type\n" + 
3352
		"Object.Integer cannot be resolved to a type\n" + 
3342
		"----------\n");
3353
		"----------\n");
3343
}
3354
}
3355
// Bug 349326 - [1.7] new warning for missing try-with-resources
3356
// a method uses an AutoCloseable without ever closing it.
3357
public void test055() {
3358
	Map options = getCompilerOptions();
3359
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3360
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3361
	this.runNegativeTest(
3362
		new String[] {
3363
			"X.java",
3364
			"import java.io.File;\n" +
3365
			"import java.io.FileReader;\n" +
3366
			"import java.io.IOException;\n" +
3367
			"public class X {\n" +
3368
			"    void foo() throws IOException {\n" +
3369
			"        File file = new File(\"somefile\");\n" +
3370
			"        FileReader fileReader = new FileReader(file);\n" +
3371
// not invoking any methods on FileReader, try to avoid necessary call to superclass()
3372
//			"        char[] in = new char[50];\n" +
3373
//			"        fileReader.read(in);\n" +
3374
			"    }\n" +
3375
			"    public static void main(String[] args) throws IOException {\n" +
3376
			"        new X().foo();\n" +
3377
			"    }\n" +
3378
			"}\n"
3379
		},
3380
		"----------\n" + 
3381
		"1. ERROR in X.java (at line 7)\n" + 
3382
		"	FileReader fileReader = new FileReader(file);\n" + 
3383
		"	           ^^^^^^^^^^\n" + 
3384
		"Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.\n" + 
3385
		"----------\n",
3386
		null,
3387
		true,
3388
		options);
3389
}
3390
// Bug 349326 - [1.7] new warning for missing try-with-resources
3391
// a method uses an AutoCloseable and closes it but exception may occur earlier.
3392
public void test055a() {
3393
	Map options = getCompilerOptions();
3394
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3395
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
3396
	this.runNegativeTest(
3397
		new String[] {
3398
			"X.java",
3399
			"import java.io.File;\n" +
3400
			"import java.io.FileReader;\n" +
3401
			"import java.io.IOException;\n" +
3402
			"public class X {\n" +
3403
			"    void foo() throws IOException {\n" +
3404
			"        File file = new File(\"somefile\");\n" +
3405
			"        FileReader fileReader = new FileReader(file);\n" +
3406
			"        char[] in = new char[50];\n" +
3407
			"        fileReader.read(in);\n" +
3408
			"		 fileReader.close();\n" +
3409
			"    }\n" +
3410
			"    public static void main(String[] args) {\n" +
3411
			"        try {\n" +
3412
			"            new X().foo();\n" +
3413
			"        } catch (IOException ioex) {\n" +
3414
			"            System.out.println(\"caught\");\n" +
3415
			"        }\n" +
3416
			"    }\n" +
3417
			"}\n"
3418
		},
3419
		"----------\n" + 
3420
		"1. ERROR in X.java (at line 7)\n" + 
3421
		"	FileReader fileReader = new FileReader(file);\n" + 
3422
		"	           ^^^^^^^^^^\n" + 
3423
		"Value of type AutoCloseable is not closed on all paths.\n" + 
3424
		"----------\n",
3425
		null,
3426
		true,
3427
		options);
3428
}
3429
// Bug 349326 - [1.7] new warning for missing try-with-resources
3430
// a method uses an AutoCloseable and closes it properly in a finally block
3431
public void test055b() {
3432
	Map options = getCompilerOptions();
3433
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3434
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
3435
	this.runConformTest(
3436
		new String[] {
3437
			"X.java",
3438
			"import java.io.File;\n" +
3439
			"import java.io.FileReader;\n" +
3440
			"import java.io.IOException;\n" +
3441
			"public class X {\n" +
3442
			"    void foo() throws IOException {\n" +
3443
			"        File file = new File(\"somefile\");\n" +
3444
			"        FileReader fileReader = new FileReader(file);\n" +
3445
			"        try {\n" +
3446
			"            char[] in = new char[50];\n" +
3447
			"            fileReader.read(in);\n" +
3448
			"        } finally {\n" +
3449
			"		     fileReader.close();\n" +
3450
			"        }\n" +
3451
			"    }\n" +
3452
			"    public static void main(String[] args) {\n" +
3453
			"        try {\n" +
3454
			"            new X().foo();\n" +
3455
			"        } catch (IOException ioex) {\n" +
3456
			"            System.out.println(\"caught\");\n" +
3457
			"        }\n" +
3458
			"    }\n" +
3459
			"}\n"
3460
		},
3461
		"caught", /*output*/
3462
		null/*classLibs*/,
3463
		true/*shouldFlush*/,
3464
		null/*vmargs*/,
3465
		options,
3466
		null/*requestor*/);
3467
}
3468
// Bug 349326 - [1.7] new warning for missing try-with-resources
3469
// a method uses an AutoCloseable properly within try-with-resources.
3470
public void test055c() {
3471
	Map options = getCompilerOptions();
3472
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3473
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3474
	this.runConformTest(
3475
		new String[] {
3476
			"X.java",
3477
			"import java.io.File;\n" +
3478
			"import java.io.FileReader;\n" +
3479
			"import java.io.IOException;\n" +
3480
			"public class X {\n" +
3481
			"    void foo() throws IOException {\n" +
3482
			"        File file = new File(\"somefile\");\n" +
3483
			"        try (FileReader fileReader = new FileReader(file)) {\n" +
3484
			"            char[] in = new char[50];\n" +
3485
			"            fileReader.read(in);\n" +
3486
			"		 }\n" +
3487
			"    }\n" +
3488
			"    public static void main(String[] args) {\n" +
3489
			"        try {\n" +
3490
			"            new X().foo();\n" +
3491
			"        } catch (IOException ioex) {\n" +
3492
			"            System.out.println(\"caught\");\n" +
3493
			"        }\n" +
3494
			"    }\n" +
3495
			"}\n"
3496
		},
3497
		"caught", /*output*/
3498
		null/*classLibs*/,
3499
		true/*shouldFlush*/,
3500
		null/*vmargs*/,
3501
		options,
3502
		null/*requestor*/);
3503
}
3504
// Bug 349326 - [1.7] new warning for missing try-with-resources
3505
// a method uses two AutoCloseables (testing independent analysis)
3506
// - one closeable may be unclosed at a conditional return
3507
// - the other is only conditionally closed
3508
public void test055d() {
3509
	Map options = getCompilerOptions();
3510
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3511
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3512
	this.runNegativeTest(
3513
		new String[] {
3514
			"X.java",
3515
			"import java.io.File;\n" +
3516
			"import java.io.FileReader;\n" +
3517
			"import java.io.IOException;\n" +
3518
			"public class X {\n" +
3519
			"    void foo(boolean flag1, boolean flag2) throws IOException {\n" +
3520
			"        File file = new File(\"somefile\");\n" +
3521
			"        char[] in = new char[50];\n" +
3522
			"        FileReader fileReader1 = new FileReader(file);\n" +
3523
			"        fileReader1.read(in);\n" +
3524
			"        FileReader fileReader2 = new FileReader(file);\n" +
3525
			"        fileReader2.read(in);\n" +
3526
			"        if (flag1) {\n" +
3527
			"            fileReader2.close();\n" +
3528
			"            return;\n" +
3529
			"        } else if (flag2) {\n" +
3530
			"            fileReader2.close();\n" +
3531
			"        }\n" +
3532
			"        fileReader1.close();\n" +
3533
			"    }\n" +
3534
			"    public static void main(String[] args) throws IOException {\n" +
3535
			"        new X().foo(false, true);\n" +
3536
			"    }\n" +
3537
			"}\n"
3538
		},
3539
		"----------\n" + 
3540
		"1. WARNING in X.java (at line 10)\n" + 
3541
		"	FileReader fileReader2 = new FileReader(file);\n" + 
3542
		"	           ^^^^^^^^^^^\n" + 
3543
		"Value of type AutoCloseable is not closed on all paths.\n" + 
3544
		"----------\n" + 
3545
		"2. ERROR in X.java (at line 14)\n" + 
3546
		"	return;\n" + 
3547
		"	^^^^^^^\n" + 
3548
		"Instance \'fileReader1\' of type AutoCloseable is not closed at this point.\n" + 
3549
		"----------\n",
3550
		null,
3551
		true,
3552
		options);
3553
}
3554
// Bug 349326 - [1.7] new warning for missing try-with-resources
3555
// one method returns an AutoCleasble, a second method uses this object without ever closing it.
3556
public void test055e() {
3557
	Map options = getCompilerOptions();
3558
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3559
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3560
	this.runNegativeTest(
3561
		new String[] {
3562
			"X.java",
3563
			"import java.io.File;\n" +
3564
			"import java.io.FileReader;\n" +
3565
			"import java.io.IOException;\n" +
3566
			"public class X {\n" +
3567
			"    FileReader getReader(String filename) throws IOException {\n" +
3568
			"        File file = new File(\"somefile\");\n" +
3569
			"        FileReader fileReader = new FileReader(file);\n" +
3570
			"        return fileReader;\n" + 		// don't complain here, pass responsibility to caller
3571
			"    }\n" +
3572
			"    void foo() throws IOException {\n" +
3573
			"        FileReader reader = getReader(\"somefile\");\n" +
3574
			"        char[] in = new char[50];\n" +
3575
			"        reader.read(in);\n" +
3576
			"    }\n" +
3577
			"    public static void main(String[] args) throws IOException {\n" +
3578
			"        new X().foo();\n" +
3579
			"    }\n" +
3580
			"}\n"
3581
		},
3582
		"----------\n" + 
3583
		"1. ERROR in X.java (at line 11)\n" + 
3584
		"	FileReader reader = getReader(\"somefile\");\n" + 
3585
		"	           ^^^^^^\n" + 
3586
		"Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.\n" + 
3587
		"----------\n",
3588
		null,
3589
		true,
3590
		options);
3591
}
3592
// Bug 349326 - [1.7] new warning for missing try-with-resources
3593
// a method explicitly closes its AutoCloseable rather than using t-w-r
3594
public void test055f() {
3595
	Map options = getCompilerOptions();
3596
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3597
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3598
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
3599
	this.runNegativeTest(
3600
		new String[] {
3601
			"X.java",
3602
			"import java.io.File;\n" +
3603
			"import java.io.FileReader;\n" +
3604
			"import java.io.IOException;\n" +
3605
			"public class X {\n" +
3606
			"    void foo() throws IOException {\n" +
3607
			"        File file = new File(\"somefile\");\n" +
3608
			"        FileReader fileReader = null;\n" +
3609
			"        try {\n" +
3610
			"            fileReader = new FileReader(file);\n" +
3611
			"            char[] in = new char[50];\n" +
3612
			"            fileReader.read(in);\n" +
3613
			"        } finally {\n" +
3614
			"            fileReader.close();\n" +
3615
			"        }\n" +
3616
			"    }\n" +
3617
			"    public static void main(String[] args) throws IOException {\n" +
3618
			"        new X().foo();\n" +
3619
			"    }\n" +
3620
			"}\n"
3621
		},
3622
		"----------\n" + 
3623
		"1. ERROR in X.java (at line 7)\n" + 
3624
		"	FileReader fileReader = null;\n" + 
3625
		"	           ^^^^^^^^^^\n" + 
3626
		"Instance \'fileReader\' should be managed by try-with-resource.\n" + 
3627
		"----------\n",
3628
		null,
3629
		true,
3630
		options);
3631
}
3632
// Bug 349326 - [1.7] new warning for missing try-with-resources
3633
// an AutoCloseable local is re-assigned
3634
public void test055g() {
3635
	Map options = getCompilerOptions();
3636
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
3637
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
3638
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
3639
	this.runNegativeTest(
3640
		new String[] {
3641
			"X.java",
3642
			"import java.io.File;\n" +
3643
			"import java.io.FileReader;\n" +
3644
			"import java.io.IOException;\n" +
3645
			"public class X {\n" +
3646
			"    void foo() throws IOException {\n" +
3647
			"        File file = new File(\"somefile\");\n" +
3648
			"        FileReader fileReader = new FileReader(file);\n" +
3649
			"        char[] in = new char[50];\n" +
3650
			"        fileReader.read(in);\n" +
3651
			"        fileReader = new FileReader(file);\n" +
3652
			"        fileReader.read(in);\n" +
3653
			"        fileReader.close();\n" +
3654
			"    }\n" +
3655
			"    public static void main(String[] args) throws IOException {\n" +
3656
			"        new X().foo();\n" +
3657
			"    }\n" +
3658
			"}\n"
3659
		},
3660
		"----------\n" + 
3661
		"1. ERROR in X.java (at line 10)\n" + 
3662
		"	fileReader = new FileReader(file);\n" + 
3663
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
3664
		"Instance \'fileReader\' of type AutoCloseable is not closed at this point.\n" + 
3665
		"----------\n",
3666
		null,
3667
		true,
3668
		options);
3669
}
3670
// Bug 349326 - [1.7] new warning for missing try-with-resources
3671
// two AutoCloseables at different nesting levels (anonymous local type)
3672
public void test055h() {
3673
	Map options = getCompilerOptions();
3674
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
3675
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
3676
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
3677
	this.runNegativeTest(
3678
		new String[] {
3679
			"X.java",
3680
			"import java.io.File;\n" +
3681
			"import java.io.FileReader;\n" +
3682
			"import java.io.IOException;\n" +
3683
			"public class X {\n" +
3684
			"    void foo() throws IOException {\n" +
3685
			"        final File file = new File(\"somefile\");\n" +
3686
			"        final FileReader fileReader = new FileReader(file);\n" +
3687
			"        char[] in = new char[50];\n" +
3688
			"        fileReader.read(in);\n" +
3689
			"        new Runnable() {\n public void run() {\n" +
3690
			"            try {\n" +
3691
			"                fileReader.close();\n" +
3692
			"                FileReader localReader = new FileReader(file);\n" +
3693
			"            } catch (IOException ex) { /* nop */ }\n" +
3694
			"        }}.run();\n" +
3695
			"    }\n" +
3696
			"    public static void main(String[] args) throws IOException {\n" +
3697
			"        new X().foo();\n" +
3698
			"    }\n" +
3699
			"}\n"
3700
		},
3701
		"----------\n" + 
3702
		"1. WARNING in X.java (at line 7)\n" + 
3703
		"	final FileReader fileReader = new FileReader(file);\n" + 
3704
		"	                 ^^^^^^^^^^\n" + 
3705
		"Value of type AutoCloseable is not closed on all paths.\n" + 
3706
		"----------\n" + 
3707
		"2. ERROR in X.java (at line 14)\n" + 
3708
		"	FileReader localReader = new FileReader(file);\n" + 
3709
		"	           ^^^^^^^^^^^\n" + 
3710
		"Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.\n" + 
3711
		"----------\n",
3712
		null,
3713
		true,
3714
		options);
3715
}
3716
// Bug 349326 - [1.7] new warning for missing try-with-resources
3717
// three AutoCloseables in different blocks of the same method
3718
public void test055i() {
3719
	Map options = getCompilerOptions();
3720
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
3721
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
3722
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
3723
	this.runNegativeTest(
3724
		new String[] {
3725
			"X.java",
3726
			"import java.io.File;\n" +
3727
			"import java.io.FileReader;\n" +
3728
			"import java.io.IOException;\n" +
3729
			"public class X {\n" +
3730
			"    void foo(boolean f1, boolean f2) throws IOException {\n" +
3731
			"        File file = new File(\"somefile\");\n" +
3732
			"        if (f1) {\n" +
3733
			"            FileReader fileReader = new FileReader(file); // err: not closed\n" +
3734
			"            char[] in = new char[50];\n" +
3735
			"            fileReader.read(in);\n" +
3736
			"            while (true) {\n" +
3737
			"                 FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" +
3738
			"                 loopReader.close();" +
3739
			"                 break;\n" +
3740
			"            }\n" +
3741
			"        } else {\n" +
3742
			"            FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
3743
			"            if (f2)\n" +
3744
			"                fileReader.close();\n" +
3745
			"        }\n" +
3746
			"    }\n" +
3747
			"    public static void main(String[] args) throws IOException {\n" +
3748
			"        new X().foo(true, true);\n" +
3749
			"    }\n" +
3750
			"}\n"
3751
		},
3752
		"----------\n" + 
3753
		"1. ERROR in X.java (at line 8)\n" + 
3754
		"	FileReader fileReader = new FileReader(file); // err: not closed\n" + 
3755
		"	           ^^^^^^^^^^\n" + 
3756
		"Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.\n" + 
3757
		"----------\n" + 
3758
		"2. WARNING in X.java (at line 16)\n" + 
3759
		"	FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" + 
3760
		"	           ^^^^^^^^^^\n" + 
3761
		"Value of type AutoCloseable is not closed on all paths.\n" + 
3762
		"----------\n",
3763
		null,
3764
		true,
3765
		options);
3766
}
3767
// Bug 349326 - [1.7] new warning for missing try-with-resources
3768
// a method uses an AutoCloseable without closing it locally but passing as arg to another method
3769
public void test055j() {
3770
	Map options = getCompilerOptions();
3771
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3772
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
3773
	this.runNegativeTest(
3774
		new String[] {
3775
			"X.java",
3776
			"import java.io.File;\n" +
3777
			"import java.io.FileReader;\n" +
3778
			"import java.io.IOException;\n" +
3779
			"public class X {\n" +
3780
			"    void foo() throws IOException {\n" +
3781
			"        File file = new File(\"somefile\");\n" +
3782
			"        FileReader fileReader = new FileReader(file);\n" +
3783
			"        read(fileReader);\n" +
3784
			"    }\n" +
3785
			"    void read(FileReader reader) { }\n" +
3786
			"    public static void main(String[] args) throws IOException {\n" +
3787
			"        new X().foo();\n" +
3788
			"    }\n" +
3789
			"}\n"
3790
		},
3791
		"----------\n" + 
3792
		"1. ERROR in X.java (at line 7)\n" + 
3793
		"	FileReader fileReader = new FileReader(file);\n" + 
3794
		"	           ^^^^^^^^^^\n" + 
3795
		"Value of type AutoCloseable is not closed on all paths.\n" + 
3796
		"----------\n",
3797
		null,
3798
		true,
3799
		options);
3800
}
3801
// Bug 349326 - [1.7] new warning for missing try-with-resources
3802
// many locals, some are AutoCloseable
3803
public void test055k() {
3804
	Map options = getCompilerOptions();
3805
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3806
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3807
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
3808
	this.runNegativeTest(
3809
		new String[] {
3810
			"X.java",
3811
			"import java.io.File;\n" +
3812
			"import java.io.FileReader;\n" +
3813
			"import java.io.IOException;\n" +
3814
			"public class X {\n" +
3815
			"    void foo() throws IOException {\n" +
3816
			"        int i01, i02, i03, i04, i05, i06, i07, i08, i09,\n" +
3817
			"            i11, i12, i13, i14, i15, i16, i17, i18, i19,\n" +
3818
			"            i21, i22, i23, i24, i25, i26, i27, i28, i29,\n" +
3819
			"            i31, i32, i33, i34, i35, i36, i37, i38, i39,\n" +
3820
			"            i41, i42, i43, i44, i45, i46, i47, i48, i49;\n" +
3821
			"        File file = new File(\"somefile\");\n" +
3822
			"        FileReader ra1 = null, ra2 = null;\n" +
3823
			"        try {\n" +
3824
			"            ra1 = new FileReader(file);\n" +
3825
			"            ra2 = new FileReader(file);\n" +
3826
			"            FileReader ra3 = new FileReader(file);\n" +
3827
			"            char[] in = new char[50];\n" +
3828
			"            ra1.read(in);\n" +
3829
			"            ra2.read(in);\n" +
3830
			"            ra3.close();\n" +
3831
			"        } finally {\n" +
3832
			"            ra1.close();\n" +
3833
			"        }\n" +
3834
			"        int i51, i52, i53, i54, i55, i56, i57, i58, i59, i60;\n" + // beyond this point locals are analyzed using extraBits
3835
			"        FileReader rb1 = null, rb2 = null;\n" +
3836
			"        try {\n" +
3837
			"            rb1 = new FileReader(file);\n" +
3838
			"            rb2 = new FileReader(file);\n" +
3839
			"            FileReader rb3 = new FileReader(file);\n" +
3840
			"            char[] in = new char[50];\n" +
3841
			"            rb1.read(in);\n" +
3842
			"            rb2.read(in);\n" +
3843
			"            rb3.close();\n" +
3844
			"        } finally {\n" +
3845
			"            rb1.close();\n" +
3846
			"        }\n" +
3847
			"    }\n" +
3848
			"    public static void main(String[] args) throws IOException {\n" +
3849
			"        new X().foo();\n" +
3850
			"    }\n" +
3851
			"}\n"
3852
		},
3853
		"----------\n" + 
3854
		"1. ERROR in X.java (at line 12)\n" + 
3855
		"	FileReader ra1 = null, ra2 = null;\n" + 
3856
		"	           ^^^\n" + 
3857
		"Instance \'ra1\' should be managed by try-with-resource.\n" + 
3858
		"----------\n" + 
3859
		"2. ERROR in X.java (at line 15)\n" + 
3860
		"	ra2 = new FileReader(file);\n" + 
3861
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
3862
		"Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.\n" + 
3863
		"----------\n" + 
3864
		"3. WARNING in X.java (at line 16)\n" + 
3865
		"	FileReader ra3 = new FileReader(file);\n" + 
3866
		"	           ^^^\n" + 
3867
		"Value of type AutoCloseable is not closed on all paths.\n" + 
3868
		"----------\n" + 
3869
		"4. ERROR in X.java (at line 25)\n" + 
3870
		"	FileReader rb1 = null, rb2 = null;\n" + 
3871
		"	           ^^^\n" + 
3872
		"Instance \'rb1\' should be managed by try-with-resource.\n" + 
3873
		"----------\n" + 
3874
		"5. ERROR in X.java (at line 28)\n" + 
3875
		"	rb2 = new FileReader(file);\n" + 
3876
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
3877
		"Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.\n" + 
3878
		"----------\n" + 
3879
		"6. WARNING in X.java (at line 29)\n" + 
3880
		"	FileReader rb3 = new FileReader(file);\n" + 
3881
		"	           ^^^\n" + 
3882
		"Value of type AutoCloseable is not closed on all paths.\n" + 
3883
		"----------\n",
3884
		null,
3885
		true,
3886
		options);
3887
}
3888
// Bug 349326 - [1.7] new warning for missing try-with-resources
3889
// various non-problems
3890
public void test055l() {
3891
	Map options = getCompilerOptions();
3892
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3893
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
3894
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
3895
	this.runNegativeTest(
3896
		new String[] {
3897
			"X.java",
3898
			"import java.io.File;\n" +
3899
			"import java.io.FileReader;\n" +
3900
			"import java.io.IOException;\n" +
3901
			"public class X {\n" +
3902
			"    X(FileReader r0) {}\n" + // don't complain against argument
3903
			"    FileReader getReader() { return null; }\n" +
3904
			"    void foo(FileReader r1) throws IOException {\n" +
3905
			"        FileReader fileReader = getReader();\n" +
3906
			"        if (fileReader == null)\n" +
3907
			"            return;\n" + // don't complain, resource is actually null
3908
			"        FileReader r3 = getReader();\n" +
3909
			"        if (r3 == null)\n" +
3910
			"            r3 = new FileReader(new File(\"absent\"));\n" + // don't complain, previous resource is actually null
3911
			"        try {\n" +
3912
			"            char[] in = new char[50];\n" +
3913
			"            fileReader.read(in);\n" +
3914
			"            r1.read(in);\n" +
3915
			"        } finally {\n" +
3916
			"            fileReader.close();\n" +
3917
			"            r3.close();\n" +
3918
			"        }\n" +
3919
			"    }\n" +
3920
			"    public static void main(String[] args) throws IOException {\n" +
3921
			"        FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" +
3922
			"        new X(r2).foo(new FileReader(new File(\"notthere\")));\n" +
3923
			"    }\n" +
3924
			"}\n"
3925
		},
3926
		"----------\n" + 
3927
		"1. ERROR in X.java (at line 8)\n" + 
3928
		"	FileReader fileReader = getReader();\n" + 
3929
		"	           ^^^^^^^^^^\n" + 
3930
		"Instance \'fileReader\' should be managed by try-with-resource.\n" + 
3931
		"----------\n" + 
3932
		"2. ERROR in X.java (at line 11)\n" + 
3933
		"	FileReader r3 = getReader();\n" + 
3934
		"	           ^^\n" + 
3935
		"Instance \'r3\' should be managed by try-with-resource.\n" + 
3936
		"----------\n" + 
3937
		"3. ERROR in X.java (at line 24)\n" + 
3938
		"	FileReader r2 = new FileReader(new File(\"inexist\")); // only potential problem: ctor X below might close r2\n" + 
3939
		"	           ^^\n" + 
3940
		"Value of type AutoCloseable is not closed on all paths.\n" + 
3941
		"----------\n",
3942
		null,
3943
		true,
3944
		options);
3945
}
3344
public static Class testClass() {
3946
public static Class testClass() {
3345
	return TryWithResourcesStatementTest.class;
3947
	return TryWithResourcesStatementTest.class;
3346
}
3948
}

Return to bug 349326