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 1392-1397 Link Here
1392
	int SwitchOnStringsNotBelow17 = TypeRelated + 881;	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=348492
1392
	int SwitchOnStringsNotBelow17 = TypeRelated + 881;	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=348492
1393
	/** @since 3.7 */
1393
	/** @since 3.7 */
1394
	int UnhandledExceptionOnAutoClose =  TypeRelated + 882;
1394
	int UnhandledExceptionOnAutoClose =  TypeRelated + 882;
1395
	/** @since 3.7 */
1396
	int PotentiallyUnclosedCloseable = Internal + 883;
1397
	/** @since 3.7 */
1398
	int PotentiallyUnclosedCloseableAtExit = Internal + 884;
1399
	/** @since 3.7 */
1400
	int UnclosedCloseable = Internal + 885;
1401
	/** @since 3.7 */
1402
	int UnclosedCloseableAtExit = Internal + 886;
1403
	/** @since 3.7 */
1404
	int ExplicitlyClosedAutoCloseable = Internal + 887;
1405
1395
	/**
1406
	/**
1396
	 * External problems -- These are problems defined by other plugins
1407
	 * External problems -- These are problems defined by other plugins
1397
	 */
1408
	 */
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java (+19 lines)
Lines 48-53 Link Here
48
	if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
48
	if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
49
		this.expression.checkNPE(currentScope, flowContext, flowInfo);
49
		this.expression.checkNPE(currentScope, flowContext, flowInfo);
50
	}
50
	}
51
	if (local != null) {
52
		LocalVariableBinding trackerBinding = null;
53
		if (local.closeTracker != null) {
54
			// Assigning to a variable already holding an AutoCloseable, has it been closed before?
55
			trackerBinding = local.closeTracker.binding;
56
			if (flowInfo.isDefinitelyNull(trackerBinding))
57
				currentScope.problemReporter().unclosedCloseable(local.closeTracker, this);
58
			else if (flowInfo.isPotentiallyNull(trackerBinding))
59
				currentScope.problemReporter().potentiallyUnclosedCloseable(local.closeTracker, this);
60
		}
61
		if (FakedTrackingVariable.isAutoCloseable(this.expression.resolvedType)) {
62
			// new value is AutoCloseable start tracking, possibly re-using existing tracker var:
63
			if (trackerBinding == null) {
64
				local.closeTracker = new FakedTrackingVariable(currentScope, this, local.name);
65
				trackerBinding = local.closeTracker.binding;
66
			}
67
			flowInfo.markAsDefinitelyNull(trackerBinding);
68
		}
69
	}
51
	flowInfo = ((Reference) this.lhs)
70
	flowInfo = ((Reference) this.lhs)
52
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
71
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
53
		.unconditionalInits();
