1 /*******************************************************************************
2 * Copyright (c) 2000, 2012 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.corext.dom;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.HashSet;
16 import java.util.List;
18 import org.eclipse.jdt.core.dom.ASTNode;
19 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
20 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
21 import org.eclipse.jdt.core.dom.Block;
22 import org.eclipse.jdt.core.dom.BodyDeclaration;
23 import org.eclipse.jdt.core.dom.CatchClause;
24 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
25 import org.eclipse.jdt.core.dom.CompilationUnit;
26 import org.eclipse.jdt.core.dom.Expression;
27 import org.eclipse.jdt.core.dom.FieldAccess;
28 import org.eclipse.jdt.core.dom.ForStatement;
29 import org.eclipse.jdt.core.dom.IBinding;
30 import org.eclipse.jdt.core.dom.IMethodBinding;
31 import org.eclipse.jdt.core.dom.ITypeBinding;
32 import org.eclipse.jdt.core.dom.IVariableBinding;
33 import org.eclipse.jdt.core.dom.ImportDeclaration;
34 import org.eclipse.jdt.core.dom.Initializer;
35 import org.eclipse.jdt.core.dom.MethodDeclaration;
36 import org.eclipse.jdt.core.dom.MethodInvocation;
37 import org.eclipse.jdt.core.dom.Modifier;
38 import org.eclipse.jdt.core.dom.QualifiedName;
39 import org.eclipse.jdt.core.dom.SimpleName;
40 import org.eclipse.jdt.core.dom.Statement;
41 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
42 import org.eclipse.jdt.core.dom.SwitchCase;
43 import org.eclipse.jdt.core.dom.SwitchStatement;
44 import org.eclipse.jdt.core.dom.Type;
45 import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
46 import org.eclipse.jdt.core.dom.TypeParameter;
47 import org.eclipse.jdt.core.dom.VariableDeclaration;
48 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
49 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
51 import org.eclipse.jdt.internal.ui.text.correction.ASTResolving;
54 * Evaluates all fields, methods and types available (declared) at a given offset
55 * in a compilation unit (Code assist that returns IBindings)
57 public class ScopeAnalyzer {
59 private static final IBinding[] NO_BINDING= new IBinding[0];
62 * Flag to specify that method should be reported.
64 public static final int METHODS= 1;
67 * Flag to specify that variables should be reported.
69 public static final int VARIABLES= 2;
72 * Flag to specify that types should be reported.
74 public static final int TYPES= 4;
77 * Flag to specify that only visible elements should be added.
79 public static final int CHECK_VISIBILITY= 16;
81 private static interface IBindingRequestor {
82 boolean acceptBinding(IBinding binding);
85 private static class DefaultBindingRequestor implements IBindingRequestor {
87 private final List<IBinding> fResult;
88 private final HashSet<String> fNamesAdded;
89 private final int fFlags;
90 private final ITypeBinding fParentTypeBinding;
92 public DefaultBindingRequestor(ITypeBinding parentTypeBinding, int flags) {
93 fParentTypeBinding= parentTypeBinding;
95 fResult= new ArrayList<IBinding>();
96 fNamesAdded= new HashSet<String>();
99 public DefaultBindingRequestor() {
106 public boolean acceptBinding(IBinding binding) {
110 String signature= getSignature(binding);
111 if (signature != null && fNamesAdded.add(signature)) { // avoid duplicated results from inheritance
112 fResult.add(binding);
117 public List<IBinding> getResult() {
118 if (hasFlag(CHECK_VISIBILITY, fFlags)) {
119 for (int i= fResult.size() - 1; i >= 0; i--) {
120 IBinding binding= fResult.get(i);
121 if (!isVisible(binding, fParentTypeBinding)) {
131 private final HashSet<ITypeBinding> fTypesVisited;
133 private final CompilationUnit fRoot;
135 public ScopeAnalyzer(CompilationUnit root) {
136 fTypesVisited= new HashSet<ITypeBinding>();
140 private void clearLists() {
141 fTypesVisited.clear();
144 private static String getSignature(IBinding binding) {
145 if (binding != null) {
146 switch (binding.getKind()) {
147 case IBinding.METHOD:
148 StringBuffer buf= new StringBuffer();
150 buf.append(binding.getName()).append('(');
151 ITypeBinding[] parameters= ((IMethodBinding) binding).getParameterTypes();
152 for (int i= 0; i < parameters.length; i++) {
156 ITypeBinding paramType= parameters[i].getErasure();
157 buf.append(paramType.getQualifiedName());
160 return buf.toString();
161 case IBinding.VARIABLE:
162 return 'V' + binding.getName();
164 return 'T' + binding.getName();
170 static final boolean hasFlag(int property, int flags) {
171 return (flags & property) != 0;
175 * Collects all elements available in a type and its hierarchy
176 * @param binding The type binding
177 * @param flags Flags defining the elements to report
178 * @param requestor the requestor to which all results are reported
179 * @return return <code>true</code> if the requestor has reported the binding as found and no further results are required
181 private boolean addInherited(ITypeBinding binding, int flags, IBindingRequestor requestor) {
182 if (!fTypesVisited.add(binding)) {
185 if (hasFlag(VARIABLES, flags)) {
186 IVariableBinding[] variableBindings= binding.getDeclaredFields();
187 for (int i= 0; i < variableBindings.length; i++) {
188 if (requestor.acceptBinding(variableBindings[i]))
193 if (hasFlag(METHODS, flags)) {
194 IMethodBinding[] methodBindings= binding.getDeclaredMethods();
195 for (int i= 0; i < methodBindings.length; i++) {
196 IMethodBinding curr= methodBindings[i];
197 if (!curr.isSynthetic() && !curr.isConstructor()) {
198 if (requestor.acceptBinding(curr))
204 if (hasFlag(TYPES, flags)) {
205 ITypeBinding[] typeBindings= binding.getDeclaredTypes();
206 for (int i= 0; i < typeBindings.length; i++) {
207 ITypeBinding curr= typeBindings[i];
208 if (requestor.acceptBinding(curr))
214 ITypeBinding superClass= binding.getSuperclass();
215 if (superClass != null) {
216 if (addInherited(superClass, flags, requestor)) // recursive
218 } else if (binding.isArray()) {
219 if (addInherited(fRoot.getAST().resolveWellKnownType("java.lang.Object"), flags, requestor)) //$NON-NLS-1$
223 ITypeBinding[] interfaces= binding.getInterfaces(); // includes looking for methods: abstract, unimplemented methods
224 for (int i= 0; i < interfaces.length; i++) {
225 if (addInherited(interfaces[i], flags, requestor)) // recursive
233 * Collects all elements available in a type: its hierarchy and its outer scopes.
234 * @param binding The type binding
235 * @param flags Flags defining the elements to report
236 * @param requestor the requestor to which all results are reported
237 * @return return <code>true</code> if the requestor has reported the binding as found and no further results are required
239 private boolean addTypeDeclarations(ITypeBinding binding, int flags, IBindingRequestor requestor) {
240 if (hasFlag(TYPES, flags) && !binding.isAnonymous()) {
241 if (requestor.acceptBinding(binding))
244 ITypeBinding[] typeParameters= binding.getTypeParameters();
245 for (int i= 0; i < typeParameters.length; i++) {
246 if (requestor.acceptBinding(typeParameters[i]))
251 addInherited(binding, flags, requestor); // add inherited
253 if (binding.isLocal()) {
254 addOuterDeclarationsForLocalType(binding, flags, requestor);
256 ITypeBinding declaringClass= binding.getDeclaringClass();
257 if (declaringClass != null) {
258 if (addTypeDeclarations(declaringClass, flags, requestor)) // Recursively add inherited
260 } else if (hasFlag(TYPES, flags)) {
261 if (fRoot.findDeclaringNode(binding) != null) {
262 List<AbstractTypeDeclaration> types= fRoot.types();
263 for (int i= 0; i < types.size(); i++) {
264 if (requestor.acceptBinding(types.get(i).resolveBinding()))
273 private boolean addOuterDeclarationsForLocalType(ITypeBinding localBinding, int flags, IBindingRequestor requestor) {
274 ASTNode node= fRoot.findDeclaringNode(localBinding);
279 if (node instanceof AbstractTypeDeclaration || node instanceof AnonymousClassDeclaration) {
280 if (addLocalDeclarations(node.getParent(), flags, requestor))
283 ITypeBinding parentTypeBinding= Bindings.getBindingOfParentType(node.getParent());
284 if (parentTypeBinding != null) {
285 if (addTypeDeclarations(parentTypeBinding, flags, requestor))
293 private static ITypeBinding getBinding(Expression node) {
295 return node.resolveTypeBinding();
300 private static ITypeBinding getQualifier(SimpleName selector) {
301 ASTNode parent= selector.getParent();
302 switch (parent.getNodeType()) {
303 case ASTNode.METHOD_INVOCATION:
304 MethodInvocation decl= (MethodInvocation) parent;
305 if (selector == decl.getName()) {
306 return getBinding(decl.getExpression());
309 case ASTNode.QUALIFIED_NAME:
310 QualifiedName qualifiedName= (QualifiedName) parent;
311 if (selector == qualifiedName.getName()) {
312 return getBinding(qualifiedName.getQualifier());
315 case ASTNode.FIELD_ACCESS:
316 FieldAccess fieldAccess= (FieldAccess) parent;
317 if (selector == fieldAccess.getName()) {
318 return getBinding(fieldAccess.getExpression());
321 case ASTNode.SUPER_FIELD_ACCESS: {
322 ITypeBinding curr= Bindings.getBindingOfParentType(parent);
323 return curr.getSuperclass();
325 case ASTNode.SUPER_METHOD_INVOCATION: {
326 SuperMethodInvocation superInv= (SuperMethodInvocation) parent;
327 if (selector == superInv.getName()) {
328 ITypeBinding curr= Bindings.getBindingOfParentType(parent);
329 return curr.getSuperclass();
334 if (parent instanceof Type) {
335 // bug 67644: in 'a.new X()', all member types of A are visible as location of X.
336 ASTNode normalizedNode= ASTNodes.getNormalizedNode(parent);
337 if (normalizedNode.getLocationInParent() == ClassInstanceCreation.TYPE_PROPERTY) {
338 ClassInstanceCreation creation= (ClassInstanceCreation) normalizedNode.getParent();
339 return getBinding(creation.getExpression());
346 public IBinding[] getDeclarationsInScope(SimpleName selector, int flags) {
348 // special case for switch on enum
349 if (selector.getLocationInParent() == SwitchCase.EXPRESSION_PROPERTY) {
350 ITypeBinding binding= ((SwitchStatement) selector.getParent().getParent()).getExpression().resolveTypeBinding();
351 if (binding != null && binding.isEnum()) {
352 return getEnumContants(binding);
356 ITypeBinding parentTypeBinding= Bindings.getBindingOfParentType(selector);
357 if (parentTypeBinding != null) {
358 ITypeBinding binding= getQualifier(selector);
359 DefaultBindingRequestor requestor= new DefaultBindingRequestor(parentTypeBinding, flags);
360 if (binding == null) {
361 addLocalDeclarations(selector, flags, requestor);
362 addTypeDeclarations(parentTypeBinding, flags, requestor);
364 addInherited(binding, flags, requestor);
367 List<IBinding> result= requestor.getResult();
368 return result.toArray(new IBinding[result.size()]);
376 private static class SearchRequestor implements IBindingRequestor {
378 private final int fFlags;
379 private final ITypeBinding fParentTypeBinding;
380 private final IBinding fToSearch;
381 private boolean fFound;
382 private boolean fIsVisible;
384 public SearchRequestor(IBinding toSearch, ITypeBinding parentTypeBinding, int flag) {
387 fParentTypeBinding= parentTypeBinding;
392 public boolean acceptBinding(IBinding binding) {
399 if (fToSearch.getKind() != binding.getKind()) {
403 boolean checkVisibility= hasFlag(CHECK_VISIBILITY, fFlags);
404 if (binding == fToSearch) {
407 IBinding bindingDeclaration= Bindings.getDeclaration(binding);
408 if (bindingDeclaration == fToSearch) {
410 } else if (bindingDeclaration.getName().equals(fToSearch.getName())) {
411 String signature= getSignature(bindingDeclaration);
412 if (signature != null && signature.equals(getSignature(fToSearch))) {
413 if (checkVisibility) {
416 return true; // found element that hides the binding to find
421 if (fFound && checkVisibility) {
422 fIsVisible= ScopeAnalyzer.isVisible(binding, fParentTypeBinding);
427 public boolean found() {
431 public boolean isVisible() {
436 public boolean isDeclaredInScope(IBinding declaration, SimpleName selector, int flags) {
438 // special case for switch on enum
439 if (selector.getLocationInParent() == SwitchCase.EXPRESSION_PROPERTY) {
440 ITypeBinding binding= ((SwitchStatement) selector.getParent().getParent()).getExpression().resolveTypeBinding();
441 if (binding != null && binding.isEnum()) {
442 return hasEnumContants(declaration, binding.getTypeDeclaration());
446 ITypeBinding parentTypeBinding= Bindings.getBindingOfParentTypeContext(selector);
447 if (parentTypeBinding != null) {
448 ITypeBinding binding= getQualifier(selector);
449 SearchRequestor requestor= new SearchRequestor(declaration, parentTypeBinding, flags);
450 if (binding == null) {
451 addLocalDeclarations(selector, flags, requestor);
452 if (requestor.found())
453 return requestor.isVisible();
454 addTypeDeclarations(parentTypeBinding, flags, requestor);
455 if (requestor.found())
456 return requestor.isVisible();
458 addInherited(binding, flags, requestor);
459 if (requestor.found())
460 return requestor.isVisible();
469 private IVariableBinding[] getEnumContants(ITypeBinding binding) {
470 IVariableBinding[] declaredFields= binding.getDeclaredFields();
471 ArrayList<IVariableBinding> res= new ArrayList<IVariableBinding>(declaredFields.length);
472 for (int i= 0; i < declaredFields.length; i++) {
473 IVariableBinding curr= declaredFields[i];
474 if (curr.isEnumConstant()) {
478 return res.toArray(new IVariableBinding[res.size()]);
481 private boolean hasEnumContants(IBinding declaration, ITypeBinding binding) {
482 IVariableBinding[] declaredFields= binding.getDeclaredFields();
483 for (int i= 0; i < declaredFields.length; i++) {
484 IVariableBinding curr= declaredFields[i];
485 if (curr == declaration)
491 public IBinding[] getDeclarationsInScope(int offset, int flags) {
492 org.eclipse.jdt.core.dom.NodeFinder finder= new org.eclipse.jdt.core.dom.NodeFinder(fRoot, offset, 0);
493 ASTNode node= finder.getCoveringNode();
498 if (node instanceof SimpleName) {
499 return getDeclarationsInScope((SimpleName) node, flags);
503 ITypeBinding binding= Bindings.getBindingOfParentType(node);
504 DefaultBindingRequestor requestor= new DefaultBindingRequestor(binding, flags);
505 addLocalDeclarations(node, offset, flags, requestor);
506 if (binding != null) {
507 addTypeDeclarations(binding, flags, requestor);
509 List<IBinding> result= requestor.getResult();
510 return result.toArray(new IBinding[result.size()]);
516 private static ITypeBinding getDeclaringType(IBinding binding) {
517 switch (binding.getKind()) {
518 case IBinding.VARIABLE:
519 return ((IVariableBinding) binding).getDeclaringClass();
520 case IBinding.METHOD:
521 return ((IMethodBinding) binding).getDeclaringClass();
523 ITypeBinding typeBinding= (ITypeBinding) binding;
524 if (typeBinding.getDeclaringClass() != null) {
533 * Evaluates if the declaration is visible in a certain context.
534 * @param binding The binding of the declaration to examine
535 * @param context The context to test in
538 public static boolean isVisible(IBinding binding, ITypeBinding context) {
539 if (binding.getKind() == IBinding.VARIABLE && !((IVariableBinding) binding).isField()) {
540 return true; // all local variables found are visible
542 ITypeBinding declaring= getDeclaringType(binding);
543 if (declaring == null) {
547 declaring= declaring.getTypeDeclaration();
549 int modifiers= binding.getModifiers();
550 if (Modifier.isPublic(modifiers) || declaring.isInterface()) {
552 } else if (Modifier.isProtected(modifiers) || !Modifier.isPrivate(modifiers)) {
553 if (declaring.getPackage() == context.getPackage()) {
556 return isTypeInScope(declaring, context, Modifier.isProtected(modifiers));
558 // private visibility
559 return isTypeInScope(declaring, context, false);
562 private static boolean isTypeInScope(ITypeBinding declaring, ITypeBinding context, boolean includeHierarchy) {
563 ITypeBinding curr= context.getTypeDeclaration();
564 while (curr != null && curr != declaring) {
565 if (includeHierarchy && isInSuperTypeHierarchy(declaring, curr)) {
568 curr= curr.getDeclaringClass();
570 return curr == declaring;
574 * This method is different from Binding.isSuperType as type declarations are compared
576 private static boolean isInSuperTypeHierarchy(ITypeBinding possibleSuperTypeDecl, ITypeBinding type) {
577 if (type == possibleSuperTypeDecl) {
580 ITypeBinding superClass= type.getSuperclass();
581 if (superClass != null) {
582 if (isInSuperTypeHierarchy(possibleSuperTypeDecl, superClass.getTypeDeclaration())) {
586 if (possibleSuperTypeDecl.isInterface()) {
587 ITypeBinding[] superInterfaces= type.getInterfaces();
588 for (int i= 0; i < superInterfaces.length; i++) {
589 if (isInSuperTypeHierarchy(possibleSuperTypeDecl, superInterfaces[i].getTypeDeclaration())) {
598 public IBinding[] getDeclarationsAfter(int offset, int flags) {
600 org.eclipse.jdt.core.dom.NodeFinder finder= new org.eclipse.jdt.core.dom.NodeFinder(fRoot, offset, 0);
601 ASTNode node= finder.getCoveringNode();
606 ASTNode declaration= ASTResolving.findParentStatement(node);
607 while (declaration instanceof Statement && declaration.getNodeType() != ASTNode.BLOCK) {
608 declaration= declaration.getParent();
611 if (declaration instanceof Block) {
612 DefaultBindingRequestor requestor= new DefaultBindingRequestor();
613 DeclarationsAfterVisitor visitor= new DeclarationsAfterVisitor(node.getStartPosition(), flags, requestor);
614 declaration.accept(visitor);
615 List<IBinding> result= requestor.getResult();
616 return result.toArray(new IBinding[result.size()]);
625 private class ScopeAnalyzerVisitor extends HierarchicalASTVisitor {
627 private final int fPosition;
628 private final int fFlags;
629 private final IBindingRequestor fRequestor;
630 private boolean fBreak;
632 public ScopeAnalyzerVisitor(int position, int flags, IBindingRequestor requestor) {
635 fRequestor= requestor;
639 private boolean isInside(ASTNode node) {
640 int start= node.getStartPosition();
641 int end= start + node.getLength();
643 return start <= fPosition && fPosition < end;
647 public boolean visit(MethodDeclaration node) {
648 if (isInside(node)) {
649 Block body= node.getBody();
653 visitBackwards(node.parameters());
654 visitBackwards(node.typeParameters());
661 * @see org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor#visit(org.eclipse.jdt.core.dom.TypeParameter)
664 public boolean visit(TypeParameter node) {
665 if (hasFlag(TYPES, fFlags) && node.getStartPosition() < fPosition) {
666 fBreak= fRequestor.acceptBinding(node.getName().resolveBinding());
672 public boolean visit(SwitchCase node) {
673 // switch on enum allows to use enum constants without qualification
674 if (hasFlag(VARIABLES, fFlags) && !node.isDefault() && isInside(node.getExpression())) {
675 SwitchStatement switchStatement= (SwitchStatement) node.getParent();
676 ITypeBinding binding= switchStatement.getExpression().resolveTypeBinding();
677 if (binding != null && binding.isEnum()) {
678 IVariableBinding[] declaredFields= binding.getDeclaredFields();
679 for (int i= 0; i < declaredFields.length; i++) {
680 IVariableBinding curr= declaredFields[i];
681 if (curr.isEnumConstant()) {
682 fBreak= fRequestor.acceptBinding(curr);
693 public boolean visit(Initializer node) {
694 return !fBreak && isInside(node);
698 public boolean visit(Statement node) {
699 return !fBreak && isInside(node);
703 public boolean visit(ASTNode node) {
708 public boolean visit(Block node) {
709 if (isInside(node)) {
710 visitBackwards(node.statements());
716 public boolean visit(VariableDeclaration node) {
717 if (hasFlag(VARIABLES, fFlags) && node.getStartPosition() < fPosition) {
718 fBreak= fRequestor.acceptBinding(node.resolveBinding());
724 public boolean visit(VariableDeclarationStatement node) {
725 visitBackwards(node.fragments());
730 public boolean visit(VariableDeclarationExpression node) {
731 visitBackwards(node.fragments());
736 public boolean visit(CatchClause node) {
737 if (isInside(node)) {
738 node.getBody().accept(this);
739 node.getException().accept(this);
745 public boolean visit(ForStatement node) {
746 if (isInside(node)) {
747 node.getBody().accept(this);
748 visitBackwards(node.initializers());
754 public boolean visit(TypeDeclarationStatement node) {
755 if (hasFlag(TYPES, fFlags) && node.getStartPosition() + node.getLength() < fPosition) {
756 fBreak= fRequestor.acceptBinding(node.resolveBinding());
759 return !fBreak && isInside(node);
762 private void visitBackwards(List<? extends ASTNode> list) {
766 for (int i= list.size() - 1; i >= 0; i--) {
767 ASTNode curr= list.get(i);
768 if (curr.getStartPosition() < fPosition) {
775 private class DeclarationsAfterVisitor extends HierarchicalASTVisitor {
776 private final int fPosition;
777 private final int fFlags;
778 private final IBindingRequestor fRequestor;
779 private boolean fBreak;
781 public DeclarationsAfterVisitor(int position, int flags, IBindingRequestor requestor) {
784 fRequestor= requestor;
789 public boolean visit(ASTNode node) {
794 public boolean visit(VariableDeclaration node) {
795 if (hasFlag(VARIABLES, fFlags) && fPosition < node.getStartPosition()) {
796 fBreak= fRequestor.acceptBinding(node.resolveBinding());
802 public boolean visit(AnonymousClassDeclaration node) {
807 public boolean visit(TypeDeclarationStatement node) {
808 if (hasFlag(TYPES, fFlags) && fPosition < node.getStartPosition()) {
809 fBreak= fRequestor.acceptBinding(node.resolveBinding());
815 private boolean addLocalDeclarations(ASTNode node, int flags, IBindingRequestor requestor) {
816 return addLocalDeclarations(node, node.getStartPosition(), flags, requestor);
820 private boolean addLocalDeclarations(ASTNode node, int offset, int flags, IBindingRequestor requestor) {
821 if (hasFlag(VARIABLES, flags) || hasFlag(TYPES, flags)) {
822 BodyDeclaration declaration= ASTResolving.findParentBodyDeclaration(node);
823 if (declaration instanceof MethodDeclaration || declaration instanceof Initializer) {
824 ScopeAnalyzerVisitor visitor= new ScopeAnalyzerVisitor(offset, flags, requestor);
825 declaration.accept(visitor);
826 return visitor.fBreak;
832 public Collection<String> getUsedVariableNames(int offset, int length) {
833 HashSet<String> result= new HashSet<String>();
834 IBinding[] bindingsBefore= getDeclarationsInScope(offset, VARIABLES);
835 for (int i= 0; i < bindingsBefore.length; i++) {
836 result.add(bindingsBefore[i].getName());
838 IBinding[] bindingsAfter= getDeclarationsAfter(offset + length, VARIABLES);
839 for (int i= 0; i < bindingsAfter.length; i++) {
840 result.add(bindingsAfter[i].getName());
842 List<ImportDeclaration> imports= fRoot.imports();
843 for (int i= 0; i < imports.size(); i++) {
844 ImportDeclaration decl= imports.get(i);
845 if (decl.isStatic() && !decl.isOnDemand()) {
846 result.add(ASTNodes.getSimpleNameIdentifier(decl.getName()));