diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java index b39419e..7c2121e 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java @@ -202,6 +202,7 @@ public class FakedTrackingVariable extends LocalDeclaration { allocation.closeTracker = null; } } else if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable)) { + boolean isWrapper = true; if (allocation.arguments != null && allocation.arguments.length > 0) { // find the wrapped resource represented by its tracking var: FakedTrackingVariable innerTracker = findCloseTracker(scope, flowInfo, allocation, allocation.arguments[0]); @@ -231,28 +232,44 @@ public class FakedTrackingVariable extends LocalDeclaration { currentTracker = currentTracker.innerTracker; } } - return; // keep chaining wrapper + return; // keep chaining wrapper (by avoiding to fall through to removeTrackingVar below) + } else { + if (!isAnyCloseable(allocation.arguments[0].resolvedType)) { + isWrapper = false; // argument is not closeable + } } + } else { + isWrapper = false; // no argument } - // remove unnecessary attempts (wrapper has no relevant inner) - if (allocation.closeTracker != null) { - scope.removeTrackingVar(allocation.closeTracker); - allocation.closeTracker = null; - } - } else { // regular resource - FakedTrackingVariable presetTracker = allocation.closeTracker; - if (presetTracker != null && presetTracker.originalBinding != null) { - int closeStatus = flowInfo.nullStatus(presetTracker.binding); - if (closeStatus != FlowInfo.NON_NULL - && closeStatus != FlowInfo.UNKNOWN - && !flowInfo.isDefinitelyNull(presetTracker.originalBinding) - && !(presetTracker.currentAssignment instanceof LocalDeclaration)) - allocation.closeTracker.recordErrorLocation(presetTracker.currentAssignment, closeStatus); + // successful wrapper detection has exited above, let's see why that failed + if (isWrapper) { + // remove unnecessary attempts (wrapper has no relevant inner) + if (allocation.closeTracker != null) { + scope.removeTrackingVar(allocation.closeTracker); + allocation.closeTracker = null; + } } else { - allocation.closeTracker = new FakedTrackingVariable(scope, allocation); // no local available, closeable is unassigned + // allocation does not provide a resource as the first argument -> don't treat as a wrapper + handleRegularResource(scope, flowInfo, allocation); } - flowInfo.markAsDefinitelyNull(allocation.closeTracker.binding); + } else { // regular resource + handleRegularResource(scope, flowInfo, allocation); + } + } + + private static void handleRegularResource(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation) { + FakedTrackingVariable presetTracker = allocation.closeTracker; + if (presetTracker != null && presetTracker.originalBinding != null) { + int closeStatus = flowInfo.nullStatus(presetTracker.binding); + if (closeStatus != FlowInfo.NON_NULL + && closeStatus != FlowInfo.UNKNOWN + && !flowInfo.isDefinitelyNull(presetTracker.originalBinding) + && !(presetTracker.currentAssignment instanceof LocalDeclaration)) + allocation.closeTracker.recordErrorLocation(presetTracker.currentAssignment, closeStatus); + } else { + allocation.closeTracker = new FakedTrackingVariable(scope, allocation); // no local available, closeable is unassigned } + flowInfo.markAsDefinitelyNull(allocation.closeTracker.binding); } /** Find an existing tracking variable for the argument of an allocation for a resource wrapper. */