### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/core/compiler/IProblem.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java,v retrieving revision 1.229 diff -u -r1.229 IProblem.java --- compiler/org/eclipse/jdt/core/compiler/IProblem.java 23 Aug 2011 06:03:55 -0000 1.229 +++ compiler/org/eclipse/jdt/core/compiler/IProblem.java 25 Sep 2011 21:11:31 -0000 @@ -116,7 +116,12 @@ * Benjamin Muskalla - added the following constants * MissingSynchronizedModifierInInheritedMethod * Stephan Herrmann - added the following constants - * UnusedObjectAllocation + * UnusedObjectAllocation + * PotentiallyUnclosedCloseable + * PotentiallyUnclosedCloseableAtExit + * UnclosedCloseable + * UnclosedCloseableAtExit + * ExplicitlyClosedAutoCloseable *******************************************************************************/ package org.eclipse.jdt.core.compiler; @@ -1394,6 +1399,16 @@ int DiamondNotBelow17 = TypeRelated + 883; /** @since 3.7.1 */ int RedundantSpecificationOfTypeArguments = TypeRelated + 884; + /** @since 3.8 */ + int PotentiallyUnclosedCloseable = Internal + 885; + /** @since 3.8 */ + int PotentiallyUnclosedCloseableAtExit = Internal + 886; + /** @since 3.8 */ + int UnclosedCloseable = Internal + 887; + /** @since 3.8 */ + int UnclosedCloseableAtExit = Internal + 888; + /** @since 3.8 */ + int ExplicitlyClosedAutoCloseable = Internal + 889; /** * External problems -- These are problems defined by other plugins */ Index: compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java,v retrieving revision 1.87 diff -u -r1.87 AllocationExpression.java --- compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java 28 Jul 2011 17:07:04 -0000 1.87 +++ compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java 25 Sep 2011 21:11:32 -0000 @@ -10,6 +10,7 @@ * Stephan Herrmann - Contributions for * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -42,6 +43,8 @@ // process arguments if (this.arguments != null) { for (int i = 0, count = this.arguments.length; i < count; i++) { + // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.) + flowInfo = FakedTrackingVariable.markPotentialClosing(this.arguments[i], flowInfo); flowInfo = this.arguments[i] .analyseCode(currentScope, flowContext, flowInfo) Index: compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java,v retrieving revision 1.97 diff -u -r1.97 Assignment.java --- compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java 28 Jul 2011 17:07:01 -0000 1.97 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java 25 Sep 2011 21:11:32 -0000 @@ -12,6 +12,7 @@ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 292478 - Report potentially null across variable assignment * bug 335093 - [compiler][null] minimal hook for future null annotation support + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -47,6 +48,27 @@ flowInfo = ((Reference) this.lhs) .analyseAssignment(currentScope, flowContext, flowInfo, this, false) .unconditionalInits(); + if (local != null) { + LocalVariableBinding trackerBinding = null; + if (local.closeTracker != null) { + // Assigning to a variable already holding an AutoCloseable, has it been closed before? + trackerBinding = local.closeTracker.binding; + if (!flowInfo.isDefinitelyNull(local)) { // only if previous value may be non-null + local.closeTracker.recordErrorLocation(this, flowInfo.nullStatus(trackerBinding)); + } + } + if (FakedTrackingVariable.isAutoCloseable(this.expression.resolvedType)) { + // new value is AutoCloseable, start tracking, possibly re-using existing tracker var: + if (trackerBinding == null) { + local.closeTracker = new FakedTrackingVariable(local, this); + trackerBinding = local.closeTracker.binding; + } + flowInfo.markAsDefinitelyNull(trackerBinding); +// TODO(stephan): this might be useful, but I could not find a test case for it: +// if (flowContext.initsOnFinally != null) +// flowContext.initsOnFinally.markAsDefinitelyNonNull(trackerBinding); + } + } int nullStatus = this.expression.nullStatus(flowInfo); if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { if (nullStatus == FlowInfo.NULL) { Index: compiler/org/eclipse/jdt/internal/compiler/ast/Block.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java,v retrieving revision 1.43 diff -u -r1.43 Block.java --- compiler/org/eclipse/jdt/internal/compiler/ast/Block.java 14 Oct 2009 18:08:37 -0000 1.43 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Block.java 25 Sep 2011 21:11:32 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -32,10 +33,12 @@ int complaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED; for (int i = 0, max = this.statements.length; i < max; i++) { Statement stat = this.statements[i]; - if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel)) < Statement.COMPLAINED_UNREACHABLE) { + if ((complaintLevel = stat.complainIfUnreachable(flowInfo, flowContext, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) { flowInfo = stat.analyseCode(this.scope, flowContext, flowInfo); } } + if (this.explicitDeclarations > 0) // if block has its own scope analyze tracking vars now: + this.scope.checkUnclosedCloseables(flowInfo, flowContext, null); return flowInfo; } /** Index: compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java,v retrieving revision 1.101 diff -u -r1.101 ConditionalExpression.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java 12 Aug 2011 20:48:20 -0000 1.101 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java 25 Sep 2011 21:11:34 -0000 @@ -12,6 +12,7 @@ * bug 292478 - Report potentially null across variable assignment * bug 324178 - [null] ConditionalExpression.nullStatus(..) doesn't take into account the analysis of condition itself * bug 354554 - [null] conditional with redundant condition yields weak error message + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -65,7 +66,7 @@ trueFlowInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) { - this.valueIfTrue.complainIfUnreachable(trueFlowInfo, currentScope, initialComplaintLevel); + this.valueIfTrue.complainIfUnreachable(trueFlowInfo, flowContext, currentScope, initialComplaintLevel, false); } } this.trueInitStateIndex = currentScope.methodScope().recordInitializationStates(trueFlowInfo); @@ -78,7 +79,7 @@ falseFlowInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) { - this.valueIfFalse.complainIfUnreachable(falseFlowInfo, currentScope, initialComplaintLevel); + this.valueIfFalse.complainIfUnreachable(falseFlowInfo, flowContext, currentScope, initialComplaintLevel, true); } } this.falseInitStateIndex = currentScope.methodScope().recordInitializationStates(falseFlowInfo); Index: compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java,v retrieving revision 1.115 diff -u -r1.115 ConstructorDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java 25 Apr 2011 22:51:18 -0000 1.115 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java 25 Sep 2011 21:11:35 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for Bug 343713 - [compiler] bogus line number in constructor of inner class in 1.5 compliance + * Stephan Herrmann - Contributions for + * bug 343713 - [compiler] bogus line number in constructor of inner class in 1.5 compliance + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -151,7 +153,7 @@ int complaintLevel = (nonStaticFieldInfoReachMode & FlowInfo.UNREACHABLE) == 0 ? Statement.NOT_COMPLAINED : Statement.COMPLAINED_FAKE_REACHABLE; for (int i = 0, count = this.statements.length; i < count; i++) { Statement stat = this.statements[i]; - if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel)) < Statement.COMPLAINED_UNREACHABLE) { + if ((complaintLevel = stat.complainIfUnreachable(flowInfo, constructorContext, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) { flowInfo = stat.analyseCode(this.scope, constructorContext, flowInfo); } } Index: compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java,v retrieving revision 1.26 diff -u -r1.26 EmptyStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java 7 Mar 2009 01:08:07 -0000 1.26 +++ compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java 25 Sep 2011 21:11:35 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -29,12 +30,12 @@ } // Report an error if necessary - public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int complaintLevel) { + public int complainIfUnreachable(FlowInfo flowInfo, FlowContext flowContext, BlockScope scope, int complaintLevel, boolean endOfBlock) { // before 1.4, empty statements are tolerated anywhere if (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_4) { return complaintLevel; } - return super.complainIfUnreachable(flowInfo, scope, complaintLevel); + return super.complainIfUnreachable(flowInfo, flowContext, scope, complaintLevel, endOfBlock); } public void generateCode(BlockScope currentScope, CodeStream codeStream){ Index: compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java =================================================================== RCS file: compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java diff -N compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,166 @@ +/******************************************************************************* + * Copyright (c) 2011 GK Software AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.ast; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.flow.FlowInfo; +import org.eclipse.jdt.internal.compiler.impl.Constant; +import org.eclipse.jdt.internal.compiler.lookup.Binding; +import org.eclipse.jdt.internal.compiler.lookup.BlockScope; +import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; +import org.eclipse.jdt.internal.compiler.lookup.MethodScope; +import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.Scope; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; +import org.eclipse.jdt.internal.compiler.lookup.TypeIds; +import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; + +/** + * A faked local variable declaration used for keeping track of data flows of a + * special variable. Certain events will be recorded by changing the null info + * for this variable. + * + * See bug 349326 - [1.7] new warning for missing try-with-resources + */ +public class FakedTrackingVariable extends LocalDeclaration { + + /** + * If close() is invoked from a nested method (inside a local type) + * report remaining problems only as potential. + */ + public boolean closedInNestedMethod; + + MethodScope methodScope; // designates the method declaring this variable + + public LocalVariableBinding originalBinding; // the real local being tracked + + HashMap recordedLocations; // initially null, ASTNode -> Integer + + public FakedTrackingVariable(LocalVariableBinding original, Statement location) { + super(original.name, location.sourceStart, location.sourceEnd); + this.type = new SingleTypeReference( + TypeConstants.OBJECT, + ((long)this.sourceStart <<32)+this.sourceEnd); + this.methodScope = original.declaringScope.methodScope(); + this.originalBinding = original; + resolve(original.declaringScope); + } + + public void generateCode(BlockScope currentScope, CodeStream codeStream) + { /* NOP - this variable is completely dummy, ie. for analysis only. */ } + + public void resolve (BlockScope scope) { + // only need the binding, which is used as reference in FlowInfo methods. + this.binding = new LocalVariableBinding( + this.name, + scope.getJavaLangObject(), // dummy, just needs to be a reference type + 0, + false); + this.binding.setConstant(Constant.NotAConstant); + this.binding.useFlag = LocalVariableBinding.USED; + // use a free slot without assigning it: + this.binding.id = scope.registerTrackingVariable(this); + } + + /** + * If expression resolves to a local variable binding of type AutoCloseable, + * answer the variable that tracks closing of that local, creating it if needed. + * @param expression + * @return a new {@link FakedTrackingVariable} or null. + */ + public static FakedTrackingVariable getCloseTrackingVariable(Expression expression) { + if (expression instanceof SingleNameReference) { + SingleNameReference name = (SingleNameReference) expression; + if (name.binding instanceof LocalVariableBinding) { + LocalVariableBinding local = (LocalVariableBinding)name.binding; + if (local.closeTracker != null) + return local.closeTracker; + if (local.isParameter() || !isAutoCloseable(expression.resolvedType)) + return null; + // tracking var doesn't yet exist. This happens in finally block + // which is analyzed before the corresponding try block + Statement location = local.declaration; + return local.closeTracker = new FakedTrackingVariable(local, location); + } + } + return null; + } + + /** if 'invocationSite' is a call to close() that has a registered tracking variable, answer that variable's binding. */ + public static LocalVariableBinding getTrackerForCloseCall(ASTNode invocationSite) { + if (invocationSite instanceof MessageSend) { + MessageSend send = (MessageSend) invocationSite; + if (CharOperation.equals(TypeConstants.CLOSE, send.selector) && send.receiver instanceof SingleNameReference) { + Binding receiverBinding = ((SingleNameReference)send.receiver).binding; + if (receiverBinding instanceof LocalVariableBinding) { + FakedTrackingVariable trackingVariable = ((LocalVariableBinding)receiverBinding).closeTracker; + if (trackingVariable != null) + return trackingVariable.binding; + } + } + } + return null; + } + + public static FlowInfo markPotentialClosing(Expression expression, FlowInfo flowInfo) { + FakedTrackingVariable trackVar = getCloseTrackingVariable(expression); + if (trackVar != null) { + // insert info that the tracked resource *may* be closed (by the target method, i.e.) + FlowInfo infoResourceIsClosed = flowInfo.copy(); + infoResourceIsClosed.markAsDefinitelyNonNull(trackVar.binding); + return FlowInfo.conditional(flowInfo, infoResourceIsClosed); + } + return flowInfo; + } + + /** Answer wither the given type binding is a subtype of java.lang.AutoCloseable. */ + public static boolean isAutoCloseable(TypeBinding typeBinding) { + return typeBinding instanceof ReferenceBinding + && ((ReferenceBinding)typeBinding).hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable); + } + + public void recordErrorLocation(ASTNode location, int nullStatus) { + if (this.recordedLocations == null) + this.recordedLocations = new HashMap(); + this.recordedLocations.put(location, new Integer(nullStatus)); + } + + public boolean reportRecordedErrors(Scope scope) { + boolean hasReported = false; + if (this.recordedLocations != null) { + Iterator locations = this.recordedLocations.entrySet().iterator(); + while (locations.hasNext()) { + Map.Entry entry = (Entry) locations.next(); + reportError(scope.problemReporter(), (ASTNode)entry.getKey(), ((Integer)entry.getValue()).intValue()); + hasReported = true; + } + } + return hasReported; + } + + public void reportError(ProblemReporter problemReporter, ASTNode location, int nullStatus) { + if (nullStatus == FlowInfo.NULL) { + if (this.closedInNestedMethod) + problemReporter.potentiallyUnclosedCloseable(this, location); + else + problemReporter.unclosedCloseable(this, location); + } else if (nullStatus == FlowInfo.POTENTIALLY_NULL) { + problemReporter.potentiallyUnclosedCloseable(this, location); + } + } +} Index: compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java,v retrieving revision 1.71 diff -u -r1.71 ForStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java 5 Mar 2011 17:18:43 -0000 1.71 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java 25 Sep 2011 21:11:37 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * Stephan Herrmann - Contributions for + * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -138,7 +140,7 @@ actionInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } } - if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel) < Statement.COMPLAINED_UNREACHABLE) { + if (this.action.complainIfUnreachable(actionInfo, flowContext, this.scope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) { actionInfo = this.action.analyseCode(this.scope, loopingContext, actionInfo).unconditionalInits(); } Index: compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java,v retrieving revision 1.65 diff -u -r1.65 ForeachStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java 5 Mar 2011 17:18:43 -0000 1.65 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java 25 Sep 2011 21:11:39 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -99,7 +100,7 @@ if (!(this.action == null || (this.action.isEmptyBlock() && currentScope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_3))) { - if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel) < Statement.COMPLAINED_UNREACHABLE) { + if (this.action.complainIfUnreachable(actionInfo, flowContext, this.scope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) { actionInfo = this.action.analyseCode(this.scope, loopingContext, actionInfo).unconditionalCopy(); } Index: compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java,v retrieving revision 1.71 diff -u -r1.71 IfStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java 5 Mar 2011 17:18:43 -0000 1.71 +++ compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java 25 Sep 2011 21:11:39 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * Stephan Herrmann - Contributions for + * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -89,7 +91,7 @@ this.thenInitStateIndex = currentScope.methodScope().recordInitializationStates(thenFlowInfo); if (isConditionOptimizedFalse || ((this.bits & ASTNode.IsThenStatementUnreachable) != 0)) { if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) { - this.thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, initialComplaintLevel); + this.thenStatement.complainIfUnreachable(thenFlowInfo, flowContext, currentScope, initialComplaintLevel, false); } else { // its a known coding pattern which should be tolerated by dead code analysis // according to isKnowDeadCodePattern() @@ -115,7 +117,7 @@ this.elseInitStateIndex = currentScope.methodScope().recordInitializationStates(elseFlowInfo); if (isConditionOptimizedTrue || ((this.bits & ASTNode.IsElseStatementUnreachable) != 0)) { if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) { - this.elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, initialComplaintLevel); + this.elseStatement.complainIfUnreachable(elseFlowInfo, flowContext, currentScope, initialComplaintLevel, false); } else { // its a known coding pattern which should be tolerated by dead code analysis // according to isKnowDeadCodePattern() @@ -124,6 +126,8 @@ } elseFlowInfo = this.elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo); } + // process AutoCloseable resources closed in only one branch: + currentScope.correlateTrackingVarsIfElse(thenFlowInfo, elseFlowInfo); // merge THEN & ELSE initializations FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranchesIfElse( thenFlowInfo, Index: compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java,v retrieving revision 1.80 diff -u -r1.80 LocalDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java 8 Mar 2011 16:46:01 -0000 1.80 +++ compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java 25 Sep 2011 21:11:39 -0000 @@ -11,6 +11,7 @@ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 292478 - Report potentially null across variable assignment * bug 335093 - [compiler][null] minimal hook for future null annotation support + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -76,6 +77,13 @@ this.initialization .analyseCode(currentScope, flowContext, flowInfo) .unconditionalInits(); + if (FakedTrackingVariable.isAutoCloseable(this.initialization.resolvedType)) { + this.binding.closeTracker = new FakedTrackingVariable(this.binding, this); + flowInfo.markAsDefinitelyNull(this.binding.closeTracker.binding); +// TODO(stephan): this might be useful, but I could not find a test case for it: +// if (flowContext.initsOnFinally != null) +// flowContext.initsOnFinally.markAsDefinitelyNonNull(this.binding.closeTracker.binding); + } int nullStatus = this.initialization.nullStatus(flowInfo); if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes this.bits |= FirstAssignmentToLocal; Index: compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java,v retrieving revision 1.153 diff -u -r1.153 MessageSend.java --- compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 28 Jul 2011 17:07:01 -0000 1.153 +++ compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 25 Sep 2011 21:11:40 -0000 @@ -8,7 +8,9 @@ * Contributors: * IBM Corporation - initial API and implementation * Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752) - * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * Stephan Herrmann - Contributions for + * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -38,6 +40,7 @@ import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; @@ -60,6 +63,21 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { boolean nonStatic = !this.binding.isStatic(); flowInfo = this.receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits(); + // recording the closing of AutoCloseable resources: + if (CharOperation.equals(TypeConstants.CLOSE, this.selector)) + { + FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.receiver); + if (trackingVariable != null) { // null happens if receiver is not a local variable or not an AutoCloseable + if (trackingVariable.methodScope == currentScope.methodScope()) { + flowInfo.markAsDefinitelyNonNull(trackingVariable.binding); +// TODO(stephan): this might be useful, but I could not find a test case for it: +// if (flowContext.initsOnFinally != null) +// flowContext.initsOnFinally.markAsDefinitelyNonNull(trackingVariable.binding); + } else { + trackingVariable.closedInNestedMethod = true; + } + } + } if (nonStatic) { this.receiver.checkNPE(currentScope, flowContext, flowInfo); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682 @@ -80,6 +98,8 @@ if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) { this.arguments[i].checkNPE(currentScope, flowContext, flowInfo); } + // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.) + flowInfo = FakedTrackingVariable.markPotentialClosing(this.arguments[i], flowInfo); flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); } } Index: compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java,v retrieving revision 1.80 diff -u -r1.80 MethodDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java 5 Mar 2011 17:18:43 -0000 1.80 +++ compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java 25 Sep 2011 21:11:41 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -100,7 +101,7 @@ int complaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) == 0 ? Statement.NOT_COMPLAINED : Statement.COMPLAINED_FAKE_REACHABLE; for (int i = 0, count = this.statements.length; i < count; i++) { Statement stat = this.statements[i]; - if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel)) < Statement.COMPLAINED_UNREACHABLE) { + if ((complaintLevel = stat.complainIfUnreachable(flowInfo, methodContext, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) { flowInfo = stat.analyseCode(this.scope, methodContext, flowInfo); } } @@ -134,6 +135,7 @@ } } + this.scope.checkUnclosedCloseables(flowInfo, methodContext, null/*don't report against a specific location*/); } catch (AbortMethod e) { this.ignoreFurtherInvestigation = true; } Index: compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java,v retrieving revision 1.103 diff -u -r1.103 QualifiedAllocationExpression.java --- compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java 28 Jul 2011 17:07:04 -0000 1.103 +++ compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java 25 Sep 2011 21:11:41 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * Stephan Herrmann - Contributions for + * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -72,6 +74,8 @@ // process arguments if (this.arguments != null) { for (int i = 0, count = this.arguments.length; i < count; i++) { + // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.) + flowInfo = FakedTrackingVariable.markPotentialClosing(this.arguments[i], flowInfo); flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo); if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) { this.arguments[i].checkNPE(currentScope, flowContext, flowInfo); Index: compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java,v retrieving revision 1.71 diff -u -r1.71 ReturnStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java 27 Apr 2011 15:44:15 -0000 1.71 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java 25 Sep 2011 21:11:43 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * Stephan Herrmann - Contributions for + * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -40,6 +42,12 @@ if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) { this.expression.checkNPE(currentScope, flowContext, flowInfo); } + FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.expression); + if (trackingVariable != null) { + // don't report issues concerning this local, since by returning + // the method passes the responsibility to the caller: + currentScope.removeTrackingVar(trackingVariable); + } } this.initStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); @@ -104,6 +112,7 @@ this.expression.bits |= ASTNode.IsReturnedValue; } } + currentScope.checkUnclosedCloseables(flowInfo, null/*ignore exception exits from flowContext*/, this); return FlowInfo.DEAD_END; } Index: compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java,v retrieving revision 1.53 diff -u -r1.53 Statement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java 28 Jul 2011 17:07:04 -0000 1.53 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java 25 Sep 2011 21:11:43 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 335093 - [compiler][null] minimal hook for future null annotation support + * Stephan Herrmann - Contributions for + * bug 335093 - [compiler][null] minimal hook for future null annotation support + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -70,18 +72,22 @@ // Report an error if necessary (if even more unreachable than previously reported // complaintLevel = 0 if was reachable up until now, 1 if fake reachable (deadcode), 2 if fatal unreachable (error) -public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int previousComplaintLevel) { +public int complainIfUnreachable(FlowInfo flowInfo, FlowContext flowContext, BlockScope scope, int previousComplaintLevel, boolean endOfBlock) { if ((flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0) { if ((flowInfo.reachMode() & FlowInfo.UNREACHABLE_OR_DEAD) != 0) this.bits &= ~ASTNode.IsReachable; if (flowInfo == FlowInfo.DEAD_END) { if (previousComplaintLevel < COMPLAINED_UNREACHABLE) { scope.problemReporter().unreachableCode(this); + if (endOfBlock) + scope.checkUnclosedCloseables(flowInfo, flowContext, null); } return COMPLAINED_UNREACHABLE; } else { if (previousComplaintLevel < COMPLAINED_FAKE_REACHABLE) { scope.problemReporter().fakeReachable(this); + if (endOfBlock) + scope.checkUnclosedCloseables(flowInfo, flowContext, null); } return COMPLAINED_FAKE_REACHABLE; } Index: compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java,v retrieving revision 1.82 diff -u -r1.82 SwitchStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java 1 Sep 2011 18:42:40 -0000 1.82 +++ compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java 25 Sep 2011 21:11:44 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * Stephan Herrmann - Contributions for + * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -99,7 +101,7 @@ } else { fallThroughState = FALLTHROUGH; // reset below if needed } - if ((complaintLevel = statement.complainIfUnreachable(caseInits, this.scope, complaintLevel)) < Statement.COMPLAINED_UNREACHABLE) { + if ((complaintLevel = statement.complainIfUnreachable(caseInits, flowContext, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) { caseInits = statement.analyseCode(this.scope, switchContext, caseInits); if (caseInits == FlowInfo.DEAD_END) { fallThroughState = ESCAPING; Index: compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java,v retrieving revision 1.121 diff -u -r1.121 TryStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java 18 Aug 2011 17:07:34 -0000 1.121 +++ compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java 25 Sep 2011 21:11:45 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 332637 - Dead Code detection removing code that isn't dead + * Stephan Herrmann - Contributions for + * bug 332637 - Dead Code detection removing code that isn't dead + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -124,8 +126,14 @@ for (int i = 0; i < resourcesLength; i++) { flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy()); this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(flowInfo); - this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. - TypeBinding type = this.resources[i].binding.type; + LocalVariableBinding resourceBinding = this.resources[i].binding; + resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. + if (resourceBinding.closeTracker != null) { + // this was false alarm, we don't need to track the resource + this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker); + resourceBinding.closeTracker = null; + } + TypeBinding type = resourceBinding.type; if (type != null && type.isValidBinding()) { ReferenceBinding binding = (ReferenceBinding) type; MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter @@ -250,8 +258,14 @@ for (int i = 0; i < resourcesLength; i++) { flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy()); this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(flowInfo); - this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. - TypeBinding type = this.resources[i].binding.type; + LocalVariableBinding resourceBinding = this.resources[i].binding; + resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. + if (resourceBinding.closeTracker != null) { + // this was false alarm, we don't need to track the resource + this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker); + resourceBinding.closeTracker = null; + } + TypeBinding type = resourceBinding.type; if (type != null && type.isValidBinding()) { ReferenceBinding binding = (ReferenceBinding) type; MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter Index: compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java,v retrieving revision 1.68 diff -u -r1.68 WhileStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java 5 Mar 2011 17:18:43 -0000 1.68 +++ compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java 25 Sep 2011 21:11:47 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * Stephan Herrmann - Contributions for + * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -113,7 +115,7 @@ currentScope.methodScope().recordInitializationStates( condInfo.initsWhenTrue()); - if (this.action.complainIfUnreachable(actionInfo, currentScope, initialComplaintLevel) < Statement.COMPLAINED_UNREACHABLE) { + if (this.action.complainIfUnreachable(actionInfo, flowContext, currentScope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) { actionInfo = this.action.analyseCode(currentScope, loopingContext, actionInfo); } Index: compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java,v retrieving revision 1.75 diff -u -r1.75 UnconditionalFlowInfo.java --- compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java 12 Apr 2011 05:27:06 -0000 1.75 +++ compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java 25 Sep 2011 21:11:52 -0000 @@ -13,6 +13,7 @@ * bug 292478 - Report potentially null across variable assignment * bug 332637 - Dead Code detection removing code that isn't dead * bug 341499 - [compiler][null] allocate extra bits in all methods of UnconditionalFlowInfo + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; @@ -770,7 +771,7 @@ } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) - >= this.extra[0].length) { + >= this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[2][vectorIndex] & this.extra[4][vectorIndex] @@ -797,7 +798,7 @@ } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= - this.extra[0].length) { + this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[2][vectorIndex] & this.extra[3][vectorIndex] @@ -822,7 +823,7 @@ } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= - this.extra[0].length) { + this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[2][vectorIndex] & this.extra[5][vectorIndex] @@ -882,7 +883,7 @@ } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= - this.extra[0].length) { + this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[4][vectorIndex] @@ -908,7 +909,7 @@ } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= - this.extra[0].length) { + this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[3][vectorIndex] @@ -934,7 +935,7 @@ } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= - this.extra[0].length) { + this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return (this.extra[5][vectorIndex] Index: compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java,v retrieving revision 1.245 diff -u -r1.245 CompilerOptions.java --- compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java 28 Jul 2011 17:07:39 -0000 1.245 +++ compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java 25 Sep 2011 21:11:56 -0000 @@ -8,8 +8,10 @@ * Contributors: * IBM Corporation - initial API and implementation * Benjamin Muskalla - Contribution for bug 239066 - * Stephan Herrmann - Contribution for bug 236385 - * Stephan Herrmann - Contribution for bug 295551 + * Stephan Herrmann - Contributions for + * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used + * bug 295551 - Add option to automatically promote all warnings to errors + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; @@ -137,6 +139,9 @@ public static final String OPTION_ReportMethodCanBeStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic"; //$NON-NLS-1$ public static final String OPTION_ReportMethodCanBePotentiallyStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic"; //$NON-NLS-1$ public static final String OPTION_ReportRedundantSpecificationOfTypeArguments = "org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments"; //$NON-NLS-1$ + public static final String OPTION_ReportUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.unclosedCloseable"; //$NON-NLS-1$ + public static final String OPTION_ReportPotentiallyUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable"; //$NON-NLS-1$ + public static final String OPTION_ReportExplicitlyClosedAutoCloseable = "org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$ /** * Possible values for configurable options */ @@ -240,6 +245,10 @@ public static final int MethodCanBeStatic = IrritantSet.GROUP2 | ASTNode.Bit5; public static final int MethodCanBePotentiallyStatic = IrritantSet.GROUP2 | ASTNode.Bit6; public static final int RedundantSpecificationOfTypeArguments = IrritantSet.GROUP2 | ASTNode.Bit7; + // bits 8-10 reserved for https://bugs.eclipse.org/bugs/show_bug.cgi?id=186342 + public static final int UnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit11; + public static final int PotentiallyUnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit12; + public static final int ExplicitlyClosedAutoCloseable = IrritantSet.GROUP2 | ASTNode.Bit13; // Severity level for handlers /** @@ -376,8 +385,9 @@ "javadoc", //$NON-NLS-1$ "nls", //$NON-NLS-1$ "null", //$NON-NLS-1$ - "restriction", //$NON-NLS-1$ "rawtypes", //$NON-NLS-1$ + "resource", //$NON-NLS-1$ + "restriction", //$NON-NLS-1$ "serial", //$NON-NLS-1$ "static-access", //$NON-NLS-1$ "static-method", //$NON-NLS-1$ @@ -551,6 +561,12 @@ return OPTION_ReportMethodCanBePotentiallyStatic; case RedundantSpecificationOfTypeArguments : return OPTION_ReportRedundantSpecificationOfTypeArguments; + case UnclosedCloseable : + return OPTION_ReportUnclosedCloseable; + case PotentiallyUnclosedCloseable : + return OPTION_ReportPotentiallyUnclosedCloseable; + case ExplicitlyClosedAutoCloseable : + return OPTION_ReportExplicitlyClosedAutoCloseable; } return null; } @@ -714,6 +730,9 @@ OPTION_ReportUnusedTypeArgumentsForMethodInvocation, OPTION_ReportUnusedWarningToken, OPTION_ReportVarargsArgumentNeedCast, + OPTION_ReportUnclosedCloseable, + OPTION_ReportPotentiallyUnclosedCloseable, + OPTION_ReportExplicitlyClosedAutoCloseable, }; return result; } @@ -784,10 +803,14 @@ case MethodCanBeStatic : case MethodCanBePotentiallyStatic : return "static-method"; //$NON-NLS-1$ + case PotentiallyUnclosedCloseable: + case UnclosedCloseable: + case ExplicitlyClosedAutoCloseable: + return "resource"; //$NON-NLS-1$ case InvalidJavadoc : case MissingJavadocComments : case MissingJavadocTags: - return "javadoc"; //$NON-NLS-1$ + return "javadoc"; //$NON-NLS-1$ } return null; } @@ -841,6 +864,8 @@ case 'r' : if ("rawtypes".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.RAW; + if ("resource".equals(warningToken)) //$NON-NLS-1$ + return IrritantSet.RESOURCE; if ("restriction".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.RESTRICTION; break; @@ -980,6 +1005,9 @@ optionsMap.put(OPTION_ReportMethodCanBeStatic, getSeverityString(MethodCanBeStatic)); optionsMap.put(OPTION_ReportMethodCanBePotentiallyStatic, getSeverityString(MethodCanBePotentiallyStatic)); optionsMap.put(OPTION_ReportRedundantSpecificationOfTypeArguments, getSeverityString(RedundantSpecificationOfTypeArguments)); + optionsMap.put(OPTION_ReportUnclosedCloseable, getSeverityString(UnclosedCloseable)); + optionsMap.put(OPTION_ReportPotentiallyUnclosedCloseable, getSeverityString(PotentiallyUnclosedCloseable)); + optionsMap.put(OPTION_ReportExplicitlyClosedAutoCloseable, getSeverityString(ExplicitlyClosedAutoCloseable)); return optionsMap; } @@ -1410,6 +1438,9 @@ if ((optionValue = optionsMap.get(OPTION_ReportMethodCanBeStatic)) != null) updateSeverity(MethodCanBeStatic, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportMethodCanBePotentiallyStatic)) != null) updateSeverity(MethodCanBePotentiallyStatic, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportRedundantSpecificationOfTypeArguments)) != null) updateSeverity(RedundantSpecificationOfTypeArguments, optionValue); + if ((optionValue = optionsMap.get(OPTION_ReportUnclosedCloseable)) != null) updateSeverity(UnclosedCloseable, optionValue); + if ((optionValue = optionsMap.get(OPTION_ReportPotentiallyUnclosedCloseable)) != null) updateSeverity(PotentiallyUnclosedCloseable, optionValue); + if ((optionValue = optionsMap.get(OPTION_ReportExplicitlyClosedAutoCloseable)) != null) updateSeverity(ExplicitlyClosedAutoCloseable, optionValue); // Javadoc options if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) { @@ -1625,6 +1656,9 @@ buf.append("\n\t- method can be static: ").append(getSeverityString(MethodCanBeStatic)); //$NON-NLS-1$ buf.append("\n\t- method can be potentially static: ").append(getSeverityString(MethodCanBePotentiallyStatic)); //$NON-NLS-1$ buf.append("\n\t- redundant specification of type arguments: ").append(getSeverityString(RedundantSpecificationOfTypeArguments)); //$NON-NLS-1$ + buf.append("\n\t- resource is not closed: ").append(getSeverityString(UnclosedCloseable)); //$NON-NLS-1$ + buf.append("\n\t- resource may not be closed: ").append(getSeverityString(PotentiallyUnclosedCloseable)); //$NON-NLS-1$ + buf.append("\n\t- resource should be handled by try-with-resources: ").append(getSeverityString(ExplicitlyClosedAutoCloseable)); //$NON-NLS-1$ return buf.toString(); } Index: compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java,v retrieving revision 1.15 diff -u -r1.15 IrritantSet.java --- compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java 28 Jul 2011 17:07:39 -0000 1.15 +++ compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java 25 Sep 2011 21:11:58 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; @@ -57,6 +58,7 @@ public static final IrritantSet UNUSED = new IrritantSet(CompilerOptions.UnusedLocalVariable); public static final IrritantSet UNCHECKED = new IrritantSet(CompilerOptions.UncheckedTypeOperation); public static final IrritantSet UNQUALIFIED_FIELD_ACCESS = new IrritantSet(CompilerOptions.UnqualifiedFieldAccess); + public static final IrritantSet RESOURCE = new IrritantSet(CompilerOptions.UnclosedCloseable); public static final IrritantSet JAVADOC = new IrritantSet(CompilerOptions.InvalidJavadoc); public static final IrritantSet COMPILER_DEFAULT_ERRORS = new IrritantSet(0); // no optional error by default @@ -99,7 +101,8 @@ // group-2 warnings enabled by default .set( CompilerOptions.DeadCode - |CompilerOptions.Tasks); + |CompilerOptions.Tasks + |CompilerOptions.UnclosedCloseable); ALL.setAll(); HIDING @@ -124,6 +127,9 @@ .set(CompilerOptions.RedundantSpecificationOfTypeArguments); STATIC_METHOD .set(CompilerOptions.MethodCanBePotentiallyStatic); + RESOURCE + .set(CompilerOptions.PotentiallyUnclosedCloseable) + .set(CompilerOptions.ExplicitlyClosedAutoCloseable); String suppressRawWhenUnchecked = System.getProperty("suppressRawWhenUnchecked"); //$NON-NLS-1$ if (suppressRawWhenUnchecked != null && "true".equalsIgnoreCase(suppressRawWhenUnchecked)) { //$NON-NLS-1$ UNCHECKED.set(CompilerOptions.RawTypeReference); Index: compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java,v retrieving revision 1.137 diff -u -r1.137 BinaryTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java 9 Sep 2011 14:13:17 -0000 1.137 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java 25 Sep 2011 21:11:59 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -972,6 +973,12 @@ variable.resolve(); return variable; } +public boolean hasTypeBit(int bit) { + // ensure hierarchy is resolved, which will propagate bits down to us + superclass(); + superInterfaces(); + return (this.typeBits & bit) != 0; +} private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper, char[][][] missingTypeNames) { // ParameterSignature = Identifier ':' TypeSignature // or Identifier ':' TypeSignature(optional) InterfaceBound(s) @@ -1140,8 +1147,14 @@ // finish resolving the type this.superclass = (ReferenceBinding) resolveType(this.superclass, this.environment, true /* raw conversion */); this.tagBits &= ~TagBits.HasUnresolvedSuperclass; - if (this.superclass.problemId() == ProblemReasons.NotFound) + if (this.superclass.problemId() == ProblemReasons.NotFound) { this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency + } else { + // make super-type resolving recursive for propagating typeBits downwards + this.superclass.superclass(); + this.superclass.superInterfaces(); + } + this.typeBits |= this.superclass.typeBits; return this.superclass; } // NOTE: superInterfaces of binary types are resolved when needed @@ -1151,8 +1164,14 @@ for (int i = this.superInterfaces.length; --i >= 0;) { this.superInterfaces[i] = (ReferenceBinding) resolveType(this.superInterfaces[i], this.environment, true /* raw conversion */); - if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound) + if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound) { this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency + } else { + // make super-type resolving recursive for propagating typeBits downwards + this.superInterfaces[i].superclass(); + this.superInterfaces[i].superInterfaces(); + } + this.typeBits |= this.superInterfaces[i].typeBits; } this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces; return this.superInterfaces; Index: compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java,v retrieving revision 1.126 diff -u -r1.126 BlockScope.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java 28 Jul 2011 17:07:22 -0000 1.126 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java 25 Sep 2011 21:12:02 -0000 @@ -7,13 +7,19 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.*; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.flow.FlowContext; +import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; @@ -957,4 +963,140 @@ } } } + +private List trackingVariables; // can be null if no resources are tracked +/** + * Register a tracking variable and compute its id. + */ +public int registerTrackingVariable(FakedTrackingVariable fakedTrackingVariable) { + if (this.trackingVariables == null) + this.trackingVariables = new ArrayList(3); + this.trackingVariables.add(fakedTrackingVariable); + MethodScope outerMethodScope = outerMostMethodScope(); + return outerMethodScope.analysisIndex + (outerMethodScope.trackVarCount++); + +} +/** When no longer interested in this tracking variable remove it. */ +public void removeTrackingVar(FakedTrackingVariable trackingVariable) { + if (this.trackingVariables != null) + if (this.trackingVariables.remove(trackingVariable)) + return; + if (this.parent instanceof BlockScope) + ((BlockScope)this.parent).removeTrackingVar(trackingVariable); +} +/** + * At the end of a block check the closing-status of all tracked closeables that are declared in this block. + * Also invoked when entering unreachable code. + */ +public void checkUnclosedCloseables(FlowInfo flowInfo, FlowContext flowContext, ASTNode location) { + if (this.trackingVariables == null) return; + if (location != null && flowInfo.reachMode() != 0) return; + for (int i=0; i= ClassFileConstants.JDK1_7) + problemReporter().explicitlyClosedAutoCloseable(trackingVar); + } + } +} +private void reportResourceLeak(FakedTrackingVariable trackingVar, ASTNode location, int nullStatus) { + if (location != null) + trackingVar.recordErrorLocation(location, nullStatus); + else + trackingVar.reportError(problemReporter(), null, nullStatus); +} + +/** + * If one branch of an if-else closes any AutoCloseable resource, and if the same + * resource is known to be null on the other branch mark it as closed, too, + * so that merging both branches indicates that the resource is always closed. + * Example: + * FileReader fr1 = null; + * try {\n" + + * fr1 = new FileReader(someFile);" + + * fr1.read(buf);\n" + + * } finally {\n" + + * if (fr1 != null)\n" + + * try {\n" + + * fr1.close();\n" + + * } catch (IOException e) { + * // do nothing + * } + * // after this if statement fr1 is definitely not leaked + * } + */ +public void correlateTrackingVarsIfElse(FlowInfo thenFlowInfo, FlowInfo elseFlowInfo) { + if (this.trackingVariables != null) { + for (int i=0; i always closed + } + else if ( elseFlowInfo.isDefinitelyNonNull(trackingVar.binding) // closed in else branch + && thenFlowInfo.isDefinitelyNull(trackingVar.originalBinding)) // null in then branch + { + thenFlowInfo.markAsDefinitelyNonNull(trackingVar.binding); // -> always closed + } + } + } + if (this.parent instanceof BlockScope) + ((BlockScope) this.parent).correlateTrackingVarsIfElse(thenFlowInfo, elseFlowInfo); +} + +/** + * Get the null status looking even into unreachable flows + * @param local + * @param flowInfo + * @return one of the constants FlowInfo.{NULL,POTENTIALLY_NULL,POTENTIALLY_NON_NULL,NON_NULL}. + */ +private int getNullStatusAggressively(LocalVariableBinding local, FlowInfo flowInfo) { + int reachMode = flowInfo.reachMode(); + int status = 0; + try { + // unreachable flowInfo is too shy in reporting null-issues, temporarily forget reachability: + if (reachMode != FlowInfo.REACHABLE) + flowInfo.tagBits &= ~FlowInfo.UNREACHABLE; + status = flowInfo.nullStatus(local); + } finally { + // reset + flowInfo.tagBits |= reachMode; + } + // at this point some combinations are not useful so flatten to a single bit: + if ((status & FlowInfo.NULL) != 0) { + if ((status & (FlowInfo.NON_NULL | FlowInfo.POTENTIALLY_NON_NULL)) != 0) + return FlowInfo.POTENTIALLY_NULL; // null + doubt = pot null + return FlowInfo.NULL; + } else if ((status & FlowInfo.NON_NULL) != 0) { + if ((status & FlowInfo.POTENTIALLY_NULL) != 0) + return FlowInfo.POTENTIALLY_NULL; // non-null + doubt = pot null + return FlowInfo.NON_NULL; + } else if ((status & FlowInfo.POTENTIALLY_NULL) != 0) + return FlowInfo.POTENTIALLY_NULL; + return status; +} } Index: compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java,v retrieving revision 1.186 diff -u -r1.186 ClassScope.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java 12 Aug 2011 20:40:56 -0000 1.186 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java 25 Sep 2011 21:12:03 -0000 @@ -11,6 +11,7 @@ * Bug 328281 - visibility leaks not detected when analyzing unused field in private class * Bug 300576 - NPE Computing type hierarchy when compliance doesn't match libraries * Bug 354536 - compiling package-info.java still depends on the order of compilation units + * Bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -908,6 +909,7 @@ } else { // only want to reach here when no errors are reported sourceType.superclass = superclass; + sourceType.typeBits |= superclass.typeBits; return true; } } @@ -1023,6 +1025,7 @@ noProblems &= superInterfaceRef.resolvedType.isValidBinding(); } // only want to reach here when no errors are reported + sourceType.typeBits |= superInterface.typeBits; interfaceBindings[count++] = superInterface; } // hold onto all correctly resolved superinterfaces Index: compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java,v retrieving revision 1.50 diff -u -r1.50 LocalVariableBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java 28 Jul 2011 17:07:23 -0000 1.50 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java 25 Sep 2011 21:12:05 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 185682 - Increment/decrement operators mark local variables as read + * Stephan Herrmann - Contributions for + * bug 185682 - Increment/decrement operators mark local variables as read + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -15,6 +17,7 @@ import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.impl.Constant; @@ -35,6 +38,8 @@ public int[] initializationPCs; public int initializationCount = 0; + public FakedTrackingVariable closeTracker; // track closing of instances of type AutoCloseable, maybe null + // for synthetic local variables // if declaration slot is not positionned, the variable will not be listed in attribute // 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) Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java,v retrieving revision 1.79 diff -u -r1.79 MethodScope.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java 8 Mar 2011 16:46:01 -0000 1.79 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java 25 Sep 2011 21:12:05 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -49,6 +50,9 @@ // inner-emulation public SyntheticArgumentBinding[] extraSyntheticArguments; + // count number of tracking variables, see FakedTrackingVariable + int trackVarCount = 0; + public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) { super(METHOD_SCOPE, parent); this.locals = new LocalVariableBinding[5]; Index: compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java,v retrieving revision 1.121 diff -u -r1.121 ParameterizedTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java 23 Aug 2011 17:05:22 -0000 1.121 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java 25 Sep 2011 21:12:07 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -629,6 +630,13 @@ return this.type.hasMemberTypes(); } + public boolean hasTypeBit(int bit) { + TypeBinding erasure = erasure(); + if (erasure instanceof ReferenceBinding) + return ((ReferenceBinding) erasure).hasTypeBit(bit); + return false; + } + /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#implementsMethod(MethodBinding) */ Index: compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java,v retrieving revision 1.22 diff -u -r1.22 ProblemReferenceBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java 27 Jun 2008 16:04:02 -0000 1.22 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java 25 Sep 2011 21:12:07 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -40,6 +41,12 @@ return this.closestMatch; } +public boolean hasTypeBit(int bit) { + if (this.closestMatch != null) + return this.closestMatch.hasTypeBit(bit); + return false; +} + /* API * Answer the problem id associated with the receiver. * NoError if the receiver is a valid binding. Index: compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java,v retrieving revision 1.144 diff -u -r1.144 ReferenceBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java 31 Aug 2011 20:19:50 -0000 1.144 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java 25 Sep 2011 21:12:09 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -41,7 +42,11 @@ private SimpleLookupTable compatibleCache; - public static final ReferenceBinding LUB_GENERIC = new ReferenceBinding() { /* used for lub computation */}; + int typeBits; // additional bits characterizing this type + + public static final ReferenceBinding LUB_GENERIC = new ReferenceBinding() { /* used for lub computation */ + public boolean hasTypeBit(int bit) { return false; } + }; private static final Comparator FIELD_COMPARATOR = new Comparator() { public int compare(Object o1, Object o2) { @@ -392,6 +397,10 @@ case 'i' : if (CharOperation.equals(packageName, TypeConstants.IO)) { switch (typeName[0]) { + case 'C' : + if (CharOperation.equals(typeName, TypeConstants.JAVA_IO_CLOSEABLE[2])) + this.typeBits |= TypeIds.BitCloseable; // don't assign id, only typeBit (for analysis of resource leaks) + return; case 'E' : if (CharOperation.equals(typeName, TypeConstants.JAVA_IO_EXTERNALIZABLE[2])) this.id = TypeIds.T_JavaIoExternalizable; @@ -438,8 +447,10 @@ case 'A' : switch(typeName.length) { case 13 : - if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_AUTOCLOSEABLE[2])) + if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_AUTOCLOSEABLE[2])) { this.id = TypeIds.T_JavaLangAutoCloseable; + this.typeBits |= TypeIds.BitAutoCloseable; + } return; case 14: if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ASSERTIONERROR[2])) @@ -937,6 +948,8 @@ public final boolean hasRestrictedAccess() { return (this.modifiers & ExtraCompilerModifiers.AccRestrictedAccess) != 0; } +/** Answer an additional bit characterizing this type, like {@link TypeIds#BitAutoCloseable}. */ +abstract public boolean hasTypeBit(int bit); /** Answer true if the receiver implements anInterface or is identical to anInterface. * If searchHierarchy is true, then also search the receiver's superclasses. Index: compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java,v retrieving revision 1.192 diff -u -r1.192 SourceTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 18 Aug 2011 10:02:45 -0000 1.192 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 25 Sep 2011 21:12:13 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 328281 - visibility leaks not detected when analyzing unused field in private class + * Stephan Herrmann - Contributions for + * bug 328281 - visibility leaks not detected when analyzing unused field in private class + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -1063,6 +1065,11 @@ return accessors[1]; } +public boolean hasTypeBit(int bit) { + // source types initialize type bits during connectSuperclass/interfaces() + return (this.typeBits & bit) != 0; +} + /** * @see org.eclipse.jdt.internal.compiler.lookup.Binding#initializeDeprecatedAnnotationTagBits() */ Index: compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java,v retrieving revision 1.53 diff -u -r1.53 TypeConstants.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java 31 Aug 2011 20:19:50 -0000 1.53 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java 25 Sep 2011 21:12:13 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -123,6 +124,7 @@ char[][] JAVA_LANG_ANNOTATION_ELEMENTTYPE = {JAVA, LANG, ANNOTATION, "ElementType".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_LANG_REFLECT_FIELD = new char[][] {JAVA, LANG, REFLECT, "Field".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_LANG_REFLECT_METHOD = new char[][] {JAVA, LANG, REFLECT, "Method".toCharArray()}; //$NON-NLS-1$ + char[][] JAVA_IO_CLOSEABLE = new char[][] { JAVA, IO, "Closeable".toCharArray()};//$NON-NLS-1$ char[][] JAVA_IO_OBJECTSTREAMEXCEPTION = new char[][] { JAVA, IO, "ObjectStreamException".toCharArray()};//$NON-NLS-1$ char[][] JAVA_IO_EXTERNALIZABLE = {JAVA, IO, "Externalizable".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_IO_IOEXCEPTION = new char[][] { JAVA, IO, "IOException".toCharArray()};//$NON-NLS-1$ @@ -151,6 +153,7 @@ "MethodHandle$PolymorphicSignature".toCharArray() //$NON-NLS-1$ }; char[][] JAVA_LANG_AUTOCLOSEABLE = {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$ + char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$ // Constraints for generic type argument inference int CONSTRAINT_EQUAL = 0; // Actual = Formal Index: compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java,v retrieving revision 1.40 diff -u -r1.40 TypeIds.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java 31 Aug 2011 20:19:50 -0000 1.40 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java 25 Sep 2011 21:12:13 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -182,4 +183,15 @@ final int Object2boolean = T_JavaLangObject + (T_boolean << 4); final int BOXING = 0x200; final int UNBOXING = 0x400; + + /** + * Marks all sub-types of java.lang.AutoCloseable. + * @see ReferenceBinding#hasTypeBit(int) + */ + final int BitAutoCloseable = 1; + /** + * Marks all sub-types of java.io.Closeable. + * @see ReferenceBinding#hasTypeBit(int) + */ + final int BitCloseable = 2; } Index: compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java,v retrieving revision 1.75 diff -u -r1.75 TypeVariableBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java 25 Oct 2010 08:50:02 -0000 1.75 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java 25 Sep 2011 21:12:14 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac + * Stephan Herrmann - Contributions for + * bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -42,6 +44,7 @@ this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; // treat type var as public this.tagBits |= TagBits.HasTypeVariable; this.environment = environment; + this.typeBits = -1; } /** @@ -307,6 +310,19 @@ return true; } + public boolean hasTypeBit(int bit) { + if (this.typeBits == -1) { + // initialize from bounds + this.typeBits = 0; + if (this.superclass != null) + this.typeBits |= this.superclass.typeBits; + if (this.superInterfaces != null) + for (int i = 0, l = this.superInterfaces.length; i < l; i++) + this.typeBits |= this.superInterfaces[i].typeBits; + } + return (this.typeBits & bit) != 0; + } + /** * Returns true if the type variable is directly bound to a given type */ Index: compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java,v retrieving revision 1.32 diff -u -r1.32 UnresolvedReferenceBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java 27 Jun 2008 16:04:02 -0000 1.32 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java 25 Sep 2011 21:12:14 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -41,6 +42,10 @@ public String debugName() { return toString(); } +public boolean hasTypeBit(int bit) { + // shouldn't happen since we are not called before analyseCode(), but play safe: + return false; +} ReferenceBinding resolve(LookupEnvironment environment, boolean convertGenericToRawType) { ReferenceBinding targetType = this.resolvedType; if (targetType == null) { Index: compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java,v retrieving revision 1.76 diff -u -r1.76 WildcardBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java 24 Jun 2009 18:21:59 -0000 1.76 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java 25 Sep 2011 21:12:16 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2009 IBM Corporation and others. + * Copyright (c) 2005, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -54,6 +55,7 @@ if (bound instanceof UnresolvedReferenceBinding) ((UnresolvedReferenceBinding) bound).addWrapper(this, environment); this.tagBits |= TagBits.HasUnresolvedTypeVariables; // cleared in resolve() + this.typeBits = -1; } public int kind() { @@ -420,6 +422,19 @@ return this.genericType.hashCode(); } + public boolean hasTypeBit(int bit) { + if (this.typeBits == -1) { + // initialize from upper bounds + this.typeBits = 0; + if (this.superclass != null) + this.typeBits |= this.superclass.typeBits; + if (this.superInterfaces != null) + for (int i = 0, l = this.superInterfaces.length; i < l; i++) + this.typeBits |= this.superInterfaces[i].typeBits; + } + return (this.typeBits & bit) != 0; + } + void initialize(ReferenceBinding someGenericType, TypeBinding someBound, TypeBinding[] someOtherBounds) { this.genericType = someGenericType; this.bound = someBound; Index: compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java,v retrieving revision 1.440 diff -u -r1.440 ProblemReporter.java --- compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 31 Aug 2011 20:19:51 -0000 1.440 +++ compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 25 Sep 2011 21:12:28 -0000 @@ -11,6 +11,7 @@ * Stephan Herrmann - Contributions for * bug 236385 - * bug 338303 - Warning about Redundant assignment conflicts with definite assignment + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.problem; @@ -51,6 +52,7 @@ import org.eclipse.jdt.internal.compiler.ast.EqualExpression; import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.eclipse.jdt.internal.compiler.ast.Expression; +import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.ImportReference; @@ -426,6 +428,15 @@ case IProblem.MethodCanBePotentiallyStatic: return CompilerOptions.MethodCanBePotentiallyStatic; + + case IProblem.UnclosedCloseable: + case IProblem.UnclosedCloseableAtExit: + return CompilerOptions.UnclosedCloseable; + case IProblem.PotentiallyUnclosedCloseable: + case IProblem.PotentiallyUnclosedCloseableAtExit: + return CompilerOptions.PotentiallyUnclosedCloseable; + case IProblem.ExplicitlyClosedAutoCloseable: + return CompilerOptions.ExplicitlyClosedAutoCloseable; case IProblem.RedundantSpecificationOfTypeArguments: return CompilerOptions.RedundantSpecificationOfTypeArguments; @@ -461,6 +472,7 @@ case CompilerOptions.ParameterAssignment : case CompilerOptions.MethodCanBeStatic : case CompilerOptions.MethodCanBePotentiallyStatic : + case CompilerOptions.ExplicitlyClosedAutoCloseable : return CategorizedProblem.CAT_CODE_STYLE; case CompilerOptions.MaskedCatchBlock : @@ -482,6 +494,8 @@ case CompilerOptions.ShouldImplementHashcode : case CompilerOptions.DeadCode : case CompilerOptions.UnusedObjectAllocation : + case CompilerOptions.UnclosedCloseable : + case CompilerOptions.PotentiallyUnclosedCloseable : return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM; case CompilerOptions.OverriddenPackageDefaultMethod : @@ -7931,4 +7945,49 @@ location.sourceEnd); } } +public void potentiallyUnclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) { + String[] args = { String.valueOf(trackVar.name) }; + if (location == null) { + this.handle( + IProblem.PotentiallyUnclosedCloseable, + args, + args, + trackVar.sourceStart, + trackVar.sourceEnd); + } else { + this.handle( + IProblem.PotentiallyUnclosedCloseableAtExit, + args, + args, + location.sourceStart, + location.sourceEnd); + } +} +public void unclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) { + String[] args = { String.valueOf(trackVar.name) }; + if (location == null) { + this.handle( + IProblem.UnclosedCloseable, + args, + args, + trackVar.sourceStart, + trackVar.sourceEnd); + } else { + this.handle( + IProblem.UnclosedCloseableAtExit, + args, + args, + location.sourceStart, + location.sourceEnd); + } +} +public void explicitlyClosedAutoCloseable(FakedTrackingVariable trackVar) { + String[] args = { String.valueOf(trackVar.name) }; + this.handle( + IProblem.ExplicitlyClosedAutoCloseable, + args, + args, + trackVar.sourceStart, + trackVar.sourceEnd); +} } \ No newline at end of file Index: compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties,v retrieving revision 1.269 diff -u -r1.269 messages.properties --- compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties 23 Aug 2011 06:03:55 -0000 1.269 +++ compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties 25 Sep 2011 21:12:29 -0000 @@ -8,7 +8,9 @@ # Contributors: # IBM Corporation - initial API and implementation # Benjamin Muskalla - Contribution for bug 239066 -# Stephan Herrmann - Contribution for bug 185682 - Increment/decrement operators mark local variables as read +# Stephan Herrmann - Contributions for +# bug 185682 - Increment/decrement operators mark local variables as read +# bug 349326 - [1.7] new warning for missing try-with-resources ############################################################################### 0 = {0} 1 = super cannot be used in java.lang.Object @@ -644,6 +646,11 @@ 882 = Unhandled exception type {0} thrown by automatic close() invocation on {1} 883 = '<>' operator is not allowed for source level below 1.7 884 = Redundant specification of type arguments <{0}> +885 = Potential resource leak: '{0}' may not be closed +886 = Potential resource leak: '{0}' may not be closed at this location +887 = Resource leak: '{0}' is never closed +888 = Resource leak: '{0}' is not closed at this location +889 = Resource '{0}' should be managed by try-with-resource ### ELABORATIONS ## Access restrictions Index: model/org/eclipse/jdt/core/JavaCore.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java,v retrieving revision 1.665 diff -u -r1.665 JavaCore.java --- model/org/eclipse/jdt/core/JavaCore.java 1 Sep 2011 18:42:40 -0000 1.665 +++ model/org/eclipse/jdt/core/JavaCore.java 25 Sep 2011 21:12:40 -0000 @@ -83,6 +83,10 @@ * Benjamin Muskalla - added COMPILER_PB_MISSING_SYNCHRONIZED_ON_INHERITED_METHOD * Stephan Herrmann - added COMPILER_PB_UNUSED_OBJECT_ALLOCATION * Stephan Herrmann - added COMPILER_PB_SUPPRESS_OPTIONAL_ERRORS + * Stephan Herrmann - added the following constants: + * COMPILER_PB_UNCLOSED_CLOSEABLE, + * COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE + * COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE *******************************************************************************/ package org.eclipse.jdt.core; @@ -1357,6 +1361,52 @@ */ public static final String COMPILER_PB_POTENTIALLY_MISSING_STATIC_ON_METHOD = PLUGIN_ID + ".compiler.problem.reportMethodCanBePotentiallyStatic"; //$NON-NLS-1$ /** + * Compiler option ID: Reporting a resource that is not closed properly. + *