72
		.unconditionalInits();
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java (+70 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2011 GK Software AG and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     GK Software AG - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
12
13
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
14
import org.eclipse.jdt.internal.compiler.impl.Constant;
15
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
16
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
17
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
18
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
20
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
21
22
/**
23
 * A faked local variable declaration used for keeping track of data flows of a
24
 * special variable. Certain events will be recorded by changing the null info
25
 * for this variable.
26
 * 
27
 * @author Stephan Herrmann
28
 */
29
public class FakedTrackingVariable extends LocalDeclaration {
30
31
	public boolean isInsideTWR = false;
32
33
	public FakedTrackingVariable(BlockScope currentScope, Statement location, char[] name) {
34
		super(name, location.sourceStart, location.sourceEnd);
35
		this.type = new SingleTypeReference(
36
				TypeConstants.OBJECT,
37
				((long)this.sourceStart <<32)+this.sourceEnd);
38
		resolve(currentScope);
39
	}
40
41
	public void generateCode(BlockScope currentScope, CodeStream codeStream)
42
	{ /* NOP - this variable is completely dummy, ie. for analysis only. */ }
43
44
	public void resolve (BlockScope scope) {
45
		// only need the binding, which is used as reference in FlowInfo methods.
46
		this.binding = new LocalVariableBinding(
47
				this.name,
48
				scope.getJavaLangObject(),  // dummy, just needs to be a reference type
49
				0,
50
				false);
51
		this.binding.setConstant(Constant.NotAConstant);
52
		this.binding.useFlag = LocalVariableBinding.USED;
53
		// use a free slot without assigning it:
54
		this.binding.id = scope.outerMostMethodScope().registerTrackingVariable(this);
55
	}
56
57
	public static boolean isAutoCloseable(TypeBinding typeBinding) {
58
		return typeBinding instanceof ReferenceBinding
59
			&& ((ReferenceBinding)typeBinding).hasTypeBit(TypeIds.BitAutoCloseable);
60
	}
61
	
62
	public static FakedTrackingVariable getTrackingVariable(Expression expression) {
63
		if (expression instanceof SingleNameReference) {
64
			SingleNameReference returnName = (SingleNameReference) expression;
65
			if (returnName.binding instanceof LocalVariableBinding)
66
				return ((LocalVariableBinding)returnName.binding).closeTracker;
67
		}
68
		return null;
69
	}
70
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java (+4 lines)
Lines 71-76 Link Here
71
	if ((this.initialization.implicitConversion & TypeIds.UNBOXING) != 0) {
71
	if ((this.initialization.implicitConversion & TypeIds.UNBOXING) != 0) {
72
		this.initialization.checkNPE(currentScope, flowContext, flowInfo);
72
		this.initialization.checkNPE(currentScope, flowContext, flowInfo);
73
	}
73
	}
74
	if (FakedTrackingVariable.isAutoCloseable(this.initialization.resolvedType)) {
75
		this.binding.closeTracker = new FakedTrackingVariable(currentScope, this, this.name);
76
		flowInfo.markAsDefinitelyNull(this.binding.closeTracker.binding);
77
	}
74
	
78
	
75
	flowInfo =
79
	flowInfo =
76
		this.initialization
80
		this.initialization
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (+5 lines)
Lines 42-47 Link Here
42
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
42
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
43
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
43
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
44
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
44
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
45
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
45
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
46
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
46
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
47
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
47
48
Lines 64-69 Link Here
64
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
65
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
65
	boolean nonStatic = !this.binding.isStatic();
66
	boolean nonStatic = !this.binding.isStatic();
66
	flowInfo = this.receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits();
67
	flowInfo = this.receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits();
68
	FakedTrackingVariable trackingVariable = FakedTrackingVariable.getTrackingVariable(this.receiver);
69
	if (   trackingVariable != null 
70
		&& CharOperation.equals(TypeConstants.CLOSE, this.selector))
71
		flowInfo.markAsDefinitelyNonNull(trackingVariable.binding);
67
	if (nonStatic) {
72
	if (nonStatic) {
68
		this.receiver.checkNPE(currentScope, flowContext, flowInfo);
73
		this.receiver.checkNPE(currentScope, flowContext, flowInfo);
69
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
74
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java (+1 lines)
Lines 134-139 Link Here
134
				}
134
				}
135
					
135
					
136
			}
136
			}
137
			this.scope.checkUnclosedCloseables(flowInfo, null);
137
		} catch (AbortMethod e) {
138
		} catch (AbortMethod e) {
138
			this.ignoreFurtherInvestigation = true;
139
			this.ignoreFurtherInvestigation = true;
139
		}
140
		}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java (+4 lines)
Lines 40-45 Link Here
40
		if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
40
		if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
41
			this.expression.checkNPE(currentScope, flowContext, flowInfo);
41
			this.expression.checkNPE(currentScope, flowContext, flowInfo);
42
		}
42
		}
43
		FakedTrackingVariable trackingVariable = FakedTrackingVariable.getTrackingVariable(this.expression);
44
		if (trackingVariable != null)
45
			flowInfo.markAsDefinitelyNonNull(trackingVariable.binding);
43
	}
46
	}
44
	this.initStateIndex =
47
	this.initStateIndex =
45
		currentScope.methodScope().recordInitializationStates(flowInfo);
