1 11 package org.eclipse.jdt.internal.core.search.matching; 12 13 import org.eclipse.core.resources.IResource; 14 import org.eclipse.core.runtime.CoreException; 15 import org.eclipse.jdt.core.*; 16 import org.eclipse.jdt.core.compiler.CharOperation; 17 import org.eclipse.jdt.core.search.*; 18 import org.eclipse.jdt.internal.compiler.ast.*; 19 import org.eclipse.jdt.internal.compiler.env.IBinaryType; 20 import org.eclipse.jdt.internal.compiler.lookup.*; 21 import org.eclipse.jdt.internal.compiler.util.SimpleSet; 22 import org.eclipse.jdt.internal.core.JavaElement; 23 24 public class FieldLocator extends VariableLocator { 25 26 protected boolean isDeclarationOfAccessedFieldsPattern; 27 28 public FieldLocator(FieldPattern pattern) { 29 super(pattern); 30 31 this.isDeclarationOfAccessedFieldsPattern = this.pattern instanceof DeclarationOfAccessedFieldsPattern; 32 } 33 public int match(ASTNode node, MatchingNodeSet nodeSet) { 34 int declarationsLevel = IMPOSSIBLE_MATCH; 35 if (this.pattern.findReferences) { 36 if (node instanceof ImportReference) { 37 ImportReference importRef = (ImportReference) node; 39 int length = importRef.tokens.length-1; 40 if (importRef.isStatic() && ((importRef.bits & ASTNode.OnDemand) == 0) && matchesName(this.pattern.name, importRef.tokens[length])) { 41 char[][] compoundName = new char[length][]; 42 System.arraycopy(importRef.tokens, 0, compoundName, 0, length); 43 FieldPattern fieldPattern = (FieldPattern) this.pattern; 44 char[] declaringType = CharOperation.concat(fieldPattern.declaringQualification, fieldPattern.declaringSimpleName, '.'); 45 if (matchesName(declaringType, CharOperation.concatWith(compoundName, '.'))) { 46 declarationsLevel = ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH; 47 } 48 } 49 } 50 } 51 return nodeSet.addMatch(node, declarationsLevel); 52 } 53 public int match(FieldDeclaration node, MatchingNodeSet nodeSet) { 55 int referencesLevel = IMPOSSIBLE_MATCH; 56 if (this.pattern.findReferences) 57 if (this.pattern.writeAccess && !this.pattern.readAccess && node.initialization != null) 59 if (matchesName(this.pattern.name, node.name)) 60 referencesLevel = ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH; 61 62 int declarationsLevel = IMPOSSIBLE_MATCH; 63 if (this.pattern.findDeclarations) { 64 switch (node.getKind()) { 65 case AbstractVariableDeclaration.FIELD : 66 case AbstractVariableDeclaration.ENUM_CONSTANT : 67 if (matchesName(this.pattern.name, node.name)) 68 if (matchesTypeReference(((FieldPattern)this.pattern).typeSimpleName, node.type)) 69 declarationsLevel = ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH; 70 break; 71 } 72 } 73 return nodeSet.addMatch(node, referencesLevel >= declarationsLevel ? referencesLevel : declarationsLevel); } 75 80 protected int matchContainer() { 81 if (this.pattern.findReferences) { 82 return ALL_CONTAINER; 84 } 85 return CLASS_CONTAINER; 86 } 87 protected int matchField(FieldBinding field, boolean matchName) { 88 if (field == null) return INACCURATE_MATCH; 89 90 if (matchName && !matchesName(this.pattern.name, field.readableName())) return IMPOSSIBLE_MATCH; 91 92 FieldPattern fieldPattern = (FieldPattern)this.pattern; 93 ReferenceBinding receiverBinding = field.declaringClass; 94 if (receiverBinding == null) { 95 if (field == ArrayBinding.ArrayLength) 96 return fieldPattern.declaringQualification == null && fieldPattern.declaringSimpleName == null 98 ? ACCURATE_MATCH 99 : IMPOSSIBLE_MATCH; 100 return INACCURATE_MATCH; 101 } 102 103 int declaringLevel = resolveLevelForType(fieldPattern.declaringSimpleName, fieldPattern.declaringQualification, receiverBinding); 105 if (declaringLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH; 106 107 if (fieldPattern.declaringSimpleName == null) return declaringLevel; 109 110 FieldBinding fieldBinding = field; 112 if (field instanceof ParameterizedFieldBinding) { 113 fieldBinding = ((ParameterizedFieldBinding) field).originalField; 114 } 115 116 int typeLevel = resolveLevelForType(fieldBinding.type); 117 return declaringLevel > typeLevel ? typeLevel : declaringLevel; } 119 123 protected void matchLevelAndReportImportRef(ImportReference importRef, Binding binding, MatchLocator locator) throws CoreException { 124 if (importRef.isStatic() && binding instanceof FieldBinding) { 125 super.matchLevelAndReportImportRef(importRef, binding, locator); 126 } 127 } 128 protected int matchReference(Reference node, MatchingNodeSet nodeSet, boolean writeOnlyAccess) { 129 if (node instanceof FieldReference) { 130 if (matchesName(this.pattern.name, ((FieldReference) node).token)) 131 return nodeSet.addMatch(node, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH); 132 return IMPOSSIBLE_MATCH; 133 } 134 return super.matchReference(node, nodeSet, writeOnlyAccess); 135 } 136 protected void matchReportReference(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException { 137 if (this.isDeclarationOfAccessedFieldsPattern) { 138 if (accuracy != SearchMatch.A_ACCURATE) return; 140 141 DeclarationOfAccessedFieldsPattern declPattern = (DeclarationOfAccessedFieldsPattern) this.pattern; 143 while (element != null && !declPattern.enclosingElement.equals(element)) 144 element = element.getParent(); 145 if (element != null) { 146 if (reference instanceof FieldReference) { 147 reportDeclaration(((FieldReference) reference).binding, locator, declPattern.knownFields); 148 } else if (reference instanceof QualifiedNameReference) { 149 QualifiedNameReference qNameRef = (QualifiedNameReference) reference; 150 Binding nameBinding = qNameRef.binding; 151 if (nameBinding instanceof FieldBinding) 152 reportDeclaration((FieldBinding)nameBinding, locator, declPattern.knownFields); 153 int otherMax = qNameRef.otherBindings == null ? 0 : qNameRef.otherBindings.length; 154 for (int i = 0; i < otherMax; i++) 155 reportDeclaration(qNameRef.otherBindings[i], locator, declPattern.knownFields); 156 } else if (reference instanceof SingleNameReference) { 157 reportDeclaration((FieldBinding)((SingleNameReference) reference).binding, locator, declPattern.knownFields); 158 } 159 } 160 } else if (reference instanceof ImportReference) { 161 ImportReference importRef = (ImportReference) reference; 162 long[] positions = importRef.sourcePositions; 163 int lastIndex = importRef.tokens.length - 1; 164 int start = (int) ((positions[lastIndex]) >>> 32); 165 int end = (int) positions[lastIndex]; 166 match = locator.newFieldReferenceMatch(element, elementBinding, accuracy, start, end-start+1, importRef); 167 locator.report(match); 168 } else if (reference instanceof FieldReference) { 169 FieldReference fieldReference = (FieldReference) reference; 170 long position = fieldReference.nameSourcePosition; 171 int start = (int) (position >>> 32); 172 int end = (int) position; 173 match = locator.newFieldReferenceMatch(element, elementBinding, accuracy, start, end-start+1, fieldReference); 174 locator.report(match); 175 } else if (reference instanceof SingleNameReference) { 176 int offset = reference.sourceStart; 177 match = locator.newFieldReferenceMatch(element, elementBinding, accuracy, offset, reference.sourceEnd-offset+1, reference); 178 locator.report(match); 179 } else if (reference instanceof QualifiedNameReference) { 180 QualifiedNameReference qNameRef = (QualifiedNameReference) reference; 181 int length = qNameRef.tokens.length; 182 SearchMatch[] matches = new SearchMatch[length]; 183 Binding nameBinding = qNameRef.binding; 184 int indexOfFirstFieldBinding = qNameRef.indexOfFirstFieldBinding > 0 ? qNameRef.indexOfFirstFieldBinding-1 : 0; 185 186 if (matchesName(this.pattern.name, qNameRef.tokens[indexOfFirstFieldBinding]) && !(nameBinding instanceof LocalVariableBinding)) { 188 FieldBinding fieldBinding = nameBinding instanceof FieldBinding ? (FieldBinding) nameBinding : null; 189 if (fieldBinding == null) { 190 matches[indexOfFirstFieldBinding] = locator.newFieldReferenceMatch(element, elementBinding, accuracy, -1, -1, reference); 191 } else { 192 switch (matchField(fieldBinding, false)) { 193 case ACCURATE_MATCH: 194 matches[indexOfFirstFieldBinding] = locator.newFieldReferenceMatch(element, elementBinding, SearchMatch.A_ACCURATE, -1, -1, reference); 195 break; 196 case INACCURATE_MATCH: 197 match = locator.newFieldReferenceMatch(element, elementBinding, SearchMatch.A_INACCURATE, -1, -1, reference); 198 if (fieldBinding.type != null && fieldBinding.type.isParameterizedType() && this.pattern.hasTypeArguments()) { 199 updateMatch((ParameterizedTypeBinding) fieldBinding.type, this.pattern.getTypeArguments(), locator); 200 } 201 matches[indexOfFirstFieldBinding] = match; 202 break; 203 } 204 } 205 } 206 207 for (int i = indexOfFirstFieldBinding+1; i < length; i++) { 209 char[] token = qNameRef.tokens[i]; 210 if (matchesName(this.pattern.name, token)) { 211 FieldBinding otherBinding = qNameRef.otherBindings == null ? null : qNameRef.otherBindings[i-(indexOfFirstFieldBinding+1)]; 212 if (otherBinding == null) { 213 matches[i] = locator.newFieldReferenceMatch(element, elementBinding, accuracy, -1, -1, reference); 214 } else { 215 switch (matchField(otherBinding, false)) { 216 case ACCURATE_MATCH: 217 matches[i] = locator.newFieldReferenceMatch(element, elementBinding, SearchMatch.A_ACCURATE, -1, -1, reference); 218 break; 219 case INACCURATE_MATCH: 220 match = locator.newFieldReferenceMatch(element, elementBinding, SearchMatch.A_INACCURATE, -1, -1, reference); 221 if (otherBinding.type != null && otherBinding.type.isParameterizedType() && this.pattern.hasTypeArguments()) { 222 updateMatch((ParameterizedTypeBinding) otherBinding.type, this.pattern.getTypeArguments(), locator); 223 } 224 matches[i] = match; 225 break; 226 } 227 } 228 } 229 } 230 locator.reportAccurateFieldReference(matches, qNameRef); 231 } 232 } 233 238 protected void updateMatch(ParameterizedTypeBinding parameterizedBinding, char[][][] patternTypeArguments, MatchLocator locator) { 239 if (locator.unitScope == null) return; 241 updateMatch(parameterizedBinding, patternTypeArguments, false, 0, locator); 242 if (!match.isExact()) { 243 match.setRule(0); 245 } 246 } 247 protected void reportDeclaration(FieldBinding fieldBinding, MatchLocator locator, SimpleSet knownFields) throws CoreException { 248 if (fieldBinding == ArrayBinding.ArrayLength) return; 250 251 ReferenceBinding declaringClass = fieldBinding.declaringClass; 252 IType type = locator.lookupType(declaringClass); 253 if (type == null) return; 255 char[] bindingName = fieldBinding.name; 256 IField field = type.getField(new String (bindingName)); 257 if (knownFields.addIfNotIncluded(field) == null) return; 258 259 IResource resource = type.getResource(); 260 boolean isBinary = type.isBinary(); 261 IBinaryType info = null; 262 if (isBinary) { 263 if (resource == null) 264 resource = type.getJavaProject().getProject(); 265 info = locator.getBinaryInfo((org.eclipse.jdt.internal.core.ClassFile) type.getClassFile(), resource); 266 locator.reportBinaryMemberDeclaration(resource, field, fieldBinding, info, SearchMatch.A_ACCURATE); 267 } else { 268 if (declaringClass instanceof ParameterizedTypeBinding) 269 declaringClass = ((ParameterizedTypeBinding) declaringClass).genericType(); 270 ClassScope scope = ((SourceTypeBinding) declaringClass).scope; 271 if (scope != null) { 272 TypeDeclaration typeDecl = scope.referenceContext; 273 FieldDeclaration fieldDecl = null; 274 FieldDeclaration[] fieldDecls = typeDecl.fields; 275 for (int i = 0, length = fieldDecls.length; i < length; i++) { 276 if (CharOperation.equals(bindingName, fieldDecls[i].name)) { 277 fieldDecl = fieldDecls[i]; 278 break; 279 } 280 } 281 if (fieldDecl != null) { 282 int offset = fieldDecl.sourceStart; 283 match = new FieldDeclarationMatch(((JavaElement) field).resolved(fieldBinding), SearchMatch.A_ACCURATE, offset, fieldDecl.sourceEnd-offset+1, locator.getParticipant(), resource); 284 locator.report(match); 285 } 286 } 287 } 288 } 289 protected int referenceType() { 290 return IJavaElement.FIELD; 291 } 292 public int resolveLevel(ASTNode possiblelMatchingNode) { 293 if (this.pattern.findReferences) { 294 if (possiblelMatchingNode instanceof FieldReference) 295 return matchField(((FieldReference) possiblelMatchingNode).binding, true); 296 else if (possiblelMatchingNode instanceof NameReference) 297 return resolveLevel((NameReference) possiblelMatchingNode); 298 } 299 if (possiblelMatchingNode instanceof FieldDeclaration) 300 return matchField(((FieldDeclaration) possiblelMatchingNode).binding, true); 301 return IMPOSSIBLE_MATCH; 302 } 303 public int resolveLevel(Binding binding) { 304 if (binding == null) return INACCURATE_MATCH; 305 if (!(binding instanceof FieldBinding)) return IMPOSSIBLE_MATCH; 306 307 return matchField((FieldBinding) binding, true); 308 } 309 protected int resolveLevel(NameReference nameRef) { 310 if (nameRef instanceof SingleNameReference) 311 return resolveLevel(nameRef.binding); 312 313 Binding binding = nameRef.binding; 314 QualifiedNameReference qNameRef = (QualifiedNameReference) nameRef; 315 FieldBinding fieldBinding = null; 316 if (binding instanceof FieldBinding) { 317 fieldBinding = (FieldBinding) binding; 318 char[] bindingName = fieldBinding.name; 319 int lastDot = CharOperation.lastIndexOf('.', bindingName); 320 if (lastDot > -1) 321 bindingName = CharOperation.subarray(bindingName, lastDot+1, bindingName.length); 322 if (matchesName(this.pattern.name, bindingName)) { 323 int level = matchField(fieldBinding, false); 324 if (level != IMPOSSIBLE_MATCH) return level; 325 } 326 } 327 int otherMax = qNameRef.otherBindings == null ? 0 : qNameRef.otherBindings.length; 328 for (int i = 0; i < otherMax; i++) { 329 char[] token = qNameRef.tokens[i + qNameRef.indexOfFirstFieldBinding]; 330 if (matchesName(this.pattern.name, token)) { 331 FieldBinding otherBinding = qNameRef.otherBindings[i]; 332 int level = matchField(otherBinding, false); 333 if (level != IMPOSSIBLE_MATCH) return level; 334 } 335 } 336 return IMPOSSIBLE_MATCH; 337 } 338 341 protected int resolveLevelForType(TypeBinding typeBinding) { 342 FieldPattern fieldPattern = (FieldPattern) this.pattern; 343 TypeBinding fieldTypeBinding = typeBinding; 344 if (fieldTypeBinding != null && fieldTypeBinding.isParameterizedType()) { 345 fieldTypeBinding = typeBinding.erasure(); 346 } 347 return resolveLevelForType( 348 fieldPattern.typeSimpleName, 349 fieldPattern.typeQualification, 350 fieldPattern.getTypeArguments(), 351 0, 352 fieldTypeBinding); 353 } 354 } 355 | Popular Tags |