When enabled, that compiler will issue an error or a warning if + * a local variable holds a value of type AutoCloseable and if + * flow analysis shows that the method close() is not invoked locally on that value. + *

+ *
Option id:
"org.eclipse.jdt.core.compiler.problem.reportUnclosedCloseable"
+ *
Possible values:
{ "error", "warning", "ignore" }
+ *
Default:
"warning"
+ *
+ * @since 3.8 + * @category CompilerOptionID + */ + public static final String COMPILER_PB_UNCLOSED_CLOSEABLE = PLUGIN_ID + ".compiler.problem.unclosedCloseable"; //$NON-NLS-1$ + /** + * Compiler option ID: Reporting a resource that may not be closed properly. + *

When enabled, that compiler will issue an error or a warning if + * a local variable holds a value of type AutoCloseable and if + * flow analysis shows that the method close() is + * not invoked locally on that value for all execution paths. + *

+ *
Option id:
"org.eclipse.jdt.core.compiler.problem.reportPotentiallyUnclosedCloseable"
+ *
Possible values:
{ "error", "warning", "ignore" }
+ *
Default:
"ignore"
+ *
+ * @since 3.8 + * @category CompilerOptionID + */ + public static final String COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE = PLUGIN_ID + ".compiler.problem.potentiallyUnclosedCloseable"; //$NON-NLS-1$ + /** + * Compiler option ID: Reporting a resource that is not managed by try-with-resources. + *

