View | Details | Raw Unified | Return to bug 358903 | Differences between
and this patch

Collapse All | Expand All

(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java (-1 / +94 lines)
Lines 33-39 import junit.framework.Test; Link Here
33
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
33
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
34
34
35
static {
35
static {
36
//	TESTS_NAMES = new String[] { "test061a"};
36
//	TESTS_NAMES = new String[] { "test061m"};
37
//	TESTS_NUMBERS = new int[] { 50 };
37
//	TESTS_NUMBERS = new int[] { 50 };
38
//	TESTS_RANGE = new int[] { 11, -1 };
38
//	TESTS_RANGE = new int[] { 11, -1 };
39
}
39
}
Lines 5911-5916 public void test061l() throws IOException { Link Here
5911
		options,
5911
		options,
5912
		null);
5912
		null);
5913
}
5913
}
5914
// Bug 358903 - Filter practically unimportant resource leak warnings
5915
// a closeable is passed to another method in a return statement
5916
// example constructed after org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository#getArtifact(..)
5917
public void test061m() throws IOException {
5918
	Map options = getCompilerOptions();
5919
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5920
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5921
	this.runNegativeTest(
5922
		new String[] {
5923
			"X.java",
5924
			"import java.io.File;\n" +
5925
			"import java.io.FileInputStream;\n" +
5926
			"import java.io.BufferedInputStream;\n" +
5927
			"import java.io.InputStream;\n" +
5928
			"import java.io.IOException;\n" +
5929
			"public class X {\n" +
5930
			"    BufferedInputStream stream;\n" +
5931
			"    BufferedInputStream foo(File file) throws IOException {\n" +
5932
			"        FileInputStream s = new FileInputStream(file);\n" +
5933
			"        return check(new BufferedInputStream(s));\n" +
5934
			"    }\n" +
5935
			"    BufferedInputStream foo2(FileInputStream s, File file) throws IOException {\n" +
5936
			"        s = new FileInputStream(file);\n" +
5937
			"        return check(s);\n" +
5938
			"    }\n" +
5939
			"    BufferedInputStream foo3(InputStream s) throws IOException {\n" +
5940
			"        s = check(s);\n" +
5941
			"        return check(s);\n" +
5942
			"    }\n" +
5943
			"    BufferedInputStream check(InputStream s) { return null; }\n" +
5944
			"}\n"
5945
		},
5946
		// TODO: also these warnings *might* be avoidable by detecting check(s) as a wrapper creation?? 
5947
		"----------\n" + 
5948
		"1. ERROR in X.java (at line 14)\n" + 
5949
		"	return check(s);\n" + 
5950
		"	^^^^^^^^^^^^^^^^\n" + 
5951
		"Potential resource leak: \'s\' may not be closed at this location\n" + 
5952
		"----------\n" + 
5953
		"2. ERROR in X.java (at line 18)\n" + 
5954
		"	return check(s);\n" + 
5955
		"	^^^^^^^^^^^^^^^^\n" + 
5956
		"Potential resource leak: \'s\' may not be closed at this location\n" + 
5957
		"----------\n",
5958
		null,
5959
		true,
5960
		options);
5961
}
5914
// Bug 362331 - Resource leak not detected when closeable not assigned to variable
5962
// Bug 362331 - Resource leak not detected when closeable not assigned to variable
5915
// a resource is never assigned
5963
// a resource is never assigned
5916
public void test062a() throws IOException {
5964
public void test062a() throws IOException {
Lines 6123-6128 public void test063c() throws IOException { Link Here
6123
		options,
6171
		options,
6124
		null);
6172
		null);
6125
}
6173
}
6174
// Bug 362332 - Only report potential leak when closeable not created in the local scope
6175
// a resource is obtained as a method argument and/or assigned with a cast
6176
public void test063d() throws IOException {
6177
	Map options = getCompilerOptions();
6178
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
6179
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
6180
	options.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
6181
	this.runNegativeTest(
6182
		new String[] {
6183
			"X.java",
6184
			"import java.io.FileInputStream;\n" +
6185
			"import java.io.BufferedInputStream;\n" +
6186
			"import java.io.InputStream;\n" +
6187
			"import java.io.IOException;\n" +
6188
			"public class X {\n" +
6189
			"    void foo( InputStream input) throws IOException {\n" +
6190
			"        FileInputStream input1  = (FileInputStream)input;\n" +
6191
			"        System.out.println(input1.read());\n" +
6192
			"        input.close();\n" + // don't propose t-w-r for argument
6193
			"    }\n" +
6194
			"    void foo() throws IOException {\n" +
6195
			"        InputStream input = new FileInputStream(\"somefile\");\n" + 
6196
			"        FileInputStream input1  = (FileInputStream)input;\n" + 
6197
			"        System.out.println(input1.read());\n" + 
6198
			"        input.close();\n" + // do propose t-w-r, not from a method argument
6199
			"    }\n" +
6200
			"    void foo3( InputStream input, InputStream input2) throws IOException {\n" +
6201
			"        FileInputStream input1  = (FileInputStream)input;\n" + // still don't claim because obtained from outside
6202
			"        System.out.println(input1.read());\n" +
6203
			"        BufferedInputStream bis = new BufferedInputStream(input2);\n" +
6204
			"        System.out.println(bis.read());\n" +
6205
			"    }\n" +
6206
			"}\n"
6207
		},
6208
		"----------\n" + 
6209
		"1. ERROR in X.java (at line 12)\n" + 
6210
		"	InputStream input = new FileInputStream(\"somefile\");\n" + 
6211
		"	            ^^^^^\n" + 
6212
		"Resource \'input\' should be managed by try-with-resource\n" + 
6213
		"----------\n",
6214
		null,
6215
		true,
6216
		options);
6217
	
6218
}
6126
public static Class testClass() {
6219
public static Class testClass() {
6127
	return TryWithResourcesStatementTest.class;
6220
	return TryWithResourcesStatementTest.class;
6128
}
6221
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java (-1 / +1 lines)
Lines 60-66 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl Link Here
60
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
60
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
61
	}