48
		currentScope.methodScope().recordInitializationStates(flowInfo);
Lines 104-109 Link Here
104
			this.expression.bits |= ASTNode.IsReturnedValue;
107
			this.expression.bits |= ASTNode.IsReturnedValue;
105
		}
108
		}
106
	}
109
	}
110
	currentScope.checkUnclosedCloseables(flowInfo, this);
107
	return FlowInfo.DEAD_END;
111
	return FlowInfo.DEAD_END;
108
}
112
}
109
113
(-)compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java (-2 / +7 lines)
Lines 120-127 Link Here
120
120
121
		for (int i = 0, max = this.resources.length; i < max; i++) {
121
		for (int i = 0, max = this.resources.length; i < max; i++) {
122
			flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
122
			flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
123
			this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
123
			LocalVariableBinding resourceBinding = this.resources[i].binding;
124
			TypeBinding type = this.resources[i].binding.type;
124
			resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
125
			if (resourceBinding.closeTracker != null) {
126
				resourceBinding.closeTracker.isInsideTWR = true;
127
				flowInfo.markAsDefinitelyNonNull(resourceBinding.closeTracker.binding);
128
			} 
129
			TypeBinding type = resourceBinding.type;
125
			if (type != null && type.isValidBinding()) {
130
			if (type != null && type.isValidBinding()) {
126
				ReferenceBinding binding = (ReferenceBinding) type;
131
				ReferenceBinding binding = (ReferenceBinding) type;
127
				MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter
132
				MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter
(-)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.reportUnclosedCloseable"; //$NON-NLS-1$
140
	public static final String OPTION_ReportPotentiallyUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.reportPotentiallyUnclosedCloseable"; //$NON-NLS-1$
141
	public static final String OPTION_ReportExplicitlyClosedAutoCloseable = "org.eclipse.jdt.core.compiler.problem.reportExplicitlyClosedAutoCloseable"; //$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 (+19 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 1141-1146 Link Here
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 1152-1157 Link Here
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
		// TODO(SH): check if this actually speeds up anything:
1168
		if ((this.superInterfaces[i].tagBits & (TagBits.HasUnresolvedSuperclass|TagBits.HasUnresolvedSuperinterfaces)) != 0) 
1169
		{
1170
			this.superInterfaces[i].superclass();
1171
			this.superInterfaces[i].superInterfaces();
1172
		}
1173
		this.typeBits |= this.superInterfaces[i].typeBits;
1155
	}
1174
	}
1156
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
1175
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
1157
	return this.superInterfaces;
1176
	return this.superInterfaces;
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java (+27 lines)
Lines 10-19 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
11
package org.eclipse.jdt.internal.compiler.lookup;
12
12
13
import java.util.ArrayList;
14
import java.util.List;
15
13
import org.eclipse.jdt.core.compiler.CharOperation;
16
import org.eclipse.jdt.core.compiler.CharOperation;
14
import org.eclipse.jdt.internal.compiler.ast.*;
17
import org.eclipse.jdt.internal.compiler.ast.*;
15
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
18
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
16
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
19
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
20
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
17
import org.eclipse.jdt.internal.compiler.impl.Constant;
21
import org.eclipse.jdt.internal.compiler.impl.Constant;
18
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
22
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
19
23
Lines 957-960 Link Here
957
		}
961
		}
958
	}
962
	}
959
}
963
}
964
965
// TODO: List or array?
966
// TODO: move these to FlowInfo? (beware of flowInfo copying!)
967
private List trackingVariables;
968
public int addTrackingVariable(FakedTrackingVariable fakedTrackingVariable) {
969
	if (this.trackingVariables == null)
970
		this.trackingVariables = new ArrayList();
971
	this.trackingVariables.add(fakedTrackingVariable);
972
	return this.trackingVariables.size();
973
}
974
975
public void checkUnclosedCloseables(FlowInfo flowInfo, 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 (flowInfo.isDefinitelyNull(trackingVar.binding))
980
			problemReporter().unclosedCloseable(trackingVar, location);
981
		else if (flowInfo.isPotentiallyNull(trackingVar.binding))
982
			problemReporter().potentiallyUnclosedCloseable(trackingVar, location);
983
		else if (environment().globalOptions.complianceLevel >= ClassFileConstants.JDK1_7 && !trackingVar.isInsideTWR)
984
			problemReporter().explicitlyClosedAutoCloseable(trackingVar);
985
	}	