When enabled, that compiler will issue an error or a warning if a local variable + * holds a value of type AutoCloseable, and if the method close() is + * explicitly invoked on that resource, but the resource is not managed by a + * try-with-resources block. + *

Note that this option is not intended to be surfaced in the UI, as it is intended + * only for internal use for computing quick assists / cleanups. + *

+ *
Option id:
"org.eclipse.jdt.core.compiler.problem.reportPotentiallyUnclosedCloseable"
+ *
Possible values:
{ "error", "warning", "ignore" }
+ *
Default:
"ignore"
+ *
+ * @since 3.8 + * @category CompilerOptionID + */ + public static final String COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE = PLUGIN_ID + ".compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$ + /** * Compiler option ID: Setting Source Compatibility Mode. *

Specify whether which source level compatibility is used. From 1.4 on, 'assert' is a keyword * reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java,v retrieving revision 1.227 diff -u -r1.227 BatchCompilerTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java 8 Aug 2011 09:51:23 -0000 1.227 +++ src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java 25 Sep 2011 21:13:02 -0000 @@ -8,9 +8,11 @@ * Contributors: * IBM Corporation - initial API and implementation * Benjamin Muskalla - Contribution for bug 239066 - * Stephan Herrmann - Contribution for bug 236385 - * Stephan Herrmann - Contribution for bug 295551 - * Stephan Herrmann - Contribution for bug 185682 - Increment/decrement operators mark local variables as read + * Stephan Herrmann - Contributions for + * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used + * bug 295551 - Add option to automatically promote all warnings to errors + * bug 185682 - Increment/decrement operators mark local variables as read + * bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; @@ -1816,6 +1818,7 @@ "