1 11 package org.eclipse.jdt.internal.corext.dom; 12 13 import java.util.ArrayList ; 14 import java.util.Iterator ; 15 import java.util.List ; 16 17 import org.eclipse.jdt.core.dom.*; 18 import org.eclipse.jdt.core.dom.ASTNode; 19 import org.eclipse.jdt.core.dom.ASTVisitor; 20 import org.eclipse.jdt.core.dom.Block; 21 import org.eclipse.jdt.core.dom.BodyDeclaration; 22 import org.eclipse.jdt.core.dom.Expression; 23 import org.eclipse.jdt.core.dom.ForStatement; 24 import org.eclipse.jdt.core.dom.IBinding; 25 import org.eclipse.jdt.core.dom.MethodInvocation; 26 import org.eclipse.jdt.core.dom.QualifiedName; 27 import org.eclipse.jdt.core.dom.SimpleName; 28 import org.eclipse.jdt.core.dom.TypeDeclarationStatement; 29 30 31 public class CodeScopeBuilder extends ASTVisitor { 32 33 public static class Scope { 34 private Scope fParent; 35 private int fStart; 36 private int fLength; 37 private List fNames; 38 private List fChildren; 39 private int fCursorOffset; 40 Scope(Scope parent, int start, int length) { 41 fParent= parent; 42 fStart= start; 43 fLength= length; 44 if (fParent != null) 45 fParent.addChild(this); 46 } 47 public void setCursor(int offset) { 48 fCursorOffset= offset; 49 } 50 private void addChild(Scope child) { 51 if (fChildren == null) 52 fChildren= new ArrayList (2); 53 fChildren.add(child); 54 } 55 private void addName(String name) { 56 if (fNames == null) 57 fNames= new ArrayList (2); 58 fNames.add(name); 59 } 60 public Scope findScope(int start, int length) { 61 if (fStart <= start && start + length <= fStart + fLength) { 62 if (fChildren == null) 63 return this; 64 for (Iterator iter= fChildren.iterator(); iter.hasNext();) { 65 Scope scope= ((Scope)iter.next()).findScope(start, length); 66 if (scope != null) 67 return scope; 68 } 69 return this; 70 } 71 return null; 72 } 73 public String createName(String candidate, boolean add) { 74 int i= 1; 75 String result= candidate; 76 while(isInUse(result)) { 77 result= candidate + i++; 78 } 79 if (add) 80 addName(result); 81 return result; 82 } 83 public boolean isInUse(String name) { 84 if (internalIsInUse(name)) 85 return true; 86 if (fChildren != null) { 87 for (Iterator iter= fChildren.iterator(); iter.hasNext();) { 88 Scope child= (Scope) iter.next(); 89 if (fCursorOffset < child.fStart && child.isInUseDown(name)) { 90 return true; 91 } 92 } 93 } 94 return false; 95 } 96 private boolean internalIsInUse(String name) { 97 if (fNames != null && fNames.contains(name)) 98 return true; 99 if (fParent != null) 100 return fParent.internalIsInUse(name); 101 return false; 102 103 } 104 private boolean isInUseDown(String name) { 105 if (fNames != null && fNames.contains(name)) 106 return true; 107 if (fChildren == null) 108 return false; 109 for (Iterator iter= fChildren.iterator(); iter.hasNext();) { 110 Scope scope= (Scope) iter.next(); 111 if (scope.isInUseDown(name)) 112 return true; 113 } 114 return false; 115 } 116 } 117 118 private IBinding fIgnoreBinding; 119 private Selection fIgnoreRange; 120 private Scope fScope; 121 private List fScopes; 122 123 public static Scope perform(BodyDeclaration node, IBinding ignore) { 124 CodeScopeBuilder collector= new CodeScopeBuilder(node, ignore); 125 node.accept(collector); 126 return collector.fScope; 127 } 128 129 public static Scope perform(BodyDeclaration node, Selection ignore) { 130 CodeScopeBuilder collector= new CodeScopeBuilder(node, ignore); 131 node.accept(collector); 132 return collector.fScope; 133 } 134 135 private CodeScopeBuilder(ASTNode node, IBinding ignore) { 136 fScope= new Scope(null, node.getStartPosition(), node.getLength()); 137 fScopes= new ArrayList (); 138 fIgnoreBinding= ignore; 139 } 140 141 private CodeScopeBuilder(ASTNode node, Selection ignore) { 142 fScope= new Scope(null, node.getStartPosition(), node.getLength()); 143 fScopes= new ArrayList (); 144 fIgnoreRange= ignore; 145 } 146 147 public boolean visit(CatchClause node) { 148 fScopes.add(fScope); 150 fScope= new Scope(fScope, node.getStartPosition(), node.getLength()); 151 return true; 152 } 153 154 public void endVisit(CatchClause node) { 155 fScope= (Scope)fScopes.remove(fScopes.size() - 1); 156 } 157 158 public boolean visit(SimpleName node) { 159 if (fIgnoreBinding != null && Bindings.equals(fIgnoreBinding, node.resolveBinding())) 160 return false; 161 if (fIgnoreRange != null && fIgnoreRange.covers(node)) 162 return false; 163 fScope.addName(node.getIdentifier()); 164 return false; 165 } 166 167 public boolean visit(QualifiedName node) { 168 node.getQualifier().accept(this); 170 return false; 171 } 172 173 public boolean visit(MethodInvocation node) { 174 Expression receiver= node.getExpression(); 175 if (receiver == null) { 176 SimpleName name= node.getName(); 177 if (fIgnoreBinding == null || !Bindings.equals(fIgnoreBinding, name.resolveBinding())) 178 node.getName().accept(this); 179 } else { 180 receiver.accept(this); 181 } 182 accept(node.arguments()); 183 return false; 184 } 185 186 public boolean visit(TypeDeclarationStatement node) { 187 if (node.getAST().apiLevel() == AST.JLS2) { 188 fScope.addName(node.getTypeDeclaration().getName().getIdentifier()); 189 } else { 190 fScope.addName(node.getDeclaration().getName().getIdentifier()); 191 } 192 return false; 193 } 194 195 public boolean visit(Block node) { 196 fScopes.add(fScope); 197 fScope= new Scope(fScope, node.getStartPosition(), node.getLength()); 198 return true; 199 } 200 201 public void endVisit(Block node) { 202 fScope= (Scope)fScopes.remove(fScopes.size() - 1); 203 } 204 205 public boolean visit(ForStatement node) { 206 fScopes.add(fScope); 207 fScope= new Scope(fScope, node.getStartPosition(), node.getLength()); 208 return true; 209 } 210 211 public void endVisit(ForStatement node) { 212 fScope= (Scope)fScopes.remove(fScopes.size() - 1); 213 } 214 215 private void accept(List list) { 216 int size; 217 if (list == null || (size= list.size()) == 0) 218 return; 219 for (int i= 0; i < size; i++) { 220 ((ASTNode)list.get(i)).accept(this); 221 } 222 } 223 } 224 | Popular Tags |