986
}
960
}
987
}
(-)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;
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 (+6 lines)
Lines 479-482 Link Here
479
public TypeDeclaration referenceType() {
479
public TypeDeclaration referenceType() {
480
	return ((ClassScope) this.parent).referenceContext;
480
	return ((ClassScope) this.parent).referenceContext;
481
}
481
}
482
483
public int registerTrackingVariable(FakedTrackingVariable fakedTrackingVariable) {
484
	int offset = addTrackingVariable(fakedTrackingVariable);
485
	return this.analysisIndex + offset;
486
	
487
}
482
}
488
}
(-)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/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
	public 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
	if (!isLocalType())
938
		Assert.isTrue((this.tagBits & TagBits.EndHierarchyCheck) != 0, "Hierarchy should be connected"); //$NON-NLS-1$
939
	return (this.typeBits & bit) != 0;
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/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/problem/ProblemReporter.java (+55 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 7862-7865 Link Here
7862
			type.sourceStart, 
7872
			type.sourceStart, 
7863
			type.sourceEnd);
7873
			type.sourceEnd);
7864
}
7874
}
7875
public void potentiallyUnclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) {
7876
	if (location == null) {
7877
		this.handle(
7878
			IProblem.PotentiallyUnclosedCloseable,
7879
			NoArgument,
7880
			NoArgument,
7881
			trackVar.sourceStart,
7882
			trackVar.sourceEnd);
7883
	} else {
7884
		String[] args = { String.valueOf(trackVar.name) };
7885
		this.handle(
7886
			IProblem.PotentiallyUnclosedCloseableAtExit,
7887
			args,
7888
			args,
7889
			location.sourceStart,
7890
			location.sourceEnd);
7891
	}
7892
}
7893
public void unclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) {
7894
	if (location == null) {
7895
		this.handle(
7896
			IProblem.UnclosedCloseable,
7897
			NoArgument,
7898
			NoArgument,
7899
			trackVar.sourceStart,
7900
			trackVar.sourceEnd);
7901
	} else {
7902
		String[] args = { String.valueOf(trackVar.name) };
7903
		this.handle(
7904
			IProblem.UnclosedCloseableAtExit,
7905
			args,
7906
			args,
7907
			location.sourceStart,
7908
			location.sourceEnd);
7909
	}
7910
}
7911
public void explicitlyClosedAutoCloseable(FakedTrackingVariable trackVar) {
7912
	String[] args = { String.valueOf(trackVar.name) };
7913
	this.handle(
7914
		IProblem.ExplicitlyClosedAutoCloseable,
7915
		args,
7916
		args,
7917
		trackVar.sourceStart,
7918
		trackVar.sourceEnd);	
7919
}
7865
}
7920
}
(-)compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties (+5 lines)
Lines 645-650 Link Here
645
880 = '<>' cannot be used with anonymous classes
645
880 = '<>' cannot be used with anonymous classes
646
881 = Cannot switch on a value of type String for source level below 1.7. Only convertible int values or enum constants are permitted
646
881 = Cannot switch on a value of type String for source level below 1.7. Only convertible int values or enum constants are permitted
647
882 = Unhandled exception type {0} thrown by automatic close() invocation on {1}
647
882 = Unhandled exception type {0} thrown by automatic close() invocation on {1}
648
883 = Value of type AutoCloseable is not closed on all paths.
649
884 = Instance '{0}' of type AutoCloseable may be unclosed at this point.
650
885 = Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.
651
886 = Instance '{0}' of type AutoCloseable is not closed at this point.
652
887 = Instance '{0}' should be managed by try-with-resource.
648
653
649
### ELABORATIONS
654
### ELABORATIONS
650
## Access restrictions
655
## 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.reportUnclosedCloseable"; //$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.reportPotentiallyUnclosedCloseable"; //$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.reportExplicitlyClosedAutoCloseable"; //$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/TryWithResourcesStatementTest.java (-1 / +272 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 3341-3346 Link Here
3341
		"Object.Integer cannot be resolved to a type\n" + 
