### 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.228 diff -u -r1.228 IProblem.java --- compiler/org/eclipse/jdt/core/compiler/IProblem.java 28 Jul 2011 17:07:43 -0000 1.228 +++ compiler/org/eclipse/jdt/core/compiler/IProblem.java 12 Aug 2011 23:53:19 -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; @@ -1392,6 +1397,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 12 Aug 2011 23:53:20 -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 12 Aug 2011 23:53:20 -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,34 @@ 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 + if (flowInfo.isDefinitelyNull(trackerBinding)) + currentScope.problemReporter().unclosedCloseable(local.closeTracker, this); + else if (flowInfo.isPotentiallyNull(trackerBinding)) + currentScope.problemReporter().potentiallyUnclosedCloseable(local.closeTracker, this); + } + } + if (FakedTrackingVariable.isAutoCloseable(this.expression.resolvedType)) { + if (local.closeTracker != null && local.closeTracker.isInsideTryWithResources) { + // re-assigning resource of try-with-resources is a different error + } else { + // 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 12 Aug 2011 23:53:20 -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; @@ -36,6 +37,8 @@ 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/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,115 @@ +/******************************************************************************* + * 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 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.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.TypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; +import org.eclipse.jdt.internal.compiler.lookup.TypeIds; + +/** + * 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 resource is already managed by try-with-resources don't complain. */ + public boolean isInsideTryWithResources; + + /** + * If close() is invoked from a nested method (inside a local type) + * report remaining problems only as potential. + */ + public boolean closedInNestedMethod; + + /** If a problem has already been reported don't complain again. */ + public boolean hasReportedProblem; + + MethodScope methodScope; // designates the method declaring this variable + + public LocalVariableBinding originalBinding; // the real local being tracked + + 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; + } + + 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); + } +} 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 12 Aug 2011 23:53:22 -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; @@ -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 12 Aug 2011 23:53:22 -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 12 Aug 2011 23:53:24 -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 12 Aug 2011 23:53:25 -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; @@ -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 12 Aug 2011 23:53:25 -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 12 Aug 2011 23:53:27 -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,13 @@ 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: + flowInfo.markAsDefinitelyNonNull(trackingVariable.binding); + trackingVariable.hasReportedProblem = true; + } } this.initStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); @@ -104,6 +113,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/TryStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java,v retrieving revision 1.120 diff -u -r1.120 TryStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java 28 Jul 2011 17:07:01 -0000 1.120 +++ compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java 12 Aug 2011 23:53:28 -0000 @@ -7,10 +7,15 @@ * * 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; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; @@ -116,8 +121,13 @@ for (int i = 0, max = this.resources.length; i < max; i++) { flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy()); - 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) { + resourceBinding.closeTracker.isInsideTryWithResources = true; + flowInfo.markAsDefinitelyNonNull(resourceBinding.closeTracker.binding); // all is well + } + 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 @@ -241,8 +251,13 @@ for (int i = 0, max = this.resources.length; i < max; i++) { flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy()); - 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) { + resourceBinding.closeTracker.isInsideTryWithResources = true; + flowInfo.markAsDefinitelyNonNull(resourceBinding.closeTracker.binding); // all is well + } + 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 @@ -263,6 +278,13 @@ this.bits |= ASTNode.IsTryBlockExiting; } + // superimpose status for tracking variables: + // don't complain on initsOnException if finally has a better state. + List trackVars = new ArrayList(); + currentScope.getTrackVars(trackVars, subInfo); + if (trackVars.size() > 0) + flowContext.improveNullInfoForExceptionExits(trackVars, subInfo); + // check unreachable catch blocks handlingContext.complainIfUnusedExceptionHandlers(this.scope, this); Index: compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java,v retrieving revision 1.47 diff -u -r1.47 ExceptionHandlingFlowContext.java --- compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java 28 Jul 2011 17:07:43 -0000 1.47 +++ compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java 12 Aug 2011 23:53:29 -0000 @@ -7,22 +7,26 @@ * * 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.flow; import java.util.ArrayList; +import java.util.List; -import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Argument; -import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference; +import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable; import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement; import org.eclipse.jdt.internal.compiler.ast.TryStatement; import org.eclipse.jdt.internal.compiler.ast.TypeReference; +import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference; import org.eclipse.jdt.internal.compiler.codegen.ObjectCache; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.CatchParameterBinding; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; +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; @@ -180,7 +184,14 @@ return node; } - +public int getNullStatusAfter(LocalVariableBinding local, FlowInfo flowInfo) { + // collect info from normal flow and exceptional flows: + int status = flowInfo.nullStatus(local); + if (this.initsOnExceptions != null) + for (int i = 0; i < this.initsOnExceptions.length; i++) + status |= (this.initsOnExceptions[i].nullStatus(local) & (FlowInfo.NULL|FlowInfo.POTENTIALLY_NULL)); + return status; +} public String individualToString() { StringBuffer buffer = new StringBuffer("Exception flow context"); //$NON-NLS-1$ @@ -298,4 +309,31 @@ } return null; } +/** + * {@inheritDoc} + */ +public void improveNullInfoForExceptionExits(List moreTrackVars, FlowInfo otherInfo) { + if (this.initsOnExceptions == null) return; + for (int j = 0; j < this.initsOnExceptions.length; j++) { + UnconditionalFlowInfo copy = null; + for (int i = 0; i < moreTrackVars.size(); i++) { + LocalVariableBinding trackVar = ((FakedTrackingVariable) moreTrackVars.get(i)).binding; + int status = otherInfo.nullStatus(trackVar); + if ((status & FlowInfo.NULL) == 0) { + if ((status & FlowInfo.NON_NULL) != 0) { + this.initsOnExceptions[j].markAsDefinitelyNonNull(trackVar); + } else if ((status & FlowInfo.POTENTIALLY_NON_NULL) != 0) { + if (this.initsOnExceptions[j].isDefinitelyNull(trackVar)) { + // cannot directly set to pot.nn, need to construct and merge infos for this task: + if (copy == null) + copy = this.initsOnExceptions[j].unconditionalCopy(); + copy.markAsDefinitelyNonNull(trackVar); + } + } + } + } + if (copy != null) + this.initsOnExceptions[j] = this.initsOnExceptions[j].mergedWith(copy); + } +} } Index: compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java,v retrieving revision 1.71 diff -u -r1.71 FlowContext.java --- compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java 28 Jul 2011 17:07:43 -0000 1.71 +++ compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java 12 Aug 2011 23:53:31 -0000 @@ -7,13 +7,16 @@ * * 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.flow; import java.util.ArrayList; +import java.util.List; + import org.eclipse.jdt.core.compiler.CharOperation; -import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.LabeledStatement; import org.eclipse.jdt.internal.compiler.ast.Reference; @@ -391,6 +394,14 @@ return null; } +/** + * Answer the combined null status that local will have after this flow context. + * Subclasses will respect break and exception exits. + */ +public int getNullStatusAfter(LocalVariableBinding local, FlowInfo flowInfo) { + return flowInfo.nullStatus(local); +} + /* * lookup through break labels */ @@ -732,4 +743,41 @@ buffer.append(individualToString()).append('\n'); return buffer.toString(); } +/** + * For all tracking variables in the given list improve the null info in initsOnException (if existent) + * with information from the given otherInfo. + */ +public void improveNullInfoForExceptionExits(List moreTrackVars, FlowInfo otherInfo) { + // nothing here, overridden in ExceptionHandlingFlowContext +} + +/** + * Get the null status that local will have after the current point as indicated by flowInfo and flowContext + * @param local + * @param flowInfo + * @param flowContext may be null + * @return a bitset from the constants FlowInfo.{NULL,POTENTIALLY_NULL,POTENTIALLY_NON_NULL,NON_NULL}. + */ +public static int getNullStatusAfter(LocalVariableBinding local, FlowInfo flowInfo, FlowContext flowContext) { + int status = (flowContext != null) + ? flowContext.getNullStatusAfter(local, flowInfo) + : flowInfo.nullStatus(local); + // at this point some combinations are not useful so flatten to a single bit: + return mergeNullStatus(status); +} + +/* Merge the bits NULL, NON_NULL, POTENTIALLY_NULL, POTENTIALLY_NON_NULL to a one-bit answer. */ +private static int mergeNullStatus(int status) { + 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/flow/SwitchFlowContext.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/SwitchFlowContext.java,v retrieving revision 1.33 diff -u -r1.33 SwitchFlowContext.java --- compiler/org/eclipse/jdt/internal/compiler/flow/SwitchFlowContext.java 8 Mar 2011 16:46:01 -0000 1.33 +++ compiler/org/eclipse/jdt/internal/compiler/flow/SwitchFlowContext.java 12 Aug 2011 23:53:31 -0000 @@ -7,11 +7,13 @@ * * 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.flow; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.codegen.BranchLabel; +import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; /** * Reflects the context of code analysis, keeping track of enclosing @@ -31,6 +33,14 @@ return this.breakLabel; } +public int getNullStatusAfter(LocalVariableBinding local, FlowInfo flowInfo) { + // collect info from normal flow and breaks flows: + int status = flowInfo.nullStatus(local); + if (this.initsOnBreak != null) + status |= this.initsOnBreak.nullStatus(local); + return status; +} + public String individualToString() { StringBuffer buffer = new StringBuffer("Switch flow context"); //$NON-NLS-1$ buffer.append("[initsOnBreak -").append(this.initsOnBreak.toString()).append(']'); //$NON-NLS-1$ 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 12 Aug 2011 23:53:33 -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 12 Aug 2011 23:53:38 -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,9 @@ 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; + public static final int UnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit8; + public static final int PotentiallyUnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit9; + public static final int ExplicitlyClosedAutoCloseable = IrritantSet.GROUP2 | ASTNode.Bit10; // Severity level for handlers /** @@ -376,8 +384,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 +560,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 +729,9 @@ OPTION_ReportUnusedTypeArgumentsForMethodInvocation, OPTION_ReportUnusedWarningToken, OPTION_ReportVarargsArgumentNeedCast, + OPTION_ReportUnclosedCloseable, + OPTION_ReportPotentiallyUnclosedCloseable, + OPTION_ReportExplicitlyClosedAutoCloseable, }; return result; } @@ -784,10 +802,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 +863,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 +1004,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 +1437,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 +1655,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 12 Aug 2011 23:53:38 -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.136 diff -u -r1.136 BinaryTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java 17 Jan 2011 13:00:56 -0000 1.136 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java 12 Aug 2011 23:53:40 -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; @@ -971,6 +972,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) @@ -1139,8 +1146,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 @@ -1150,8 +1163,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 12 Aug 2011 23:53:42 -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,99 @@ } } } + +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(); + this.trackingVariables.add(fakedTrackingVariable); + MethodScope outerMethodScope = outerMostMethodScope(); + return outerMethodScope.analysisIndex + (++outerMethodScope.trackVarCount); + +} +/** + * At the end of a block check the closing-status of all tracked closeables that are declared in this block. + */ +public void checkUnclosedCloseables(FlowInfo flowInfo, FlowContext flowContext, ASTNode location) { + if (this.trackingVariables == null) return; + for (int i=0; i= ClassFileConstants.JDK1_7 + && !trackingVar.isInsideTryWithResources) + problemReporter().explicitlyClosedAutoCloseable(trackingVar); + } + } +} +/** + * Find all tracking variables in scope that have relevant null status. + * @param moreTrackVars list for collecting all found tracking variables + * @param flowInfo use to check if tracking variable has interesting status + */ +public void getTrackVars(List moreTrackVars, FlowInfo flowInfo) { + 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); +} } 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 12 Aug 2011 23:53:44 -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 12 Aug 2011 23:53:44 -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 12 Aug 2011 23:53:46 -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; + 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.120 diff -u -r1.120 ParameterizedTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java 23 Dec 2010 13:57:49 -0000 1.120 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java 12 Aug 2011 23:53:47 -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 12 Aug 2011 23:53:47 -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.143 diff -u -r1.143 ReferenceBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java 28 Jul 2011 17:07:23 -0000 1.143 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java 12 Aug 2011 23:53:50 -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) { @@ -424,8 +429,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])) @@ -923,6 +930,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.191 diff -u -r1.191 SourceTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 9 Aug 2011 13:06:23 -0000 1.191 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 12 Aug 2011 23:53:53 -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.52 diff -u -r1.52 TypeConstants.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java 28 Jul 2011 17:07:23 -0000 1.52 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java 12 Aug 2011 23:53:54 -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; @@ -150,6 +151,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.39 diff -u -r1.39 TypeIds.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java 1 Aug 2011 05:37:22 -0000 1.39 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java 12 Aug 2011 23:53:54 -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; @@ -177,4 +178,10 @@ 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; } 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 12 Aug 2011 23:53:54 -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 12 Aug 2011 23:53:54 -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 12 Aug 2011 23:53:55 -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.438 diff -u -r1.438 ProblemReporter.java --- compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 9 Aug 2011 13:06:23 -0000 1.438 +++ compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 12 Aug 2011 23:54:09 -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 : @@ -7906,4 +7920,51 @@ 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); + } + trackVar.hasReportedProblem = true; +} +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); + } + trackVar.hasReportedProblem = true; +} +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.268 diff -u -r1.268 messages.properties --- compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties 9 Aug 2011 14:32:41 -0000 1.268 +++ compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties 12 Aug 2011 23:54:11 -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 @@ -643,6 +645,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 = Potentially leaking resource '{0}': is not closed on all paths +886 = Potentially leaking resource '{0}': may not be closed at this location +887 = Leaking resource '{0}': is never closed +888 = Leaking resource '{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.664 diff -u -r1.664 JavaCore.java --- model/org/eclipse/jdt/core/JavaCore.java 28 Jul 2011 17:07:48 -0000 1.664 +++ model/org/eclipse/jdt/core/JavaCore.java 12 Aug 2011 23:54:21 -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 12 Aug 2011 23:54:42 -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 @@ "