1 11 package org.eclipse.jdt.internal.corext.dom; 12 13 import java.util.ArrayList ; 14 15 import org.eclipse.jdt.core.compiler.IProblem; 16 import org.eclipse.jdt.core.dom.ASTNode; 17 import org.eclipse.jdt.core.dom.ASTVisitor; 18 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; 19 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration; 20 import org.eclipse.jdt.core.dom.BreakStatement; 21 import org.eclipse.jdt.core.dom.CompilationUnit; 22 import org.eclipse.jdt.core.dom.ContinueStatement; 23 import org.eclipse.jdt.core.dom.EnumDeclaration; 24 import org.eclipse.jdt.core.dom.IBinding; 25 import org.eclipse.jdt.core.dom.IMethodBinding; 26 import org.eclipse.jdt.core.dom.ITypeBinding; 27 import org.eclipse.jdt.core.dom.IVariableBinding; 28 import org.eclipse.jdt.core.dom.LabeledStatement; 29 import org.eclipse.jdt.core.dom.MethodDeclaration; 30 import org.eclipse.jdt.core.dom.SimpleName; 31 import org.eclipse.jdt.core.dom.TypeDeclaration; 32 33 34 39 40 public class LinkedNodeFinder { 41 42 private LinkedNodeFinder() { 43 } 44 45 46 54 public static SimpleName[] findByBinding(ASTNode root, IBinding binding) { 55 ArrayList res= new ArrayList (); 56 BindingFinder nodeFinder= new BindingFinder(binding, res); 57 root.accept(nodeFinder); 58 return (SimpleName[]) res.toArray(new SimpleName[res.size()]); 59 } 60 61 69 public static SimpleName[] findByNode(ASTNode root, SimpleName name) { 70 IBinding binding = name.resolveBinding(); 71 if (binding != null) { 72 return findByBinding(root, binding); 73 } 74 SimpleName[] names= findByProblems(root, name); 75 if (names != null) { 76 return names; 77 } 78 int parentKind= name.getParent().getNodeType(); 79 if (parentKind == ASTNode.LABELED_STATEMENT || parentKind == ASTNode.BREAK_STATEMENT || parentKind == ASTNode.CONTINUE_STATEMENT) { 80 ArrayList res= new ArrayList (); 81 LabelFinder nodeFinder= new LabelFinder(name, res); 82 root.accept(nodeFinder); 83 return (SimpleName[]) res.toArray(new SimpleName[res.size()]); 84 } 85 return new SimpleName[] { name }; 86 } 87 88 89 90 private static final int FIELD= 1; 91 private static final int METHOD= 2; 92 private static final int TYPE= 4; 93 private static final int LABEL= 8; 94 private static final int NAME= FIELD | TYPE; 95 96 private static int getProblemKind(IProblem problem) { 97 switch (problem.getID()) { 98 case IProblem.UndefinedField: 99 return FIELD; 100 case IProblem.UndefinedMethod: 101 return METHOD; 102 case IProblem.UndefinedLabel: 103 return LABEL; 104 case IProblem.UndefinedName: 105 return NAME; 106 case IProblem.UndefinedType: 107 return TYPE; 108 } 109 return 0; 110 } 111 112 private static int getNameNodeProblemKind(IProblem[] problems, SimpleName nameNode) { 113 int nameOffset= nameNode.getStartPosition(); 114 int nameInclEnd= nameOffset + nameNode.getLength() - 1; 115 116 for (int i= 0; i < problems.length; i++) { 117 IProblem curr= problems[i]; 118 if (curr.getSourceStart() == nameOffset && curr.getSourceEnd() == nameInclEnd) { 119 int kind= getProblemKind(curr); 120 if (kind != 0) { 121 return kind; 122 } 123 } 124 } 125 return 0; 126 } 127 128 129 public static SimpleName[] findByProblems(ASTNode parent, SimpleName nameNode) { 130 ArrayList res= new ArrayList (); 131 132 ASTNode astRoot = parent.getRoot(); 133 if (!(astRoot instanceof CompilationUnit)) { 134 return null; 135 } 136 137 IProblem[] problems= ((CompilationUnit) astRoot).getProblems(); 138 int nameNodeKind= getNameNodeProblemKind(problems, nameNode); 139 if (nameNodeKind == 0) { return null; 141 } 142 143 int bodyStart= parent.getStartPosition(); 144 int bodyEnd= bodyStart + parent.getLength(); 145 146 String name= nameNode.getIdentifier(); 147 148 for (int i= 0; i < problems.length; i++) { 149 IProblem curr= problems[i]; 150 int probStart= curr.getSourceStart(); 151 int probEnd= curr.getSourceEnd() + 1; 152 153 if (probStart > bodyStart && probEnd < bodyEnd) { 154 int currKind= getProblemKind(curr); 155 if ((nameNodeKind & currKind) != 0) { 156 ASTNode node= NodeFinder.perform(parent, probStart, probEnd - probStart); 157 if (node instanceof SimpleName && name.equals(((SimpleName) node).getIdentifier())) { 158 res.add(node); 159 } 160 } 161 } 162 } 163 return (SimpleName[]) res.toArray(new SimpleName[res.size()]); 164 } 165 166 private static class LabelFinder extends ASTVisitor { 167 168 private SimpleName fLabel; 169 private ASTNode fDefiningLabel; 170 private ArrayList fResult; 171 172 public LabelFinder(SimpleName label, ArrayList result) { 173 super(true); 174 fLabel= label; 175 fResult= result; 176 fDefiningLabel= null; 177 } 178 179 private boolean isSameLabel(SimpleName label) { 180 return label != null && fLabel.getIdentifier().equals(label.getIdentifier()); 181 } 182 183 public boolean visit(BreakStatement node) { 184 SimpleName label= node.getLabel(); 185 if (fDefiningLabel != null && isSameLabel(label) && ASTNodes.isParent(label, fDefiningLabel)) { 186 fResult.add(label); 187 } 188 return false; 189 } 190 191 public boolean visit(ContinueStatement node) { 192 SimpleName label= node.getLabel(); 193 if (fDefiningLabel != null && isSameLabel(label) && ASTNodes.isParent(label, fDefiningLabel)) { 194 fResult.add(label); 195 } 196 return false; 197 } 198 199 public boolean visit(LabeledStatement node) { 200 if (fDefiningLabel == null) { 201 SimpleName label= node.getLabel(); 202 if (fLabel == label || isSameLabel(label) && ASTNodes.isParent(fLabel, node)) { 203 fDefiningLabel= node; 204 fResult.add(label); 205 } 206 } 207 node.getBody().accept(this); 208 return false; 209 } 210 } 211 212 private static class BindingFinder extends ASTVisitor { 213 214 private IBinding fBinding; 215 private ArrayList fResult; 216 217 public BindingFinder(IBinding binding, ArrayList result) { 218 super(true); 219 fBinding= getDeclaration(binding); 220 fResult= result; 221 } 222 223 public boolean visit(MethodDeclaration node) { 224 if (node.isConstructor() && fBinding.getKind() == IBinding.TYPE) { 225 ASTNode typeNode= node.getParent(); 226 if (typeNode instanceof AbstractTypeDeclaration) { 227 if (fBinding == ((AbstractTypeDeclaration) typeNode).resolveBinding()) { 228 fResult.add(node.getName()); 229 } 230 } 231 } 232 return true; 233 } 234 235 public boolean visit(TypeDeclaration node) { 236 if (fBinding.getKind() == IBinding.METHOD) { 237 IMethodBinding binding= (IMethodBinding) fBinding; 238 if (binding.isConstructor() && binding.getDeclaringClass() == node.resolveBinding()) { 239 fResult.add(node.getName()); 240 } 241 } 242 return true; 243 } 244 245 public boolean visit(EnumDeclaration node) { 246 if (fBinding.getKind() == IBinding.METHOD) { 247 IMethodBinding binding= (IMethodBinding) fBinding; 248 if (binding.isConstructor() && binding.getDeclaringClass() == node.resolveBinding()) { 249 fResult.add(node.getName()); 250 } 251 } 252 return true; 253 } 254 255 public boolean visit(AnnotationTypeDeclaration node) { 256 return true; 258 } 259 260 public boolean visit(SimpleName node) { 261 IBinding binding= node.resolveBinding(); 262 if (binding == null || binding.getKind() != fBinding.getKind()) { 263 return false; 264 } 265 binding= getDeclaration(binding); 266 267 if (fBinding == binding) { 268 fResult.add(node); 269 } else if (binding.getKind() == IBinding.METHOD) { 270 IMethodBinding curr= (IMethodBinding) binding; 271 IMethodBinding methodBinding= (IMethodBinding) fBinding; 272 if (methodBinding.overrides(curr) || curr.overrides(methodBinding)) { 273 fResult.add(node); 274 } 275 } 276 return false; 277 } 278 279 private static IBinding getDeclaration(IBinding binding) { 280 if (binding instanceof ITypeBinding) { 281 return ((ITypeBinding) binding).getTypeDeclaration(); 282 } else if (binding instanceof IMethodBinding) { 283 return ((IMethodBinding) binding).getMethodDeclaration(); 284 } else if (binding instanceof IVariableBinding) { 285 return ((IVariableBinding) binding).getVariableDeclaration(); 286 } 287 return binding; 288 } 289 } 290 } 291 | Popular Tags |