3342
		"Object.Integer cannot be resolved to a type\n" + 
3342
		"----------\n");
3343
		"----------\n");
3343
}
3344
}
3345
// Bug 349326 - [1.7] new warning for missing try-with-resources
3346
// a method uses an AutoCloseable without ever closing it.
3347
public void test055() {
3348
	Map options = getCompilerOptions();
3349
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3350
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3351
	this.runNegativeTest(
3352
		new String[] {
3353
			"X.java",
3354
			"import java.io.File;\n" +
3355
			"import java.io.FileReader;\n" +
3356
			"import java.io.IOException;\n" +
3357
			"public class X {\n" +
3358
			"    void foo() throws IOException {\n" +
3359
			"        File file = new File(\"somefile\");\n" +
3360
			"        FileReader fileReader = new FileReader(file);\n" +
3361
// not invoking any methods on FileReader, try to avoid necessary call to superclass()
3362
//			"        char[] in = new char[50];\n" +
3363
//			"        fileReader.read(in);\n" +
3364
			"    }\n" +
3365
			"    public static void main(String[] args) throws IOException {\n" +
3366
			"        new X().foo();\n" +
3367
			"    }\n" +
3368
			"}\n"
3369
		},
3370
		"----------\n" + 
3371
		"1. ERROR in X.java (at line 7)\n" + 
3372
		"	FileReader fileReader = new FileReader(file);\n" + 
3373
		"	           ^^^^^^^^^^\n" + 
3374
		"Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.\n" + 
3375
		"----------\n",
3376
		null,
3377
		true,
3378
		options);
3379
}
3380
// Bug 349326 - [1.7] new warning for missing try-with-resources
3381
// a method uses an AutoCloseable and closes it properly.
3382
public void test055a() {
3383
	Map options = getCompilerOptions();
3384
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3385
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3386
	this.runConformTest(
3387
		new String[] {
3388
			"X.java",
3389
			"import java.io.File;\n" +
3390
			"import java.io.FileReader;\n" +
3391
			"import java.io.IOException;\n" +
3392
			"public class X {\n" +
3393
			"    void foo() throws IOException {\n" +
3394
			"        File file = new File(\"somefile\");\n" +
3395
			"        FileReader fileReader = new FileReader(file);\n" +
3396
			"        char[] in = new char[50];\n" +
3397
			"        fileReader.read(in);\n" +
3398
			"		 fileReader.close();\n" +
3399
			"    }\n" +
3400
			"    public static void main(String[] args) {\n" +
3401
			"        try {\n" +
3402
			"            new X().foo();\n" +
3403
			"        } catch (IOException ioex) {\n" +
3404
			"            System.out.println(\"caught\");\n" +
3405
			"        }\n" +
3406
			"    }\n" +
3407
			"}\n"
3408
		},
3409
		"caught", /*output*/
3410
		null/*classLibs*/,
3411
		true/*shouldFlush*/,
3412
		null/*vmargs*/,
3413
		options,
3414
		null/*requestor*/);
3415
}
3416
// Bug 349326 - [1.7] new warning for missing try-with-resources
3417
// a method uses an AutoCloseable properly within try-with-resources.
3418
public void test055b() {
3419
	Map options = getCompilerOptions();
3420
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3421
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3422
	this.runConformTest(
3423
		new String[] {
3424
			"X.java",
3425
			"import java.io.File;\n" +
3426
			"import java.io.FileReader;\n" +
3427
			"import java.io.IOException;\n" +
3428
			"public class X {\n" +
3429
			"    void foo() throws IOException {\n" +
3430
			"        File file = new File(\"somefile\");\n" +
3431
			"        try (FileReader fileReader = new FileReader(file)) {\n" +
3432
			"            char[] in = new char[50];\n" +
3433
			"            fileReader.read(in);\n" +
3434
			"		 }\n" +
3435
			"    }\n" +
3436
			"    public static void main(String[] args) {\n" +
3437
			"        try {\n" +
3438
			"            new X().foo();\n" +
3439
			"        } catch (IOException ioex) {\n" +
3440
			"            System.out.println(\"caught\");\n" +
3441
			"        }\n" +
3442
			"    }\n" +
3443
			"}\n"
3444
		},
3445
		"caught", /*output*/
3446
		null/*classLibs*/,
3447
		true/*shouldFlush*/,
3448
		null/*vmargs*/,
3449
		options,
3450
		null/*requestor*/);
3451
}
3452
// Bug 349326 - [1.7] new warning for missing try-with-resources
3453
// a method uses two AutoCloseables (testing independent analysis)
3454
// - one closeable may be unclosed at a conditional return
3455
// - the other is only conditionally closed
3456
public void test055c() {
3457
	Map options = getCompilerOptions();
3458
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3459
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3460
	this.runNegativeTest(
3461
		new String[] {
3462
			"X.java",
3463
			"import java.io.File;\n" +
3464
			"import java.io.FileReader;\n" +
3465
			"import java.io.IOException;\n" +
3466
			"public class X {\n" +
3467
			"    void foo(boolean flag1, boolean flag2) throws IOException {\n" +
3468
			"        File file = new File(\"somefile\");\n" +
3469
			"        char[] in = new char[50];\n" +
3470
			"        FileReader fileReader1 = new FileReader(file);\n" +
3471
			"        fileReader1.read(in);\n" +
3472
			"        FileReader fileReader2 = new FileReader(file);\n" +
3473
			"        fileReader2.read(in);\n" +
3474
			"        if (flag1) {\n" +
3475
			"            fileReader2.close();\n" +
3476
			"            return;\n" +
3477
			"        } else if (flag2) {\n" +
3478
			"            fileReader2.close();\n" +
3479
			"        }\n" +
3480
			"        fileReader1.close();\n" +
3481
			"    }\n" +
3482
			"    public static void main(String[] args) throws IOException {\n" +
3483
			"        new X().foo(false, true);\n" +
3484
			"    }\n" +
3485
			"}\n"
3486
		},
3487
		"----------\n" + 
3488
		"1. WARNING in X.java (at line 10)\n" + 
3489
		"	FileReader fileReader2 = new FileReader(file);\n" + 
3490
		"	           ^^^^^^^^^^^\n" + 
3491
		"Value of type AutoCloseable is not closed on all paths.\n" + 
3492
		"----------\n" + 
3493
		"2. ERROR in X.java (at line 14)\n" + 
3494
		"	return;\n" + 
3495
		"	^^^^^^^\n" + 
3496
		"Instance \'fileReader1\' of type AutoCloseable is not closed at this point.\n" + 
3497
		"----------\n",
3498
		null,
3499
		true,
3500
		options);
3501
}
3502
// Bug 349326 - [1.7] new warning for missing try-with-resources
3503
// one method returns an AutoCleasble, a second method uses this object without ever closing it.
3504
public void test055d() {
3505
	Map options = getCompilerOptions();
3506
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3507
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3508
	this.runNegativeTest(
3509
		new String[] {
3510
			"X.java",
3511
			"import java.io.File;\n" +
3512
			"import java.io.FileReader;\n" +
3513
			"import java.io.IOException;\n" +
3514
			"public class X {\n" +
3515
			"    FileReader getReader(String filename) throws IOException {\n" +
3516
			"        File file = new File(\"somefile\");\n" +
3517
			"        FileReader fileReader = new FileReader(file);\n" +
3518
			"        return fileReader;\n" + 		// don't complain here, pass responsibility to caller
3519
			"    }\n" +
3520
			"    void foo() throws IOException {\n" +
3521
			"        FileReader reader = getReader(\"somefile\");\n" +
3522
			"        char[] in = new char[50];\n" +
3523
			"        reader.read(in);\n" +
3524
			"    }\n" +
3525
			"    public static void main(String[] args) throws IOException {\n" +
3526
			"        new X().foo();\n" +
3527
			"    }\n" +
3528
			"}\n"
3529
		},
3530
		"----------\n" + 
3531
		"1. ERROR in X.java (at line 11)\n" + 
3532
		"	FileReader reader = getReader(\"somefile\");\n" + 
3533
		"	           ^^^^^^\n" + 
3534
		"Value of type AutoCloseable is not closed neither explicitly nor using a try-with-resources.\n" + 
3535
		"----------\n",
3536
		null,
3537
		true,
3538
		options);
3539
}
3540
// Bug 349326 - [1.7] new warning for missing try-with-resources
3541
// a method explicitly closes its AutoCloseable rather than using t-w-r
3542
public void test055e() {
3543
	Map options = getCompilerOptions();
3544
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3545
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3546
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
3547
	this.runNegativeTest(
3548
		new String[] {
3549
			"X.java",
3550
			"import java.io.File;\n" +
3551
			"import java.io.FileReader;\n" +
3552
			"import java.io.IOException;\n" +
3553
			"public class X {\n" +
3554
			"    void foo() throws IOException {\n" +
3555
			"        File file = new File(\"somefile\");\n" +
3556
			"        FileReader fileReader;\n" +
3557
			"        fileReader = new FileReader(file);\n" +
3558
			"        char[] in = new char[50];\n" +
3559
			"        fileReader.read(in);\n" +
3560
			"        fileReader.close();\n" +
3561
			"    }\n" +
3562
			"    public static void main(String[] args) throws IOException {\n" +
3563
			"        new X().foo();\n" +
3564
			"    }\n" +
3565
			"}\n"
3566
		},
3567
		"----------\n" + 
3568
		"1. ERROR in X.java (at line 8)\n" + 
3569
		"	fileReader = new FileReader(file);\n" + 
3570
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
3571
		"Instance \'fileReader\' should be managed by try-with-resource.\n" + 
3572
		"----------\n",
3573
		null,
3574
		true,
3575
		options);
3576
}
3577
// Bug 349326 - [1.7] new warning for missing try-with-resources
3578
// an AutoCloseable local is re-assigned
3579
public void test055f() {
3580
	Map options = getCompilerOptions();
3581
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
3582
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.WARNING);
3583
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
3584
	this.runNegativeTest(
3585
		new String[] {
3586
			"X.java",
3587
			"import java.io.File;\n" +
3588
			"import java.io.FileReader;\n" +
3589
			"import java.io.IOException;\n" +
3590
			"public class X {\n" +
3591
			"    void foo() throws IOException {\n" +
3592
			"        File file = new File(\"somefile\");\n" +
3593
			"        FileReader fileReader = new FileReader(file);\n" +
3594
			"        char[] in = new char[50];\n" +
3595
			"        fileReader.read(in);\n" +
3596
			"        fileReader = new FileReader(file);\n" +
3597
			"        fileReader.read(in);\n" +
3598
			"        fileReader.close();\n" +
3599
			"    }\n" +
3600
			"    public static void main(String[] args) throws IOException {\n" +
3601
			"        new X().foo();\n" +
3602
			"    }\n" +
3603
			"}\n"
3604
		},
3605
		"----------\n" + 
3606
		"1. ERROR in X.java (at line 10)\n" + 
3607
		"	fileReader = new FileReader(file);\n" + 
3608
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
3609
		"Instance \'fileReader\' of type AutoCloseable is not closed at this point.\n" + 
3610
		"----------\n",
3611
		null,
3612
		true,
3613
		options);
3614
}
3344
public static Class testClass() {
3615
public static Class testClass() {
3345
	return TryWithResourcesStatementTest.class;
3616
	return TryWithResourcesStatementTest.class;
3346
}
3617
}

Return to bug 349326