61
	}
62
62
63
	if (FakedTrackingVariable.isAutoCloseable(this.resolvedType))
63
	if (FakedTrackingVariable.isAnyCloseable(this.resolvedType))
64
		FakedTrackingVariable.analyseCloseableAllocation(currentScope, flowInfo, this);
64
		FakedTrackingVariable.analyseCloseableAllocation(currentScope, flowInfo, this);
65
65
66
	// record some dependency information for exception types
66
	// record some dependency information for exception types
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java (-1 / +1 lines)
Lines 51-57 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl Link Here
51
	FlowInfo preInitInfo = null;
51
	FlowInfo preInitInfo = null;
52
	boolean shouldAnalyseResource = local != null 
52
	boolean shouldAnalyseResource = local != null 
53
			&& flowInfo.reachMode() == FlowInfo.REACHABLE 
53
			&& flowInfo.reachMode() == FlowInfo.REACHABLE 
54
			&& (FakedTrackingVariable.isAutoCloseable(this.expression.resolvedType)
54
			&& (FakedTrackingVariable.isAnyCloseable(this.expression.resolvedType)
55
					|| this.expression.resolvedType == TypeBinding.NULL);
55
					|| this.expression.resolvedType == TypeBinding.NULL);
56
	if (shouldAnalyseResource) {
56
	if (shouldAnalyseResource) {
57
		preInitInfo = flowInfo.unconditionalCopy();
57
		preInitInfo = flowInfo.unconditionalCopy();
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java (-17 / +33 lines)
Lines 43-59 public class FakedTrackingVariable extends LocalDeclaration { Link Here
43
	private static final int CLOSE_SEEN = 1;
43
	private static final int CLOSE_SEEN = 1;
44
	// the resource was passed to outside code (arg in method/ctor call or as a return value from this method):
44
	// the resource was passed to outside code (arg in method/ctor call or as a return value from this method):
45
	private static final int PASSED_TO_OUTSIDE = 2;
45
	private static final int PASSED_TO_OUTSIDE = 2;
46
	// the resource was obtained from the outside (argument of the current method, or via a field read)
47
	private static final int OBTAINED_FROM_OUTSIDE = 4;
46
	// If close() is invoked from a nested method (inside a local type) report remaining problems only as potential:
48
	// If close() is invoked from a nested method (inside a local type) report remaining problems only as potential:
47
	private static final int CLOSED_IN_NESTED_METHOD = 4;
49
	private static final int CLOSED_IN_NESTED_METHOD = 8;
48
	// a location independent issue has been reported already against this resource:
50
	// a location independent issue has been reported already against this resource:
49
	private static final int REPORTED = 8;
51
	private static final int REPORTED = 16;
50
	// a resource is wrapped in another resource:
52
	// a resource is wrapped in another resource:
51
	private static final int WRAPPED = 16;
53
	private static final int WRAPPED = 32;
52
54
53
	private static final int DOUBT_MASK = CLOSE_SEEN | PASSED_TO_OUTSIDE | CLOSED_IN_NESTED_METHOD | REPORTED; // not WRAPPED
55
	private static final int DOUBT_MASK = CLOSE_SEEN | PASSED_TO_OUTSIDE | OBTAINED_FROM_OUTSIDE | CLOSED_IN_NESTED_METHOD | REPORTED; // not WRAPPED
54
56
55
	/**
57
	/**
56
	 * Bitset of {@link #CLOSE_SEEN}, {@link #PASSED_TO_OUTSIDE}, {@link #CLOSED_IN_NESTED_METHOD}, {@link #REPORTED} and {@link #WRAPPED}.
58
	 * Bitset of {@link #CLOSE_SEEN}, {@link #PASSED_TO_OUTSIDE}, {@link #OBTAINED_FROM_OUTSIDE}, {@link #CLOSED_IN_NESTED_METHOD}, {@link #REPORTED} and {@link #WRAPPED}.
57
	 */
59
	 */
58
	private int globalClosingState = 0;
60
	private int globalClosingState = 0;
59
61
Lines 116-133 public class FakedTrackingVariable extends LocalDeclaration { Link Here
116
	 * @return a new {@link FakedTrackingVariable} or null.
118
	 * @return a new {@link FakedTrackingVariable} or null.
117
	 */
119
	 */
118
	public static FakedTrackingVariable getCloseTrackingVariable(Expression expression) {
120
	public static FakedTrackingVariable getCloseTrackingVariable(Expression expression) {
121
		while (true) {
122
			if (expression instanceof CastExpression)
123
				expression = ((CastExpression) expression).expression;
124
			else if (expression instanceof Assignment)
125
				expression = ((Assignment) expression).expression;
126
			else
127
				break;
128
		}
119
		if (expression instanceof SingleNameReference) {
129
		if (expression instanceof SingleNameReference) {
120
			SingleNameReference name = (SingleNameReference) expression;
130
			SingleNameReference name = (SingleNameReference) expression;
121
			if (name.binding instanceof LocalVariableBinding) {
131
			if (name.binding instanceof LocalVariableBinding) {
122
				LocalVariableBinding local = (LocalVariableBinding)name.binding;
132
				LocalVariableBinding local = (LocalVariableBinding)name.binding;
123
				if (local.closeTracker != null)
133
				if (local.closeTracker != null)
124
					return local.closeTracker;
134
					return local.closeTracker;
125
				if (local.isParameter() || !isAutoCloseable(expression.resolvedType))
135
				if (!isAnyCloseable(expression.resolvedType))
126
					return null;
136
					return null;
127
				// tracking var doesn't yet exist. This happens in finally block
137
				// tracking var doesn't yet exist. This happens in finally block
128
				// which is analyzed before the corresponding try block
138
				// which is analyzed before the corresponding try block
129
				Statement location = local.declaration;
139
				Statement location = local.declaration;
130
				return local.closeTracker = new FakedTrackingVariable(local, location);
140
				local.closeTracker = new FakedTrackingVariable(local, location);
141
				if (local.isParameter()) {
142
					local.closeTracker.globalClosingState |= OBTAINED_FROM_OUTSIDE;
143
					// status of this tracker is now UNKNOWN
144
				}
145
				return local.closeTracker;
131
			}
146
			}
132
		} else if (expression instanceof AllocationExpression) {
147
		} else if (expression instanceof AllocationExpression) {
133
			// return any preliminary tracking variable from analyseCloseableAllocation 
148
			// return any preliminary tracking variable from analyseCloseableAllocation 
Lines 152-158 public class FakedTrackingVariable extends LocalDeclaration { Link Here
152
		if (rhs instanceof AllocationExpression) {
167
		if (rhs instanceof AllocationExpression) {
153
			closeTracker = local.closeTracker;
168
			closeTracker = local.closeTracker;
154
			if (closeTracker == null) {
169
			if (closeTracker == null) {
155
				if (isAutoCloseable(rhs.resolvedType)) {
170
				if (isAnyCloseable(rhs.resolvedType)) {
156
					closeTracker = new FakedTrackingVariable(local, location);
171
					closeTracker = new FakedTrackingVariable(local, location);
157
				}					
172
				}					
158
			}
173
			}
Lines 178-184 public class FakedTrackingVariable extends LocalDeclaration { Link Here
178
		} else if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable)) {
193
		} else if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable)) {
179
			if (allocation.arguments != null &&  allocation.arguments.length > 0) {
194
			if (allocation.arguments != null &&  allocation.arguments.length > 0) {
180
				// find the wrapped resource represented by its tracking var:
195
				// find the wrapped resource represented by its tracking var:
181
				FakedTrackingVariable innerTracker = analyseCloseableAllocationArgument(scope, flowInfo, allocation, allocation.arguments[0]);
196
				FakedTrackingVariable innerTracker = findCloseTracker(scope, flowInfo, allocation, allocation.arguments[0]);
182
				if (innerTracker != null) {
197
				if (innerTracker != null) {
183
					if (innerTracker == allocation.closeTracker)
198
					if (innerTracker == allocation.closeTracker)
184
						return; // self wrap (res = new Res(res)) -> neither change (here) nor remove (below)
199
						return; // self wrap (res = new Res(res)) -> neither change (here) nor remove (below)
Lines 212-218 public class FakedTrackingVariable extends LocalDeclaration { Link Here
212
	}
227
	}
213
228
214
	/** Find an existing tracking variable for the argument of an allocation for a resource wrapper. */
229
	/** Find an existing tracking variable for the argument of an allocation for a resource wrapper. */
215
	public static FakedTrackingVariable analyseCloseableAllocationArgument(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation, Expression arg)
230
	private static FakedTrackingVariable findCloseTracker(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation, Expression arg)
216
	{
231
	{
217
		while (arg instanceof Assignment) {
232
		while (arg instanceof Assignment) {
218
			Assignment assign = (Assignment)arg;
233
			Assignment assign = (Assignment)arg;
Lines 276-289 public class FakedTrackingVariable extends LocalDeclaration { Link Here
276
				// keep close-status of RHS unchanged across this assignment
291
				// keep close-status of RHS unchanged across this assignment
277
			} else if (previousTracker != null) {					// 2. re-use tracking variable from the LHS?
292
			} else if (previousTracker != null) {					// 2. re-use tracking variable from the LHS?
278
				// re-assigning from a fresh value, mark as not-closed again:
293
				// re-assigning from a fresh value, mark as not-closed again:
279
				flowInfo.markAsDefinitelyNull(previousTracker.binding);
294
				if ((previousTracker.globalClosingState & (PASSED_TO_OUTSIDE|OBTAINED_FROM_OUTSIDE)) == 0)
295
					flowInfo.markAsDefinitelyNull(previousTracker.binding);
280
				local.closeTracker = analyseCloseableExpression(flowInfo, local, location, rhs, previousTracker);
296
				local.closeTracker = analyseCloseableExpression(flowInfo, local, location, rhs, previousTracker);
281
			} else {												// 3. no re-use, create a fresh tracking variable:
297
			} else {												// 3. no re-use, create a fresh tracking variable:
282
				rhsTrackVar = analyseCloseableExpression(flowInfo, local, location, rhs, null);
298
				rhsTrackVar = analyseCloseableExpression(flowInfo, local, location, rhs, null);
283
				if (rhsTrackVar != null) {
299
				if (rhsTrackVar != null) {
284
					local.closeTracker = rhsTrackVar;
300
					local.closeTracker = rhsTrackVar;
285
					// a fresh resource, mark as not-closed:
301
					// a fresh resource, mark as not-closed:
286
					if ((rhsTrackVar.globalClosingState & PASSED_TO_OUTSIDE) == 0)
302
					if ((rhsTrackVar.globalClosingState & (PASSED_TO_OUTSIDE|OBTAINED_FROM_OUTSIDE)) == 0)
287
						flowInfo.markAsDefinitelyNull(rhsTrackVar.binding);
303
						flowInfo.markAsDefinitelyNull(rhsTrackVar.binding);
288
// TODO(stephan): this might be useful, but I could not find a test case for it: 
304
// TODO(stephan): this might be useful, but I could not find a test case for it: 
289
//					if (flowContext.initsOnFinally != null)
305
//					if (flowContext.initsOnFinally != null)
Lines 333-347 public class FakedTrackingVariable extends LocalDeclaration { Link Here
333
			// we *might* be responsible for the resource obtained
349
			// we *might* be responsible for the resource obtained
334
			FakedTrackingVariable tracker = new FakedTrackingVariable(local, location);
350
			FakedTrackingVariable tracker = new FakedTrackingVariable(local, location);
335
			tracker.globalClosingState |= PASSED_TO_OUTSIDE;
351
			tracker.globalClosingState |= PASSED_TO_OUTSIDE;
336
			flowInfo.markPotentiallyNullBit(tracker.binding);
352
			flowInfo.markPotentiallyNullBit(tracker.binding); // shed some doubt
337
			return tracker;			
353
			return tracker;			
338
		} else if (expression instanceof FieldReference 
354
		} else if (expression instanceof FieldReference 
339
				|| expression instanceof QualifiedNameReference) 
355
				|| expression instanceof QualifiedNameReference) 
340
		{
356
		{
341
			// responsibility for this resource probably lies at a higher level
357
			// responsibility for this resource probably lies at a higher level
342
			FakedTrackingVariable tracker = new FakedTrackingVariable(local, location);
358
			FakedTrackingVariable tracker = new FakedTrackingVariable(local, location);
343
			tracker.globalClosingState |= PASSED_TO_OUTSIDE;
359
			tracker.globalClosingState |= OBTAINED_FROM_OUTSIDE;
344
			flowInfo.markPotentiallyNonNullBit(tracker.binding);
360
			// leave state as UNKNOWN, the bit OBTAINED_FROM_OUTSIDE will prevent spurious warnings
345
			return tracker;			
361
			return tracker;			
346
		}
362
		}
347
363
Lines 385-391 public class FakedTrackingVariable extends LocalDeclaration { Link Here
385
	}
401
	}
386
402
387
	/** Answer wither the given type binding is a subtype of java.lang.AutoCloseable. */
403
	/** Answer wither the given type binding is a subtype of java.lang.AutoCloseable. */
388
	public static boolean isAutoCloseable(TypeBinding typeBinding) {
404
	public static boolean isAnyCloseable(TypeBinding typeBinding) {
389
		return typeBinding instanceof ReferenceBinding
405
		return typeBinding instanceof ReferenceBinding
390
			&& ((ReferenceBinding)typeBinding).hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable);
406
			&& ((ReferenceBinding)typeBinding).hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable);
391
	}
407
	}
Lines 544-550 public class FakedTrackingVariable extends LocalDeclaration { Link Here
544
	}
560
	}
545
561
546
	public void reportExplicitClosing(ProblemReporter problemReporter) {
562
	public void reportExplicitClosing(ProblemReporter problemReporter) {
547
		if ((this.globalClosingState & REPORTED) == 0) {
563
		if ((this.globalClosingState & (OBTAINED_FROM_OUTSIDE|REPORTED)) == 0) { // can't use t-w-r for OBTAINED_FROM_OUTSIDE
548
			this.globalClosingState |= REPORTED;
564
			this.globalClosingState |= REPORTED;
549
			problemReporter.explicitlyClosedAutoCloseable(this);
565
			problemReporter.explicitlyClosedAutoCloseable(this);
550
		}
566
		}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java (-1 / +1 lines)
Lines 78-84 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl Link Here
78
	FlowInfo preInitInfo = null;
78
	FlowInfo preInitInfo = null;
79
	boolean shouldAnalyseResource = this.binding != null 
79
	boolean shouldAnalyseResource = this.binding != null 
80
			&& flowInfo.reachMode() == FlowInfo.REACHABLE 
80
			&& flowInfo.reachMode() == FlowInfo.REACHABLE 
81
			&& FakedTrackingVariable.isAutoCloseable(this.initialization.resolvedType);
81
			&& FakedTrackingVariable.isAnyCloseable(this.initialization.resolvedType);
82
	if (shouldAnalyseResource) {
82
	if (shouldAnalyseResource) {
83
		preInitInfo = flowInfo.unconditionalCopy();
83
		preInitInfo = flowInfo.unconditionalCopy();
84
		// analysis of resource leaks needs additional context while analyzing the RHS:
84
		// analysis of resource leaks needs additional context while analyzing the RHS:
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java (-2 / +1 lines)
Lines 977-984 public int registerTrackingVariable(FakedTrackingVariable fakedTrackingVariable) Link Here
977
		this.trackingVariables = new ArrayList(3);
977
		this.trackingVariables = new ArrayList(3);
978
	this.trackingVariables.add(fakedTrackingVariable);
978
	this.trackingVariables.add(fakedTrackingVariable);
979
	MethodScope outerMethodScope = outerMostMethodScope();
979
	MethodScope outerMethodScope = outerMostMethodScope();
980
	return outerMethodScope.analysisIndex + (outerMethodScope.trackVarCount++);
980
	return outerMethodScope.analysisIndex++;
981
	
982
}
981
}
983
/** When are no longer interested in this tracking variable - remove it. */
982
/** When are no longer interested in this tracking variable - remove it. */
984
public void removeTrackingVar(FakedTrackingVariable trackingVariable) {
983
public void removeTrackingVar(FakedTrackingVariable trackingVariable) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java (-4 / +1 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 50-58 public class MethodScope extends BlockScope { Link Here
50
	// inner-emulation
50
	// inner-emulation
51
	public SyntheticArgumentBinding[] extraSyntheticArguments;
51
	public SyntheticArgumentBinding[] extraSyntheticArguments;
52
52
53
	// count number of tracking variables, see FakedTrackingVariable
54
	int trackVarCount = 0;
55
56
public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) {
53
public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) {
57
	super(METHOD_SCOPE, parent);
54
	super(METHOD_SCOPE, parent);
58
	this.locals = new LocalVariableBinding[5];
55
	this.locals = new LocalVariableBinding[5];

Return to bug 358903