Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (c) 2000, 2013 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 http://www.eclipse.org/legal/epl-v10.html Contributors: IBM Corporation - initial API and implementation Stephan Herrmann - Contributions for bug 349326 - [1.7] new warning for missing try-with-resources bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points bug 358903 - Filter practically unimportant resource leak warnings bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK bug 370639 - [compiler][resource] restore the default for resource leak warnings bug 388996 - [compiler][resource] Incorrect 'potential resource leak' bug 379784 - [compiler] "Method can be static" is not getting reported bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional Jesper S Moller <jesper@selskabet.org> - Contributions for bug 378674 - "The method can be declared as static" is wrong Keigo Imai - Contribution for bug 388903 - Cannot extend inner class as an anonymous class when it extends the outer class /
  
  package org.eclipse.jdt.internal.compiler.lookup;
  
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  
  
  public class BlockScope extends Scope {
  
  	// Local variable management
  	public int localIndex// position for next variable
  	public int startIndex;	// start position in this scope - for ordering scopes vs. variables
  	public int offset// for variable allocation throughout scopes
  	public int maxOffset// for variable allocation throughout scopes
  
  	// finally scopes must be shifted behind respective try&catch scope(s) so as to avoid
  	// collisions of secret variables (return address, save value).
  	public BlockScope[] shiftScopes;
  
  	public Scope[] subscopes = new Scope[1]; // need access from code assist
  	public int subscopeCount = 0; // need access from code assist
  	// record the current case statement being processed (for entire switch case block).
  	public CaseStatement enclosingCase// from 1.4 on, local types should not be accessed across switch case blocks (52221)
  
  	public final static VariableBinding[] EmulationPathToImplicitThis = {};
  	public final static VariableBinding[] NoEnclosingInstanceInConstructorCall = {};
  
  	public final static VariableBinding[] NoEnclosingInstanceInStaticContext = {};
  
  public BlockScope(BlockScope parent) {
  	this(parenttrue);
  }
  
  public BlockScope(BlockScope parentboolean addToParentScope) {
  	this(.parent);
  	this. = new LocalVariableBinding[5];
  	if (addToParentScopeparent.addSubscope(this);
  	this. = parent.localIndex;
  }
  
  public BlockScope(BlockScope parentint variableCount) {
  	this(.parent);
  	this. = new LocalVariableBinding[variableCount];
  	parent.addSubscope(this);
  	this. = parent.localIndex;
  }
  
  protected BlockScope(int kindScope parent) {
  	super(kindparent);
  }
  
  /* Create the class scope & binding for the anonymous type.
   */
  public final void addAnonymousType(TypeDeclaration anonymousTypeReferenceBinding superBinding) {
  	ClassScope anonymousClassScope = new ClassScope(thisanonymousType);
  	anonymousClassScope.buildAnonymousTypeBinding(
  		superBinding);
  }
  
  /* Create the class scope & binding for the local type.
   */
  public final void addLocalType(TypeDeclaration localType) {
  	ClassScope localTypeScope = new ClassScope(thislocalType);
  	addSubscope(localTypeScope);
  }
 
 /* Insert a local variable into a given scope, updating its position
  * and checking there are not too many locals or arguments allocated.
  */
 public final void addLocalVariable(LocalVariableBinding binding) {
 	// insert local in scope
 	if (this. == this..length)
 		System.arraycopy(
 			this.,
 			0,
 			(this. = new LocalVariableBinding[this. * 2]),
 			0,
 			this.);
 	this.[this.++] = binding;
 
 	// update local variable binding
 	binding.declaringScope = this;
 	binding.id = outerMostMethodScope().++;
 	// share the outermost method scope analysisIndex
 }
 
 public void addSubscope(Scope childScope) {
 	if (this. == this..length)
 		System.arraycopy(
 			this.,
 			0,
 			(this. = new Scope[this. * 2]),
 			0,
 	this.[this.++] = childScope;
 }

Answer true if the receiver is suitable for assigning final blank fields. in other words, it is inside an initializer, a constructor or a clinit
 
 public final boolean allowBlankFinalFieldAssignment(FieldBinding binding) {
 	if (enclosingReceiverType() != binding.declaringClass)
 		return false;
 
 	MethodScope methodScope = methodScope();
 	if (methodScope.isStatic != binding.isStatic())
 		return false;
 	return methodScope.isInsideInitializer() // inside initializer
 			|| ((AbstractMethodDeclarationmethodScope.referenceContext).isInitializationMethod(); // inside constructor or clinit
 }
 
 String basicToString(int tab) {
 	String newLine = "\n"//$NON-NLS-1$
 	for (int i = tab; --i >= 0;)
 		newLine += "\t"//$NON-NLS-1$
 
 	String s = newLine + "--- Block Scope ---"//$NON-NLS-1$
 	newLine += "\t"//$NON-NLS-1$
 	s += newLine + "locals:"//$NON-NLS-1$
 	for (int i = 0; i < this.i++)
 		s += newLine + "\t" + this.[i].toString(); //$NON-NLS-1$
 	s += newLine + "startIndex = " + this.//$NON-NLS-1$
 	return s;
 }
 
 	int modifiers = varBinding.modifiers;
 	if ((modifiers & .) != 0 && varBinding.declaration != null){
 		problemReporter().duplicateModifierForVariable(varBinding.declarationthis instanceof MethodScope);
 	}
 	int realModifiers = modifiers & .;
 
 	int unexpectedModifiers = ~.;
 	if ((realModifiers & unexpectedModifiers) != 0 && varBinding.declaration != null){
 		problemReporter().illegalModifierForVariable(varBinding.declarationthis instanceof MethodScope);
 	}
 	varBinding.modifiers = modifiers;
 }
 
 /* Compute variable positions in scopes given an initial position offset
  * ignoring unused local variables.
  *
  * No argument is expected here (ilocal is the first non-argument local of the outermost scope)
  * Arguments are managed by the MethodScope method
  */
 void computeLocalVariablePositions(int ilocalint initOffsetCodeStream codeStream) {
 	this. = initOffset;
 	this. = initOffset;
 
 	// local variable init
 	int maxLocals = this.;
 	boolean hasMoreVariables = ilocal < maxLocals;
 
 	// scope init
 	int iscope = 0, maxScopes = this.;
 	boolean hasMoreScopes = maxScopes > 0;
 
 	// iterate scopes and variables in parallel
 	while (hasMoreVariables || hasMoreScopes) {
 		if (hasMoreScopes
 			&& (!hasMoreVariables || (this.[iscope].startIndex() <= ilocal))) {
 			// consider subscope first
 			if (this.[iscopeinstanceof BlockScope) {
 				BlockScope subscope = (BlockScopethis.[iscope];
 				int subOffset = subscope.shiftScopes == null ? this. : subscope.maxShiftedOffset();
 				subscope.computeLocalVariablePositions(0, subOffsetcodeStream);
 				if (subscope.maxOffset > this.)
 					this. = subscope.maxOffset;
 			}
 			hasMoreScopes = ++iscope < maxScopes;
 		} else {
 
 			// consider variable first
 			LocalVariableBinding local = this.[ilocal]; // if no local at all, will be locals[ilocal]==null
 
 			// check if variable is actually used, and may force it to be preserved
 			boolean generateCurrentLocalVar = (local.useFlag > . && local.constant() == .);
 
 			// do not report fake used variable
 			if (local.useFlag == .
 				&& (local.declaration != null// unused (and non secret) local
 				&& ((local.declaration.bits & .) != 0)) { // declaration is reachable
 
 				if (!(local.declaration instanceof Argument)) // do not report unused catch arguments
 					problemReporter().unusedLocalVariable(local.declaration);
 			}
 
 			// could be optimized out, but does need to preserve unread variables ?
 			if (!generateCurrentLocalVar) {
 				if (local.declaration != null && compilerOptions().) {
 					generateCurrentLocalVar = true// force it to be preserved in the generated code
 					if (local.useFlag == .)
 						local.useFlag = .;
 				}
 			}
 
 			// allocate variable
 			if (generateCurrentLocalVar) {
 
 				if (local.declaration != null) {
 					codeStream.record(local); // record user-defined local variables for attribute generation
 				}
 				// assign variable position
 				local.resolvedPosition = this.;
 
 				if ((local.type == .) || (local.type == .)) {
 					this. += 2;
 				} else {
 					this.++;
 				}
 				if (this. > 0xFFFF) { // no more than 65535 words of locals
 						local,
 						local.declaration == null ? (ASTNode)methodScope(). : local.declaration);
 				}
 			} else {
 				local.resolvedPosition = -1; // not generated
 			}
 			hasMoreVariables = ++ilocal < maxLocals;
 		}
 	}
 	if (this. > this.)
 		this. = this.;
 }
 
 /*
  *	Record the suitable binding denoting a synthetic field or constructor argument,
  * mapping to the actual outer local variable in the scope context.
  * Note that this may not need any effect, in case the outer local variable does not
  * need to be emulated and can directly be used as is (using its back pointer to its
  * declaring scope).
  */
 public void emulateOuterAccess(LocalVariableBinding outerLocalVariable) {
 	BlockScope outerVariableScope = outerLocalVariable.declaringScope;
 	if (outerVariableScope == null)
 		return// no need to further emulate as already inserted (val$this$0)
 	MethodScope currentMethodScope = methodScope();
 	if (outerVariableScope.methodScope() != currentMethodScope) {
 
 		//do nothing for member types, pre emulation was performed already
 		if (!currentType.isLocalType()) {
 			return;
 		}
 		// must also add a synthetic field if we're not inside a constructor
 		if (!currentMethodScope.isInsideInitializerOrConstructor()) {
 			currentType.addSyntheticArgumentAndField(outerLocalVariable);
 		} else {
 			currentType.addSyntheticArgument(outerLocalVariable);
 		}
 	}
 }
 
 /* Note that it must never produce a direct access to the targetEnclosingType,
  * but instead a field sequence (this$2.this$1.this$0) so as to handle such a test case:
  *
  * class XX {
  *	void foo() {
  *		class A {
  *			class B {
  *				class C {
  *					boolean foo() {
  *						return (Object) A.this == (Object) B.this;
  *					}
  *				}
  *			}
  *		}
  *		new A().new B().new C();
  *	}
  * }
  * where we only want to deal with ONE enclosing instance for C (could not figure out an A for C)
  */
 public final ReferenceBinding findLocalType(char[] name) {
 	long compliance = compilerOptions().;
 	for (int i = this.-1; i >= 0; i--) {
 		if (this.[iinstanceof ClassScope) {
 			// from 1.4 on, local types should not be accessed across switch case blocks (52221)
 			if (compliance >= . && sourceType.enclosingCase != null) {
 				if (!isInsideCase(sourceType.enclosingCase)) {
 					continue;
 				}
 			}
 			if (CharOperation.equals(sourceType.sourceName(), name))
 				return sourceType;
 		}
 	}
 	return null;
 }

Returns all declarations of most specific locals containing a given position in their source range. This code does not recurse in nested types. Returned array may have null values at trailing indexes.
 
 public LocalDeclaration[] findLocalVariableDeclarations(int position) {
 	// local variable init
 	int ilocal = 0, maxLocals = this.;
 	boolean hasMoreVariables = maxLocals > 0;
 	LocalDeclaration[] localDeclarations = null;
 	int declPtr = 0;
 
 	// scope init
 	int iscope = 0, maxScopes = this.;
 	boolean hasMoreScopes = maxScopes > 0;
 
 	// iterate scopes and variables in parallel
 	while (hasMoreVariables || hasMoreScopes) {
 		if (hasMoreScopes
 			&& (!hasMoreVariables || (this.[iscope].startIndex() <= ilocal))) {
 			// consider subscope first
 			Scope subscope = this.[iscope];
 			if (subscope.kind == .) { // do not dive in nested types
 				localDeclarations = ((BlockScope)subscope).findLocalVariableDeclarations(position);
 				if (localDeclarations != null) {
 					return localDeclarations;
 				}
 			}
 			hasMoreScopes = ++iscope < maxScopes;
 		} else {
 			// consider variable first
 			LocalVariableBinding local = this.[ilocal]; // if no local at all, will be locals[ilocal]==null
 			if (local != null) {
 				LocalDeclaration localDecl = local.declaration;
 				if (localDecl != null) {
 					if (localDecl.declarationSourceStart <= position) {
 						if (position <= localDecl.declarationSourceEnd) {
 							if (localDeclarations == null) {
 								localDeclarations = new LocalDeclaration[maxLocals];
 							}
 							localDeclarations[declPtr++] = localDecl;
 						}
 					} else {
 						return localDeclarations;
 					}
 				}
 			}
 			hasMoreVariables = ++ilocal < maxLocals;
 			if (!hasMoreVariables && localDeclarations != null) {
 				return localDeclarations;
 			}
 		}
 	}
 	return null;
 }
 
 public LocalVariableBinding findVariable(char[] variableName) {
 	int varLength = variableName.length;
 	for (int i = this.-1; i >= 0; i--) { // lookup backward to reach latest additions first
 		char[] localName;
 		if ((localName = (local = this.[i]).).length == varLength && CharOperation.equals(localNamevariableName))
 			return local;
 	}
 	return null;
 }
 
 /* API
  * flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE.
  * Only bindings corresponding to the mask will be answered.
  *
  *	if the VARIABLE mask is set then
  *		If the first name provided is a field (or local) then the field (or local) is answered
  *		Otherwise, package names and type names are consumed until a field is found.
  *		In this case, the field is answered.
  *
  *	if the TYPE mask is set,
  *		package names and type names are consumed until the end of the input.
  *		Only if all of the input is consumed is the type answered
  *
  *	All other conditions are errors, and a problem binding is returned.
  *
  *	NOTE: If a problem binding is returned, senders should extract the compound name
  *	from the binding & not assume the problem applies to the entire compoundName.
  *
  *	The VARIABLE mask has precedence over the TYPE mask.
  *
  *	InvocationSite implements
  *		isSuperAccess(); this is used to determine if the discovered field is visible.
  *		setFieldIndex(int); this is used to record the number of names that were consumed.
  *
  *	For example, getBinding({"foo","y","q", VARIABLE, site) will answer
  *	the binding for the field or local named "foo" (or an error binding if none exists).
  *	In addition, setFieldIndex(1) will be sent to the invocation site.
  *	If a type named "foo" exists, it will not be detected (and an error binding will be answered)
  *
  *	IMPORTANT NOTE: This method is written under the assumption that compoundName is longer than length 1.
  */
 public Binding getBinding(char[][] compoundNameint maskInvocationSite invocationSiteboolean needResolve) {
 	Binding binding = getBinding(compoundName[0], mask | . | .invocationSiteneedResolve);
 	invocationSite.setFieldIndex(1);
 	if (binding instanceof VariableBindingreturn binding;
 	// in the problem case, we want to ensure we record the qualified dependency in case a type is added
 	// and we do not know that its package was also added (can happen with CompilationParticipants)
 	unitScope.recordQualifiedReference(compoundName);
 	if (!binding.isValidBinding()) return binding;
 
 	int length = compoundName.length;
 	int currentIndex = 1;
 	foundType : if (binding instanceof PackageBinding) {
 		PackageBinding packageBinding = (PackageBindingbinding;
 		while (currentIndex < length) {
 			unitScope.recordReference(packageBinding.compoundNamecompoundName[currentIndex]);
 			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
 			invocationSite.setFieldIndex(currentIndex);
 			if (binding == null) {
 				if (currentIndex == length) {
 					// must be a type if its the last name, otherwise we have no idea if its a package or type
 						CharOperation.subarray(compoundName, 0, currentIndex),
 						null,
 				}
 				return new ProblemBinding(
 					CharOperation.subarray(compoundName, 0, currentIndex),
 			}
 			if (binding instanceof ReferenceBinding) {
 				if (!binding.isValidBinding())
 						CharOperation.subarray(compoundName, 0, currentIndex),
 						binding.problemId());
 				if (!((ReferenceBindingbinding).canBeSeenBy(this))
 						CharOperation.subarray(compoundName, 0, currentIndex),
 						(ReferenceBindingbinding,
 				break foundType;
 			}
 			packageBinding = (PackageBindingbinding;
 		}
 
 		// It is illegal to request a PACKAGE from this method.
 			CharOperation.subarray(compoundName, 0, currentIndex),
 			null,
 	}
 
 	// know binding is now a ReferenceBinding
 	ReferenceBinding referenceBinding = (ReferenceBindingbinding;
 	binding = environment().convertToRawType(referenceBindingfalse /*do not force conversion of enclosing types*/);
 	if (invocationSite instanceof ASTNode) {
 		ASTNode invocationNode = (ASTNodeinvocationSite;
 		if (invocationNode.isTypeUseDeprecated(referenceBindingthis)) {
 			problemReporter().deprecatedType(referenceBindinginvocationNode);
 		}
 	}
 	Binding problemFieldBinding = null;
 	while (currentIndex < length) {
 		referenceBinding = (ReferenceBindingbinding;
 		char[] nextName = compoundName[currentIndex++];
 		invocationSite.setFieldIndex(currentIndex);
 		invocationSite.setActualReceiverType(referenceBinding);
 		if ((mask & .) != 0 && (binding = findField(referenceBindingnextNameinvocationSitetrue /*resolve*/)) != null) {
 			if (binding.isValidBinding()) {
 				break// binding is now a field
 			}
 			problemFieldBinding = new ProblemFieldBinding(
 				CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'),
 				binding.problemId()); 
 			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=317858 : If field is inaccessible,
 			// don't give up yet, continue to look for a visible member type 
 			if (binding.problemId() != .) {  
 				return problemFieldBinding;
 			}
 		}
 		if ((binding = findMemberType(nextNamereferenceBinding)) == null) {
 			if (problemFieldBinding != null) {
 				return problemFieldBinding;
 			}
 			if ((mask & .) != 0) {
 				return new ProblemFieldBinding(
 						null,
 						referenceBinding,
 						nextName,
 			} else if ((mask & .) != 0) {
 				return new ProblemBinding(
 					CharOperation.subarray(compoundName, 0, currentIndex),
 					referenceBinding,
 			}
 				CharOperation.subarray(compoundName, 0, currentIndex),
 				referenceBinding,
 		}
 		// binding is a ReferenceBinding
 		if (!binding.isValidBinding()) {
 			if (problemFieldBinding != null) {
 				return problemFieldBinding;
 			}
 				CharOperation.subarray(compoundName, 0, currentIndex),
 				binding.problemId());
 		}
 		if (invocationSite instanceof ASTNode) {
 			referenceBinding = (ReferenceBindingbinding;
 			ASTNode invocationNode = (ASTNodeinvocationSite;
 			if (invocationNode.isTypeUseDeprecated(referenceBindingthis)) {
 				problemReporter().deprecatedType(referenceBindinginvocationNode);
 			}
 		}
 	}
 	if ((mask & .) != 0 && (binding instanceof FieldBinding)) {
 		// was looking for a field and found a field
 		FieldBinding field = (FieldBindingbinding;
 		if (!field.isStatic())
 			return new ProblemFieldBinding(
 				field,
 				field.declaringClass,
 				CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'),
 		// Since a qualified reference must be for a static member, it won't affect static-ness of the enclosing method, 
 		// so we don't have to call resetEnclosingMethodStaticFlag() in this case
 		return binding;
 	}
 	if ((mask & .) != 0 && (binding instanceof ReferenceBinding)) {
 		// was looking for a type and found a type
 		return binding;
 	}
 
 	// handle the case when a field or type was asked for but we resolved the compoundName to a type or field
 	return new ProblemBinding(
 		CharOperation.subarray(compoundName, 0, currentIndex),
 }
 
 // Added for code assist... NOT Public API
 public final Binding getBinding(char[][] compoundNameInvocationSite invocationSite) {
 	int currentIndex = 0;
 	int length = compoundName.length;
 	Binding binding =
 			compoundName[currentIndex++],
 			invocationSite,
 			true /*resolve*/);
 	if (!binding.isValidBinding())
 		return binding;
 
 	foundType : if (binding instanceof PackageBinding) {
 		while (currentIndex < length) {
 			PackageBinding packageBinding = (PackageBindingbinding;
 			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
 			if (binding == null) {
 				if (currentIndex == length) {
 					// must be a type if its the last name, otherwise we have no idea if its a package or type
 						CharOperation.subarray(compoundName, 0, currentIndex),
 						null,
 				}
 				return new ProblemBinding(
 					CharOperation.subarray(compoundName, 0, currentIndex),
 			}
 			if (binding instanceof ReferenceBinding) {
 				if (!binding.isValidBinding())
 						CharOperation.subarray(compoundName, 0, currentIndex),
 						binding.problemId());
 				if (!((ReferenceBindingbinding).canBeSeenBy(this))
 						CharOperation.subarray(compoundName, 0, currentIndex),
 						(ReferenceBindingbinding,
 				break foundType;
 			}
 		}
 		return binding;
 	}
 
 	foundField : if (binding instanceof ReferenceBinding) {
 		while (currentIndex < length) {
 			ReferenceBinding typeBinding = (ReferenceBindingbinding;
 			char[] nextName = compoundName[currentIndex++];
 			TypeBinding receiverType = typeBinding.capture(thisinvocationSite.sourceEnd());
 			if ((binding = findField(receiverTypenextNameinvocationSitetrue /*resolve*/)) != null) {
 				if (!binding.isValidBinding()) {
 					return new ProblemFieldBinding(
 						(FieldBindingbinding,
 						CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'),
 						binding.problemId());
 				}
 				if (!((FieldBindingbinding).isStatic())
 					return new ProblemFieldBinding(
 						(FieldBindingbinding,
 						CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'),
 				break foundField; // binding is now a field
 			}
 			if ((binding = findMemberType(nextNametypeBinding)) == null) {
 				return new ProblemBinding(
 					CharOperation.subarray(compoundName, 0, currentIndex),
 					typeBinding,
 			}
 			if (!binding.isValidBinding()) {
 					CharOperation.subarray(compoundName, 0, currentIndex),
 					binding.problemId());
 			}
 		}
 		return binding;
 	}
 
 	VariableBinding variableBinding = (VariableBindingbinding;
 	while (currentIndex < length) {
 		TypeBinding typeBinding = variableBinding.type;
 		if (typeBinding == null) {
 			return new ProblemFieldBinding(
 				null,
 				null,
 				CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'),
 		}
 		TypeBinding receiverType = typeBinding.capture(thisinvocationSite.sourceEnd());
 		variableBinding = findField(receiverTypecompoundName[currentIndex++], invocationSitetrue /*resolve*/);
 		if (variableBinding == null) {
 			return new ProblemFieldBinding(
 				null,
 				receiverType instanceof ReferenceBinding ? (ReferenceBindingreceiverType : null,
 				CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'),
 		}
 		if (!variableBinding.isValidBinding())
 			return variableBinding;
 	}
 	return variableBinding;
 }
 
 /*
  * This retrieves the argument that maps to an enclosing instance of the suitable type,
  * 	if not found then answers nil -- do not create one
  *
  *		#implicitThis		  	 			: the implicit this will be ok
  *		#((arg) this$n)						: available as a constructor arg
  * 		#((arg) this$n ... this$p) 			: available as as a constructor arg + a sequence of fields
  * 		#((fieldDescr) this$n ... this$p) 	: available as a sequence of fields
  * 		nil 		 											: not found
  *
  * 	Note that this algorithm should answer the shortest possible sequence when
  * 		shortcuts are available:
  * 				this$0 . this$0 . this$0
  * 		instead of
  * 				this$2 . this$1 . this$0 . this$1 . this$0
  * 		thus the code generation will be more compact and runtime faster
  */
 public VariableBinding[] getEmulationPath(LocalVariableBinding outerLocalVariable) {
 	MethodScope currentMethodScope = methodScope();
 	SourceTypeBinding sourceType = currentMethodScope.enclosingSourceType();
 
 	// identity check
 	BlockScope variableScope = outerLocalVariable.declaringScope;
 	if (variableScope == null /*val$this$0*/ || currentMethodScope == variableScope.methodScope()) {
 		return new VariableBinding[] { outerLocalVariable };
 		// implicit this is good enough
 	}
 	// use synthetic constructor arguments if possible
 	if (currentMethodScope.isInsideInitializerOrConstructor()
 		&& (sourceType.isNestedType())) {
 		SyntheticArgumentBinding syntheticArg;
 		if ((syntheticArg = ((NestedTypeBindingsourceType).getSyntheticArgument(outerLocalVariable)) != null) {
 			return new VariableBinding[] { syntheticArg };
 		}
 	}
 	// use a synthetic field then
 	if (!currentMethodScope.isStatic) {
 		FieldBinding syntheticField;
 		if ((syntheticField = sourceType.getSyntheticField(outerLocalVariable)) != null) {
 			return new VariableBinding[] { syntheticField };
 		}
 	}
 	return null;
 }
 
 /*
  * This retrieves the argument that maps to an enclosing instance of the suitable type,
  * 	if not found then answers nil -- do not create one
  *
  *		#implicitThis		  	 											:  the implicit this will be ok
  *		#((arg) this$n)													: available as a constructor arg
  * 	#((arg) this$n access$m... access$p) 		: available as as a constructor arg + a sequence of synthetic accessors to synthetic fields
  * 	#((fieldDescr) this$n access#m... access$p)	: available as a first synthetic field + a sequence of synthetic accessors to synthetic fields
  * 	null 		 															: not found
  *	jls 15.9.2 + http://www.ergnosis.com/java-spec-report/java-language/jls-8.8.5.1-d.html
  */
 public Object[] getEmulationPath(ReferenceBinding targetEnclosingTypeboolean onlyExactMatchboolean denyEnclosingArgInConstructorCall) {
 	MethodScope currentMethodScope = methodScope();
 	SourceTypeBinding sourceType = currentMethodScope.enclosingSourceType();
 
 	// use 'this' if possible
 	if (!currentMethodScope.isStatic && !currentMethodScope.isConstructorCall) {
 		if (sourceType == targetEnclosingType || (!onlyExactMatch && sourceType.findSuperTypeOriginatingFrom(targetEnclosingType) != null)) {
 			return .// implicit this is good enough
 		}
 	}
 	if (!sourceType.isNestedType() || sourceType.isStatic()) { // no emulation from within non-inner types
 		if (currentMethodScope.isConstructorCall) {
 		} else if (currentMethodScope.isStatic){
 		}
 		return null;
 	}
 	boolean insideConstructor = currentMethodScope.isInsideInitializerOrConstructor();
 	// use synthetic constructor arguments if possible
 	if (insideConstructor) {
 		SyntheticArgumentBinding syntheticArg;
 		if ((syntheticArg = ((NestedTypeBindingsourceType).getSyntheticArgument(targetEnclosingTypeonlyExactMatchcurrentMethodScope.isConstructorCall)) != null) {
 			boolean isAnonymousAndHasEnclosing = sourceType.isAnonymousType()
 				&& sourceType.scope.referenceContext.allocation.enclosingInstance != null;
 			// reject allocation and super constructor call
 			if (denyEnclosingArgInConstructorCall
 					&& currentMethodScope.isConstructorCall
 					&& !isAnonymousAndHasEnclosing
 					&& (sourceType == targetEnclosingType || (!onlyExactMatch && sourceType.findSuperTypeOriginatingFrom(targetEnclosingType) != null))) {
 			}
 			return new Object[] { syntheticArg };
 		}
 	}
 
 	// use a direct synthetic field then
 	if (currentMethodScope.isStatic) {
 	}
 	if (sourceType.isAnonymousType()) {
 		ReferenceBinding enclosingType = sourceType.enclosingType();
 		if (enclosingType.isNestedType()) {
 			NestedTypeBinding nestedEnclosingType = (NestedTypeBindingenclosingType;
 			SyntheticArgumentBinding enclosingArgument = nestedEnclosingType.getSyntheticArgument(nestedEnclosingType.enclosingType(), onlyExactMatchcurrentMethodScope.isConstructorCall);
 			if (enclosingArgument != null) {
 				FieldBinding syntheticField = sourceType.getSyntheticField(enclosingArgument);
 				if (syntheticField != null) {
 					if (syntheticField.type == targetEnclosingType || (!onlyExactMatch && ((ReferenceBinding)syntheticField.type).findSuperTypeOriginatingFrom(targetEnclosingType) != null))
 						return new Object[] { syntheticField };
 				}
 			}
 		}
 	}
 	FieldBinding syntheticField = sourceType.getSyntheticField(targetEnclosingTypeonlyExactMatch);
 	if (syntheticField != null) {
 		if (currentMethodScope.isConstructorCall){
 		}
 		return new Object[] { syntheticField };
 	}
 
 	// could be reached through a sequence of enclosing instance link (nested members)
 	Object[] path = new Object[2]; // probably at least 2 of them
 	ReferenceBinding currentType = sourceType.enclosingType();
 	if (insideConstructor) {
 		path[0] = ((NestedTypeBindingsourceType).getSyntheticArgument(currentTypeonlyExactMatchcurrentMethodScope.isConstructorCall);
 	} else {
 		if (currentMethodScope.isConstructorCall){
 		}
 		path[0] = sourceType.getSyntheticField(currentTypeonlyExactMatch);
 	}
 	if (path[0] != null) { // keep accumulating
 
 		int count = 1;
 		ReferenceBinding currentEnclosingType;
 		while ((currentEnclosingType = currentType.enclosingType()) != null) {
 
 			//done?
 			if (currentType == targetEnclosingType
 				|| (!onlyExactMatch && currentType.findSuperTypeOriginatingFrom(targetEnclosingType) != null))	break;
 
 			if (currentMethodScope != null) {
 				currentMethodScope = currentMethodScope.enclosingMethodScope();
 				if (currentMethodScope != null && currentMethodScope.isConstructorCall){
 				}
 				if (currentMethodScope != null && currentMethodScope.isStatic){
 				}
 			}
 
 			syntheticField = ((NestedTypeBindingcurrentType).getSyntheticField(currentEnclosingTypeonlyExactMatch);
 			if (syntheticField == nullbreak;
 
 			// append inside the path
 			if (count == path.length) {
 				System.arraycopy(path, 0, (path = new Object[count + 1]), 0, count);
 			}
 			// private access emulation is necessary since synthetic field is private
 			path[count++] = ((SourceTypeBindingsyntheticField.declaringClass).addSyntheticMethod(syntheticFieldtrue/*read*/false /*not super access*/);
 			currentType = currentEnclosingType;
 		}
 		if (currentType == targetEnclosingType
 			|| (!onlyExactMatch && currentType.findSuperTypeOriginatingFrom(targetEnclosingType) != null)) {
 			return path;
 		}
 	}
 	return null;
 }
 
 /* Answer true if the variable name already exists within the receiver's scope.
  */
 public final boolean isDuplicateLocalVariable(char[] name) {
 	BlockScope current = this;
 	while (true) {
 		for (int i = 0; i < this.i++) {
 			if (CharOperation.equals(namecurrent.locals[i].))
 				return true;
 		}
 		if (current.kind != .return false;
 		current = (BlockScope)current.parent;
 	}
 }
 
 public int maxShiftedOffset() {
 	int max = -1;
 	if (this. != null){
 		for (int i = 0, length = this..lengthi < lengthi++){
 			if (this.[i] != null) {
 				int subMaxOffset = this.[i].;
 				if (subMaxOffset > maxmax = subMaxOffset;
 			}
 		}
 	}
 	return max;
 }

Returns true if the context requires to check initialization of final blank fields. in other words, it is inside an initializer, a constructor or a clinit
 
 public final boolean needBlankFinalFieldInitializationCheck(FieldBinding binding) {
 	boolean isStatic = binding.isStatic();
 	ReferenceBinding fieldDeclaringClass = binding.declaringClass;
 	// loop in enclosing context, until reaching the field declaring context
 	MethodScope methodScope = methodScope();
 	while (methodScope != null) {
 		if (methodScope.isStatic != isStatic)
 			return false;
 		if (!methodScope.isInsideInitializer() // inside initializer
 				&& !((AbstractMethodDeclarationmethodScope.referenceContext).isInitializationMethod()) { // inside constructor or clinit
 			return false// found some non-initializer context
 		}
 		ReferenceBinding enclosingType = methodScope.enclosingReceiverType();
 		if (enclosingType == fieldDeclaringClass) {
 			return true// found the field context, no need to check any further
 		}
 		if (!enclosingType.erasure().isAnonymousType()) {
 			return false// only check inside anonymous type
 		}
 		methodScope = methodScope.enclosingMethodScope();
 	}
 	return false;
 }
 
 /* Answer the problem reporter to use for raising new problems.
  *
  * Note that as a side-effect, this updates the current reference context
  * (unit, type or method) in case the problem handler decides it is necessary
  * to abort.
  */
 }
 
 /*
  * Code responsible to request some more emulation work inside the invocation type, so as to supply
  * correct synthetic arguments to any allocation of the target type.
  */
 public void propagateInnerEmulation(ReferenceBinding targetTypeboolean isEnclosingInstanceSupplied) {
 	// no need to propagate enclosing instances, they got eagerly allocated already.
 
 	SyntheticArgumentBinding[] syntheticArguments;
 	if ((syntheticArguments = targetType.syntheticOuterLocalVariables()) != null) {
 		for (int i = 0, max = syntheticArguments.lengthi < maxi++) {
 			SyntheticArgumentBinding syntheticArg = syntheticArguments[i];
 			// need to filter out the one that could match a supplied enclosing instance
 			if (!(isEnclosingInstanceSupplied
 				&& (syntheticArg.type == targetType.enclosingType()))) {
 				emulateOuterAccess(syntheticArg.actualOuterLocalVariable);
 			}
 		}
 	}
 }
 
 /* Answer the reference type of this scope.
  *
  * It is the nearest enclosing type of this scope.
  */
 }
 
 /*
  * Answer the index of this scope relatively to its parent.
  * For method scope, answers -1 (not a classScope relative position)
  */
 public int scopeIndex() {
 	if (this instanceof MethodScopereturn -1;
 	BlockScope parentScope = (BlockScope)this.;
 	Scope[] parentSubscopes = parentScope.subscopes;
 	for (int i = 0, max = parentScope.subscopeCounti < maxi++) {
 		if (parentSubscopes[i] == thisreturn i;
 	}
 	return -1;
 }
 
 // start position in this scope - for ordering scopes vs. variables
 int startIndex() {
 	return this.;
 }
 
 public String toString() {
 	return toString(0);
 }
 
 public String toString(int tab) {
 	String s = basicToString(tab);
 	for (int i = 0; i < this.i++)
 		if (this.[iinstanceof BlockScope)
 			s += ((BlockScopethis.[i]).toString(tab + 1) + "\n"//$NON-NLS-1$
 	return s;
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
This method is used to reset the CanBeStatic the enclosing method of the current block
 
 	MethodScope methodScope = methodScope();
 	if (methodScope != null) {
 		if (methodScope.referenceContext instanceof MethodDeclaration) {
 			MethodDeclaration methodDeclaration = (MethodDeclarationmethodScope.referenceContext;
 			methodDeclaration.bits &= ~.;
 		} else if (methodScope.referenceContext instanceof TypeDeclaration) {
 			// anonymous type, find enclosing method
 			methodScope = methodScope.enclosingMethodScope();
 			if (methodScope != null && methodScope.referenceContext instanceof MethodDeclaration) {
 				MethodDeclaration methodDeclaration = (MethodDeclarationmethodScope.referenceContext;
 				methodDeclaration.bits &= ~.;
 			}
 		}
 	}
 }
 
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=376550
This method is used to reset the CanBeStatic on all enclosing methods until the method belonging to the enclosingInstanceType

Parameters:
enclosingInstanceType type of which an enclosing instance is required in the code.
 
 public void resetDeclaringClassMethodStaticFlag(TypeBinding enclosingInstanceType) {
 	MethodScope methodScope = methodScope();
 	if (methodScope != null && methodScope.referenceContext instanceof TypeDeclaration) {
		if (!methodScope.enclosingReceiverType().isCompatibleWith(enclosingInstanceType)) { // unless invoking a method of the local type ...
			// anonymous type, find enclosing method
			methodScope = methodScope.enclosingMethodScope();
	while (methodScope != null && methodScope.referenceContext instanceof MethodDeclaration) {
		MethodDeclaration methodDeclaration = (MethodDeclarationmethodScope.referenceContext;
		methodDeclaration.bits &= ~.;
		ClassScope enclosingClassScope = methodScope.enclosingClassScope();
		if (enclosingClassScope != null) {
			TypeDeclaration type = enclosingClassScope.referenceContext;
			if (type != null && type.binding != null && enclosingInstanceType != null
					&& !type.binding.isCompatibleWith(enclosingInstanceType.original()))
				methodScope = enclosingClassScope.enclosingMethodScope();
				continue;
		break;
private List trackingVariables// can be null if no resources are tracked
Used only during analyseCode and only for checking if a resource was closed in a finallyBlock.
Register a tracking variable and compute its id.
public int registerTrackingVariable(FakedTrackingVariable fakedTrackingVariable) {
	if (this. == null)
		this. = new ArrayList(3);
	this..add(fakedTrackingVariable);
	MethodScope outerMethodScope = outerMostMethodScope();
	return outerMethodScope.analysisIndex++;
When are no longer interested in this tracking variable - remove it.
public void removeTrackingVar(FakedTrackingVariable trackingVariable) {
	if (trackingVariable.innerTracker != null) {
		removeTrackingVar(trackingVariable.innerTracker);
		trackingVariable.innerTracker = null;
	if (this. != null)
		if (this..remove(trackingVariable))
			return;
	if (this. instanceof BlockScope)
		((BlockScope)this.).removeTrackingVar(trackingVariable);
Unregister a wrapper resource without affecting its inner.
public void pruneWrapperTrackingVar(FakedTrackingVariable trackingVariable) {
	this..remove(trackingVariable);
At the end of a block check the closing-status of all tracked closeables that are declared in this block. Also invoked when entering unreachable code.
public void checkUnclosedCloseables(FlowInfo flowInfoFlowContext flowContextASTNode locationBlockScope locationScope) {
	if (this. == null) {
		// at a method return we also consider enclosing scopes
		if (location != null && this. instanceof BlockScope)
			((BlockScopethis.).checkUnclosedCloseables(flowInfoflowContextlocationlocationScope);
		return;
	if (location != null && flowInfo.reachMode() != 0) return;
	FakedTrackingVariable returnVar = (location instanceof ReturnStatement) ?
			FakedTrackingVariable.getCloseTrackingVariable(((ReturnStatement)location).flowInfoflowContext) : null;
	Set varSet = new HashSet(this.);
	// pick one outer-most variable from the set at a time
	while ((trackingVar = FakedTrackingVariable.pickVarForReporting(varSetthislocation != null)) != null) {
		if (returnVar != null && trackingVar.isResourceBeingReturned(returnVar)) {
			continue;
		if (location != null && trackingVar.hasDefinitelyNoResource(flowInfo)) {
			continue// reporting against a specific location, there is no resource at this flow, don't complain
		if (location != null && flowContext != null && flowContext.recordExitAgainstResource(thisflowInfotrackingVarlocation)) {
			continue// handled by the flow context
		// compute the most specific null status for this resource,
		int status = trackingVar.findMostSpecificStatus(flowInfothislocationScope);
		if (status == .) {
			// definitely unclosed: highest priority
			reportResourceLeak(trackingVarlocationstatus);
			continue;
		if (location == null// at end of block and not definitely unclosed
			// problems at specific locations: medium&