/******************************************************************************* * Copyright (c) 2008, 2010 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 *******************************************************************************/ package org.eclipse.jdt.internal.codeassist; import java.util.HashMap; import java.util.Map; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.WorkingCopyOwner; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.codeassist.complete.CompletionNodeDetector; import org.eclipse.jdt.internal.codeassist.complete.CompletionParser; import org.eclipse.jdt.internal.codeassist.impl.AssistCompilationUnit; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.Initializer; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeParameter; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.ImportBinding; import org.eclipse.jdt.internal.compiler.lookup.InvocationSite; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.SignatureWrapper; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; import org.eclipse.jdt.internal.compiler.util.ObjectVector; import org.eclipse.jdt.internal.core.CompilationUnitElementInfo; import org.eclipse.jdt.internal.core.JavaElement; import org.eclipse.jdt.internal.core.LocalVariable; import org.eclipse.jdt.internal.core.util.Util; public class InternalExtendedCompletionContext { private static Util.BindingsToNodesMap EmptyNodeMap= new Util.BindingsToNodesMap() { public ASTNode get(Binding binding) { return null; } }; private InternalCompletionContext completionContext; // static data private ITypeRoot typeRoot; private CompilationUnitDeclaration compilationUnitDeclaration; private LookupEnvironment lookupEnvironment; private Scope assistScope; private ASTNode assistNode; private WorkingCopyOwner owner; private CompletionParser parser; // computed data private boolean hasComputedVisibleElementBindings; private ObjectVector visibleLocalVariables; private ObjectVector visibleFields; private ObjectVector visibleMethods; private boolean hasComputedEnclosingJavaElements; private Map bindingsToHandles; private Map nodesWithProblemsToHandles; private ICompilationUnit compilationUnit; public InternalExtendedCompletionContext( InternalCompletionContext completionContext, ITypeRoot typeRoot, CompilationUnitDeclaration compilationUnitDeclaration, LookupEnvironment lookupEnvironment, Scope assistScope, ASTNode assistNode, WorkingCopyOwner owner, CompletionParser parser) { this.completionContext= completionContext; this.typeRoot= typeRoot; this.compilationUnitDeclaration= compilationUnitDeclaration; this.lookupEnvironment= lookupEnvironment; this.assistScope= assistScope; this.assistNode= assistNode; this.owner= owner; this.parser= parser; } private void computeEnclosingJavaElements() { this.hasComputedEnclosingJavaElements= true; if (this.typeRoot == null) return; if (this.typeRoot.getElementType() == IJavaElement.COMPILATION_UNIT) { ICompilationUnit original= (org.eclipse.jdt.core.ICompilationUnit)this.typeRoot; HashMap handleToBinding= new HashMap(); HashMap bindingToHandle= new HashMap(); HashMap nodeWithProblemToHandle= new HashMap(); HashMap handleToInfo= new HashMap(); org.eclipse.jdt.core.ICompilationUnit handle= new AssistCompilationUnit(original, this.owner, handleToBinding, handleToInfo); CompilationUnitElementInfo info= new CompilationUnitElementInfo(); handleToInfo.put(handle, info); CompletionUnitStructureRequestor structureRequestor= new CompletionUnitStructureRequestor( handle, info, this.parser, this.assistNode, handleToBinding, bindingToHandle, nodeWithProblemToHandle, handleToInfo); CompletionElementNotifier notifier= new CompletionElementNotifier( structureRequestor, true, this.assistNode); notifier.notifySourceElementRequestor( this.compilationUnitDeclaration, this.compilationUnitDeclaration.sourceStart, this.compilationUnitDeclaration.sourceEnd, false, this.parser.sourceEnds, new HashMap()); this.bindingsToHandles= bindingToHandle; this.nodesWithProblemsToHandles= nodeWithProblemToHandle; this.compilationUnit= handle; } } private void computeVisibleElementBindings() { CompilationUnitDeclaration previousUnitBeingCompleted= this.lookupEnvironment.unitBeingCompleted; this.lookupEnvironment.unitBeingCompleted= this.compilationUnitDeclaration; try { this.hasComputedVisibleElementBindings= true; Scope scope= this.assistScope; ASTNode astNode= this.assistNode; boolean notInJavadoc= this.completionContext.javadoc == 0; this.visibleLocalVariables= new ObjectVector(); this.visibleFields= new ObjectVector(); this.visibleMethods= new ObjectVector(); ReferenceContext referenceContext= scope.referenceContext(); if (referenceContext instanceof AbstractMethodDeclaration) { // completion is inside a method body searchVisibleVariablesAndMethods(scope, this.visibleLocalVariables, this.visibleFields, this.visibleMethods, notInJavadoc); } else if (referenceContext instanceof TypeDeclaration) { TypeDeclaration typeDeclaration= (TypeDeclaration)referenceContext; FieldDeclaration[] fields= typeDeclaration.fields; if (fields != null) { done: for (int i= 0; i < fields.length; i++) { if (fields[i] instanceof Initializer) { Initializer initializer= (Initializer)fields[i]; if (initializer.block.sourceStart <= astNode.sourceStart && astNode.sourceStart < initializer.bodyEnd) { // completion is inside an initializer searchVisibleVariablesAndMethods(scope, this.visibleLocalVariables, this.visibleFields, this.visibleMethods, notInJavadoc); break done; } } else { FieldDeclaration fieldDeclaration= fields[i]; if (fieldDeclaration.initialization != null && fieldDeclaration.initialization.sourceStart <= astNode.sourceStart && astNode.sourceEnd <= fieldDeclaration.initialization.sourceEnd) { // completion is inside a field initializer searchVisibleVariablesAndMethods(scope, this.visibleLocalVariables, this.visibleFields, this.visibleMethods, notInJavadoc); break done; } } } } } } finally { this.lookupEnvironment.unitBeingCompleted= previousUnitBeingCompleted; } } public IJavaElement getEnclosingElement() { try { if (!this.hasComputedEnclosingJavaElements) { computeEnclosingJavaElements(); } if (this.compilationUnit == null) return null; IJavaElement enclosingElement= this.compilationUnit.getElementAt(this.completionContext.offset); return enclosingElement == null ? this.compilationUnit : enclosingElement; } catch (JavaModelException e) { Util.log(e, "Cannot compute enclosing element"); //$NON-NLS-1$ return null; } } private JavaElement getJavaElement(LocalVariableBinding binding) { LocalDeclaration local= binding.declaration; JavaElement parent= null; ReferenceContext referenceContext= binding.declaringScope.referenceContext(); if (referenceContext instanceof AbstractMethodDeclaration) { AbstractMethodDeclaration methodDeclaration= (AbstractMethodDeclaration)referenceContext; parent= this.getJavaElementOfCompilationUnit(methodDeclaration, methodDeclaration.binding); } else if (referenceContext instanceof TypeDeclaration) { // Local variable is declared inside an initializer TypeDeclaration typeDeclaration= (TypeDeclaration)referenceContext; JavaElement type= this.getJavaElementOfCompilationUnit(typeDeclaration, typeDeclaration.binding); parent= Util.getUnresolvedJavaElement(local.sourceStart, local.sourceEnd, type); } if (parent == null) return null; return new LocalVariable( parent, new String(local.name), local.declarationSourceStart, local.declarationSourceEnd, local.sourceStart, local.sourceEnd, Util.typeSignature(local.type), binding.declaration.annotations); } private JavaElement getJavaElementOfCompilationUnit(Binding binding) { if (!this.hasComputedEnclosingJavaElements) { computeEnclosingJavaElements(); } if (this.bindingsToHandles == null) return null; return (JavaElement)this.bindingsToHandles.get(binding); } private JavaElement getJavaElementOfCompilationUnit(ASTNode node, Binding binding) { if (!this.hasComputedEnclosingJavaElements) { computeEnclosingJavaElements(); } if (binding != null) { if (this.bindingsToHandles == null) return null; return (JavaElement)this.bindingsToHandles.get(binding); } else { if (this.nodesWithProblemsToHandles == null) return null; return (JavaElement)this.nodesWithProblemsToHandles.get(node); } } private TypeBinding getTypeFromSignature(String typeSignature, Scope scope) { TypeBinding assignableTypeBinding= null; TypeVariableBinding[] typeVariables= Binding.NO_TYPE_VARIABLES; ReferenceContext referenceContext= scope.referenceContext(); if (referenceContext instanceof AbstractMethodDeclaration) { AbstractMethodDeclaration methodDeclaration= (AbstractMethodDeclaration)referenceContext; TypeParameter[] typeParameters= methodDeclaration.typeParameters(); if (typeParameters != null && typeParameters.length > 0) { int length= typeParameters.length; int count= 0; typeVariables= new TypeVariableBinding[length]; for (int i= 0; i < length; i++) { if (typeParameters[i].binding != null) { typeVariables[count++]= typeParameters[i].binding; } } if (count != length) { System.arraycopy(typeVariables, 0, typeVariables= new TypeVariableBinding[count], 0, count); } } } CompilationUnitDeclaration previousUnitBeingCompleted= this.lookupEnvironment.unitBeingCompleted; this.lookupEnvironment.unitBeingCompleted= this.compilationUnitDeclaration; try { SignatureWrapper wrapper= new SignatureWrapper(replacePackagesDot(typeSignature.toCharArray())); assignableTypeBinding= this.lookupEnvironment.getTypeFromTypeSignature(wrapper, typeVariables, this.assistScope.enclosingClassScope().referenceContext.binding, null); assignableTypeBinding= BinaryTypeBinding.resolveType(assignableTypeBinding, this.lookupEnvironment, true); } catch (AbortCompilation e) { assignableTypeBinding= null; } finally { this.lookupEnvironment.unitBeingCompleted= previousUnitBeingCompleted; } return assignableTypeBinding; } private char[] replacePackagesDot(char[] signature) { boolean replace= true; int length= signature.length; for (int i= 0; i < length; i++) { switch (signature[i]) { case '.': if (replace) signature[i]= '/'; break; case '<': replace= true; break; case '>': replace= false; break; } } return signature; } public IJavaElement[] getVisibleElements(String typeSignature) { if (this.assistScope == null) return new IJavaElement[0]; if (!this.hasComputedVisibleElementBindings) { computeVisibleElementBindings(); } TypeBinding assignableTypeBinding= null; if (typeSignature != null) { assignableTypeBinding= getTypeFromSignature(typeSignature, this.assistScope); if (assignableTypeBinding == null) return new IJavaElement[0]; } int length= this.visibleLocalVariables.size() + this.visibleFields.size() + this.visibleMethods.size(); if (length == 0) return new IJavaElement[0]; IJavaElement[] result= new IJavaElement[length]; int elementCount= 0; int size= this.visibleLocalVariables.size(); if (size > 0) { next: for (int i= 0; i < size; i++) { try { LocalVariableBinding binding= (LocalVariableBinding)this.visibleLocalVariables.elementAt(i); if (assignableTypeBinding != null && !binding.type.isCompatibleWith(assignableTypeBinding)) continue next; JavaElement localVariable= getJavaElement(binding); if (localVariable != null) result[elementCount++]= localVariable; } catch (AbortCompilation e) { // log the exception and proceed Util.logRepeatedMessage(e.getKey(), e); } } } size= this.visibleFields.size(); if (size > 0) { next: for (int i= 0; i < size; i++) { try { FieldBinding binding= (FieldBinding)this.visibleFields.elementAt(i); if (assignableTypeBinding != null && !binding.type.isCompatibleWith(assignableTypeBinding)) continue next; if (this.assistScope.isDefinedInSameUnit(binding.declaringClass)) { JavaElement field= getJavaElementOfCompilationUnit(binding); if (field != null) result[elementCount++]= field; } else { JavaElement field= Util.getUnresolvedJavaElement(binding, this.owner, EmptyNodeMap); if (field != null) result[elementCount++]= field.resolved(binding); } } catch (AbortCompilation e) { // log the exception and proceed Util.logRepeatedMessage(e.getKey(), e); } } } size= this.visibleMethods.size(); if (size > 0) { next: for (int i= 0; i < size; i++) { try { MethodBinding binding= (MethodBinding)this.visibleMethods.elementAt(i); if (assignableTypeBinding != null && !binding.returnType.isCompatibleWith(assignableTypeBinding)) continue next; if (this.assistScope.isDefinedInSameUnit(binding.declaringClass)) { JavaElement method= getJavaElementOfCompilationUnit(binding); if (method != null) result[elementCount++]= method; } else { JavaElement method= Util.getUnresolvedJavaElement(binding, this.owner, EmptyNodeMap); if (method != null) result[elementCount++]= method.resolved(binding); } } catch (AbortCompilation e) { // log the exception and proceed Util.logRepeatedMessage(e.getKey(), e); } } } if (elementCount != result.length) { System.arraycopy(result, 0, result= new IJavaElement[elementCount], 0, elementCount); } return result; } private void searchVisibleFields( FieldBinding[] fields, ReferenceBinding receiverType, Scope scope, InvocationSite invocationSite, Scope invocationScope, boolean onlyStaticFields, ObjectVector localsFound, ObjectVector fieldsFound) { ObjectVector newFieldsFound= new ObjectVector(); // Inherited fields which are hidden by subclasses are filtered out // No visibility checks can be performed without the scope & invocationSite next: for (int f= fields.length; --f >= 0;) { FieldBinding field= fields[f]; if (field.isSynthetic()) continue next; if (onlyStaticFields && !field.isStatic()) continue next; if (!field.canBeSeenBy(receiverType, invocationSite, scope)) continue next; for (int i= fieldsFound.size; --i >= 0;) { FieldBinding otherField= (FieldBinding)fieldsFound.elementAt(i); if (CharOperation.equals(field.name, otherField.name, true)) { continue next; } } for (int l= localsFound.size; --l >= 0;) { LocalVariableBinding local= (LocalVariableBinding)localsFound.elementAt(l); if (CharOperation.equals(field.name, local.name, true)) { continue next; } } newFieldsFound.add(field); } fieldsFound.addAll(newFieldsFound); } private void searchVisibleFields( ReferenceBinding receiverType, Scope scope, InvocationSite invocationSite, Scope invocationScope, boolean onlyStaticFields, boolean notInJavadoc, ObjectVector localsFound, ObjectVector fieldsFound) { ReferenceBinding currentType= receiverType; ReferenceBinding[] interfacesToVisit= null; int nextPosition= 0; do { ReferenceBinding[] itsInterfaces= currentType.superInterfaces(); if (notInJavadoc && itsInterfaces != Binding.NO_SUPERINTERFACES) { if (interfacesToVisit == null) { interfacesToVisit= itsInterfaces; nextPosition= interfacesToVisit.length; } else { int itsLength= itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit= new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface: for (int a= 0; a < itsLength; a++) { ReferenceBinding next= itsInterfaces[a]; for (int b= 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++]= next; } } } FieldBinding[] fields= currentType.availableFields(); if (fields != null && fields.length > 0) { searchVisibleFields( fields, receiverType, scope, invocationSite, invocationScope, onlyStaticFields, localsFound, fieldsFound); } currentType= currentType.superclass(); } while (notInJavadoc && currentType != null); if (notInJavadoc && interfacesToVisit != null) { for (int i= 0; i < nextPosition; i++) { ReferenceBinding anInterface= interfacesToVisit[i]; FieldBinding[] fields= anInterface.availableFields(); if (fields != null) { searchVisibleFields( fields, receiverType, scope, invocationSite, invocationScope, onlyStaticFields, localsFound, fieldsFound); } ReferenceBinding[] itsInterfaces= anInterface.superInterfaces(); if (itsInterfaces != Binding.NO_SUPERINTERFACES) { int itsLength= itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit= new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface: for (int a= 0; a < itsLength; a++) { ReferenceBinding next= itsInterfaces[a]; for (int b= 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++]= next; } } } } } private void searchVisibleInterfaceMethods( ReferenceBinding[] itsInterfaces, ReferenceBinding receiverType, Scope scope, InvocationSite invocationSite, Scope invocationScope, boolean onlyStaticMethods, ObjectVector methodsFound) { if (itsInterfaces != Binding.NO_SUPERINTERFACES) { ReferenceBinding[] interfacesToVisit= itsInterfaces; int nextPosition= interfacesToVisit.length; for (int i= 0; i < nextPosition; i++) { ReferenceBinding currentType= interfacesToVisit[i]; MethodBinding[] methods= currentType.availableMethods(); if (methods != null) { searchVisibleLocalMethods( methods, receiverType, scope, invocationSite, invocationScope, onlyStaticMethods, methodsFound); } itsInterfaces= currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { int itsLength= itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit= new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface: for (int a= 0; a < itsLength; a++) { ReferenceBinding next= itsInterfaces[a]; for (int b= 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++]= next; } } } } } private void searchVisibleLocalMethods( MethodBinding[] methods, ReferenceBinding receiverType, Scope scope, InvocationSite invocationSite, Scope invocationScope, boolean onlyStaticMethods, ObjectVector methodsFound) { ObjectVector newMethodsFound= new ObjectVector(); // Inherited methods which are hidden by subclasses are filtered out // No visibility checks can be performed without the scope & invocationSite next: for (int f= methods.length; --f >= 0;) { MethodBinding method= methods[f]; if (method.isSynthetic()) continue next; if (method.isDefaultAbstract()) continue next; if (method.isConstructor()) continue next; if (onlyStaticMethods && !method.isStatic()) continue next; if (!method.canBeSeenBy(receiverType, invocationSite, scope)) continue next; for (int i= methodsFound.size; --i >= 0;) { MethodBinding otherMethod= (MethodBinding)methodsFound.elementAt(i); if (method == otherMethod) continue next; if (CharOperation.equals(method.selector, otherMethod.selector, true)) { if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { continue next; } } } newMethodsFound.add(method); } methodsFound.addAll(newMethodsFound); } private void searchVisibleMethods( ReferenceBinding receiverType, Scope scope, InvocationSite invocationSite, Scope invocationScope, boolean onlyStaticMethods, boolean notInJavadoc, ObjectVector methodsFound) { ReferenceBinding currentType= receiverType; if (notInJavadoc) { if (receiverType.isInterface()) { searchVisibleInterfaceMethods( new ReferenceBinding[] { currentType }, receiverType, scope, invocationSite, invocationScope, onlyStaticMethods, methodsFound); currentType= scope.getJavaLangObject(); } } boolean hasPotentialDefaultAbstractMethods= true; while (currentType != null) { MethodBinding[] methods= currentType.availableMethods(); if (methods != null) { searchVisibleLocalMethods( methods, receiverType, scope, invocationSite, invocationScope, onlyStaticMethods, methodsFound); } if (notInJavadoc && hasPotentialDefaultAbstractMethods && (currentType.isAbstract() || currentType.isTypeVariable() || currentType.isIntersectionType() || currentType.isEnum())) { ReferenceBinding[] superInterfaces= currentType.superInterfaces(); if (superInterfaces != null && currentType.isIntersectionType()) { for (int i= 0; i < superInterfaces.length; i++) { superInterfaces[i]= (ReferenceBinding)superInterfaces[i].capture(invocationScope, invocationSite.sourceEnd()); } } searchVisibleInterfaceMethods( superInterfaces, receiverType, scope, invocationSite, invocationScope, onlyStaticMethods, methodsFound); } else { hasPotentialDefaultAbstractMethods= false; } if (currentType.isParameterizedType()) { currentType= ((ParameterizedTypeBinding)currentType).genericType().superclass(); } else { currentType= currentType.superclass(); } } } private void searchVisibleVariablesAndMethods( Scope scope, ObjectVector localsFound, ObjectVector fieldsFound, ObjectVector methodsFound, boolean notInJavadoc) { InvocationSite invocationSite= CompletionEngine.FakeInvocationSite; boolean staticsOnly= false; // need to know if we're in a static context (or inside a constructor) Scope currentScope= scope; done1: while (true) { // done when a COMPILATION_UNIT_SCOPE is found switch (currentScope.kind) { case Scope.METHOD_SCOPE: // handle the error case inside an explicit constructor call (see MethodScope>>findField) MethodScope methodScope= (MethodScope)currentScope; staticsOnly|= methodScope.isStatic | methodScope.isConstructorCall; //$FALL-THROUGH$ case Scope.BLOCK_SCOPE: BlockScope blockScope= (BlockScope)currentScope; next: for (int i= 0, length= blockScope.locals.length; i < length; i++) { LocalVariableBinding local= blockScope.locals[i]; if (local == null) break next; if (local.isSecret()) continue next; // If the local variable declaration's initialization statement itself has the completion, // then don't propose the local variable if (local.declaration.initialization != null) { if (local.declaration.initialization.sourceEnd > 0) { if (this.assistNode.sourceEnd <= local.declaration.initialization.sourceEnd && this.assistNode.sourceStart >= local.declaration.initialization.sourceStart) { continue next; } } else { CompletionNodeDetector detector= new CompletionNodeDetector( this.assistNode, local.declaration.initialization); if (detector.containsCompletionNode()) { continue next; } } } for (int f= 0; f < localsFound.size; f++) { LocalVariableBinding otherLocal= (LocalVariableBinding)localsFound.elementAt(f); if (CharOperation.equals(otherLocal.name, local.name, true)) continue next; } localsFound.add(local); } break; case Scope.COMPILATION_UNIT_SCOPE: break done1; } currentScope= currentScope.parent; } staticsOnly= false; currentScope= scope; done2: while (true) { // done when a COMPILATION_UNIT_SCOPE is found switch (currentScope.kind) { case Scope.METHOD_SCOPE: // handle the error case inside an explicit constructor call (see MethodScope>>findField) MethodScope methodScope= (MethodScope)currentScope; staticsOnly|= methodScope.isStatic | methodScope.isConstructorCall; break; case Scope.CLASS_SCOPE: ClassScope classScope= (ClassScope)currentScope; SourceTypeBinding enclosingType= classScope.referenceContext.binding; searchVisibleFields( enclosingType, classScope, invocationSite, scope, staticsOnly, notInJavadoc, localsFound, fieldsFound); searchVisibleMethods( enclosingType, classScope, invocationSite, scope, staticsOnly, notInJavadoc, methodsFound); staticsOnly|= enclosingType.isStatic(); break; case Scope.COMPILATION_UNIT_SCOPE: break done2; } currentScope= currentScope.parent; } // search in static import ImportBinding[] importBindings= scope.compilationUnitScope().imports; for (int i= 0; i < importBindings.length; i++) { ImportBinding importBinding= importBindings[i]; if (importBinding.isValidBinding() && importBinding.isStatic()) { Binding binding= importBinding.resolvedImport; if (binding != null && binding.isValidBinding()) { if (importBinding.onDemand) { if ((binding.kind() & Binding.TYPE) != 0) { searchVisibleFields( (ReferenceBinding)binding, scope, invocationSite, scope, staticsOnly, notInJavadoc, localsFound, fieldsFound); searchVisibleMethods( (ReferenceBinding)binding, scope, invocationSite, scope, staticsOnly, notInJavadoc, methodsFound); } } else { if ((binding.kind() & Binding.FIELD) != 0) { searchVisibleFields( new FieldBinding[] { (FieldBinding)binding }, ((FieldBinding)binding).declaringClass, scope, invocationSite, scope, staticsOnly, localsFound, fieldsFound); } else if ((binding.kind() & Binding.METHOD) != 0) { MethodBinding methodBinding= (MethodBinding)binding; searchVisibleLocalMethods( methodBinding.declaringClass.getMethods(methodBinding.selector), methodBinding.declaringClass, scope, invocationSite, scope, true, methodsFound); } } } } } } }