1 11 package org.eclipse.jdt.internal.core.search.matching; 12 13 import org.eclipse.core.runtime.CoreException; 14 import org.eclipse.jdt.core.IJavaElement; 15 import org.eclipse.jdt.core.compiler.CharOperation; 16 import org.eclipse.jdt.core.search.SearchMatch; 17 import org.eclipse.jdt.core.search.SearchPattern; 18 import org.eclipse.jdt.internal.compiler.ast.*; 19 import org.eclipse.jdt.internal.compiler.lookup.Binding; 20 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; 21 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding; 22 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedMethodBinding; 23 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; 24 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; 25 26 public class ConstructorLocator extends PatternLocator { 27 28 protected ConstructorPattern pattern; 29 30 public ConstructorLocator(ConstructorPattern pattern) { 31 super(pattern); 32 33 this.pattern = pattern; 34 } 35 public int match(ASTNode node, MatchingNodeSet nodeSet) { if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH; 37 if (!(node instanceof ExplicitConstructorCall)) return IMPOSSIBLE_MATCH; 38 39 if (!matchParametersCount(node, ((ExplicitConstructorCall) node).arguments)) return IMPOSSIBLE_MATCH; 40 41 return nodeSet.addMatch(node, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH); 42 } 43 public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) { 44 int referencesLevel = this.pattern.findReferences ? matchLevelForReferences(node) : IMPOSSIBLE_MATCH; 45 int declarationsLevel = this.pattern.findDeclarations ? matchLevelForDeclarations(node) : IMPOSSIBLE_MATCH; 46 47 return nodeSet.addMatch(node, referencesLevel >= declarationsLevel ? referencesLevel : declarationsLevel); } 49 public int match(Expression node, MatchingNodeSet nodeSet) { if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH; 51 if (!(node instanceof AllocationExpression)) return IMPOSSIBLE_MATCH; 52 53 AllocationExpression allocation = (AllocationExpression) node; 55 char[][] typeName = allocation.type.getTypeName(); 56 if (this.pattern.declaringSimpleName != null && !matchesName(this.pattern.declaringSimpleName, typeName[typeName.length-1])) 57 return IMPOSSIBLE_MATCH; 58 59 if (!matchParametersCount(node, allocation.arguments)) return IMPOSSIBLE_MATCH; 60 61 return nodeSet.addMatch(node, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH); 62 } 63 public int match(FieldDeclaration field, MatchingNodeSet nodeSet) { 64 if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH; 65 if (field.type != null || !(field.initialization instanceof AllocationExpression)) return IMPOSSIBLE_MATCH; 67 68 AllocationExpression allocation = (AllocationExpression) field.initialization; 69 if (field.binding != null && field.binding.declaringClass != null) { 70 if (this.pattern.declaringSimpleName != null && !matchesName(this.pattern.declaringSimpleName, field.binding.declaringClass.sourceName())) 71 return IMPOSSIBLE_MATCH; 72 } 73 74 if (!matchParametersCount(field, allocation.arguments)) return IMPOSSIBLE_MATCH; 75 76 return nodeSet.addMatch(field, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH); 77 } 78 83 public int match(MessageSend msgSend, MatchingNodeSet nodeSet) { 84 if ((msgSend.bits & ASTNode.InsideJavadoc) == 0) return IMPOSSIBLE_MATCH; 85 if (this.pattern.declaringSimpleName == null || CharOperation.equals(msgSend.selector, this.pattern.declaringSimpleName)) { 86 return nodeSet.addMatch(msgSend, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH); 87 } 88 return IMPOSSIBLE_MATCH; 89 } 90 public int match(TypeDeclaration node, MatchingNodeSet nodeSet) { 92 if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH; 93 94 return nodeSet.addMatch(node, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH); 96 } 97 99 protected int matchConstructor(MethodBinding constructor) { 100 if (!constructor.isConstructor()) return IMPOSSIBLE_MATCH; 101 102 int level = resolveLevelForType(this.pattern.declaringSimpleName, this.pattern.declaringQualification, constructor.declaringClass); 104 if (level == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH; 105 106 int parameterCount = this.pattern.parameterCount; 108 if (parameterCount > -1) { 109 if (constructor.parameters == null) return INACCURATE_MATCH; 110 if (parameterCount != constructor.parameters.length) return IMPOSSIBLE_MATCH; 111 for (int i = 0; i < parameterCount; i++) { 112 int newLevel = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], constructor.parameters[i]); 115 if (level > newLevel) { 116 if (newLevel == IMPOSSIBLE_MATCH) { 117 return IMPOSSIBLE_MATCH; 121 } 122 level = newLevel; } 124 } 125 } 126 return level; 127 } 128 protected int matchContainer() { 129 if (this.pattern.findReferences) return ALL_CONTAINER; 135 return CLASS_CONTAINER; 137 } 138 protected int matchLevelForReferences(ConstructorDeclaration constructor) { 139 ExplicitConstructorCall constructorCall = constructor.constructorCall; 140 if (constructorCall == null || constructorCall.accessMode != ExplicitConstructorCall.ImplicitSuper) 141 return IMPOSSIBLE_MATCH; 142 143 if (this.pattern.parameterSimpleNames != null) { 144 int length = this.pattern.parameterSimpleNames.length; 145 Expression[] args = constructorCall.arguments; 146 int argsLength = args == null ? 0 : args.length; 147 if (length != argsLength) return IMPOSSIBLE_MATCH; 148 } 149 return ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH; 150 } 151 protected int matchLevelForDeclarations(ConstructorDeclaration constructor) { 152 if (this.pattern.declaringSimpleName != null && !matchesName(this.pattern.declaringSimpleName, constructor.selector)) 154 return IMPOSSIBLE_MATCH; 155 156 if (this.pattern.parameterSimpleNames != null) { 157 int length = this.pattern.parameterSimpleNames.length; 158 Argument[] args = constructor.arguments; 159 int argsLength = args == null ? 0 : args.length; 160 if (length != argsLength) return IMPOSSIBLE_MATCH; 161 } 162 163 if (this.pattern.hasConstructorArguments()) { 165 if (constructor.typeParameters == null || constructor.typeParameters.length != this.pattern.constructorArguments.length) return IMPOSSIBLE_MATCH; 166 } 167 168 return ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH; 169 } 170 boolean matchParametersCount(ASTNode node, Expression[] args) { 171 if (this.pattern.parameterSimpleNames != null && (!this.pattern.varargs || ((node.bits & ASTNode.InsideJavadoc) != 0))) { 172 int length = this.pattern.parameterCount; 173 if (length < 0) length = this.pattern.parameterSimpleNames.length; 174 int argsLength = args == null ? 0 : args.length; 175 if (length != argsLength) { 176 return false; 177 } 178 } 179 return true; 180 } 181 protected void matchReportReference(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException { 182 183 MethodBinding constructorBinding = null; 184 boolean isSynthetic = false; 185 if (reference instanceof ExplicitConstructorCall) { 186 ExplicitConstructorCall call = (ExplicitConstructorCall) reference; 187 isSynthetic = call.isImplicitSuper(); 188 constructorBinding = call.binding; 189 } else if (reference instanceof AllocationExpression) { 190 AllocationExpression alloc = (AllocationExpression) reference; 191 constructorBinding = alloc.binding; 192 } else if (reference instanceof TypeDeclaration || reference instanceof FieldDeclaration) { 193 super.matchReportReference(reference, element, elementBinding, accuracy, locator); 194 if (match != null) return; 195 } 196 197 match = locator.newMethodReferenceMatch(element, elementBinding, accuracy, -1, -1, true, isSynthetic, reference); 199 200 if (constructorBinding instanceof ParameterizedGenericMethodBinding) { ParameterizedGenericMethodBinding parameterizedMethodBinding = (ParameterizedGenericMethodBinding) constructorBinding; 204 match.setRaw(parameterizedMethodBinding.isRaw); 205 TypeBinding[] typeBindings = parameterizedMethodBinding.isRaw ? null : parameterizedMethodBinding.typeArguments; 206 updateMatch(typeBindings, locator, this.pattern.constructorArguments, this.pattern.hasConstructorParameters()); 207 208 if (constructorBinding.declaringClass.isParameterizedType() || constructorBinding.declaringClass.isRawType()) { 210 ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding)constructorBinding.declaringClass; 211 if (!this.pattern.hasTypeArguments() && this.pattern.hasConstructorArguments() || parameterizedBinding.isParameterizedWithOwnVariables()) { 212 } else if (this.pattern.hasTypeArguments() && !this.pattern.hasConstructorArguments()) { 215 updateMatch(parameterizedBinding, this.pattern.getTypeArguments(), this.pattern.hasTypeParameters(), 0, locator); 218 } else { 219 updateMatch(parameterizedBinding, this.pattern.getTypeArguments(), this.pattern.hasTypeParameters(), 0, locator); 220 } 221 } else if (this.pattern.hasTypeArguments()) { 222 match.setRule(SearchPattern.R_ERASURE_MATCH); 223 } 224 225 } else if (constructorBinding instanceof ParameterizedMethodBinding) { 228 if (constructorBinding.declaringClass.isParameterizedType() || constructorBinding.declaringClass.isRawType()) { 230 ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding)constructorBinding.declaringClass; 231 if (!this.pattern.hasTypeArguments() && this.pattern.hasConstructorArguments()) { 232 updateMatch(parameterizedBinding, new char[][][] {this.pattern.constructorArguments}, this.pattern.hasTypeParameters(), 0, locator); 234 } else if (!parameterizedBinding.isParameterizedWithOwnVariables()) { 235 updateMatch(parameterizedBinding, this.pattern.getTypeArguments(), this.pattern.hasTypeParameters(), 0, locator); 236 } 237 } else if (this.pattern.hasTypeArguments()) { 238 match.setRule(SearchPattern.R_ERASURE_MATCH); 239 } 240 241 } else if (this.pattern.hasConstructorArguments()) { match.setRule(SearchPattern.R_ERASURE_MATCH); 245 } 246 247 if (match.getRule() == 0) return; boolean report = (this.isErasureMatch && match.isErasure()) || (this.isEquivalentMatch && match.isEquivalent()) || match.isExact(); 250 if (!report) return; 251 252 int offset = reference.sourceStart; 254 match.setOffset(offset); 255 match.setLength(reference.sourceEnd - offset + 1); 256 if (reference instanceof FieldDeclaration) { FieldDeclaration enumConstant = (FieldDeclaration) reference; 258 if (enumConstant.initialization instanceof QualifiedAllocationExpression) { 259 locator.reportAccurateEnumConstructorReference(match, enumConstant, (QualifiedAllocationExpression) enumConstant.initialization); 260 return; 261 } 262 } 263 locator.report(match); 264 } 265 public SearchMatch newDeclarationMatch(ASTNode reference, IJavaElement element, Binding binding, int accuracy, int length, MatchLocator locator) { 266 match = null; 267 int offset = reference.sourceStart; 268 if (this.pattern.findReferences) { 269 if (reference instanceof TypeDeclaration) { 270 TypeDeclaration type = (TypeDeclaration) reference; 271 AbstractMethodDeclaration[] methods = type.methods; 272 if (methods != null) { 273 for (int i = 0, max = methods.length; i < max; i++) { 274 AbstractMethodDeclaration method = methods[i]; 275 boolean synthetic = method.isDefaultConstructor() && method.sourceStart < type.bodyStart; 276 match = locator.newMethodReferenceMatch(element, binding, accuracy, offset, length, method.isConstructor(), synthetic, method); 277 } 278 } 279 } else if (reference instanceof ConstructorDeclaration) { 280 ConstructorDeclaration constructor = (ConstructorDeclaration) reference; 281 ExplicitConstructorCall call = constructor.constructorCall; 282 boolean synthetic = call != null && call.isImplicitSuper(); 283 match = locator.newMethodReferenceMatch(element, binding, accuracy, offset, length, constructor.isConstructor(), synthetic, constructor); 284 } 285 } 286 if (match != null) { 287 return match; 288 } 289 return locator.newDeclarationMatch(element, binding, accuracy, reference.sourceStart, length); 291 } 292 public int resolveLevel(ASTNode node) { 293 if (this.pattern.findReferences) { 294 if (node instanceof AllocationExpression) 295 return resolveLevel((AllocationExpression) node); 296 if (node instanceof ExplicitConstructorCall) 297 return resolveLevel(((ExplicitConstructorCall) node).binding); 298 if (node instanceof TypeDeclaration) 299 return resolveLevel((TypeDeclaration) node); 300 if (node instanceof FieldDeclaration) 301 return resolveLevel((FieldDeclaration) node); 302 if (node instanceof JavadocMessageSend) { 303 return resolveLevel(((JavadocMessageSend)node).binding); 304 } 305 } 306 if (node instanceof ConstructorDeclaration) 307 return resolveLevel((ConstructorDeclaration) node, true); 308 return IMPOSSIBLE_MATCH; 309 } 310 protected int referenceType() { 311 return IJavaElement.METHOD; 312 } 313 protected int resolveLevel(AllocationExpression allocation) { 314 char[][] typeName = allocation.type.getTypeName(); 316 if (this.pattern.declaringSimpleName != null && !matchesName(this.pattern.declaringSimpleName, typeName[typeName.length-1])) 317 return IMPOSSIBLE_MATCH; 318 319 return resolveLevel(allocation.binding); 320 } 321 protected int resolveLevel(FieldDeclaration field) { 322 if (field.type != null || field.binding == null) return IMPOSSIBLE_MATCH; 324 if (this.pattern.declaringSimpleName != null && !matchesName(this.pattern.declaringSimpleName, field.binding.type.sourceName())) 325 return IMPOSSIBLE_MATCH; 326 if (!(field.initialization instanceof AllocationExpression) || field.initialization.resolvedType.isLocalType()) return IMPOSSIBLE_MATCH; 327 328 return resolveLevel(((AllocationExpression)field.initialization).binding); 329 } 330 public int resolveLevel(Binding binding) { 331 if (binding == null) return INACCURATE_MATCH; 332 if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH; 333 334 MethodBinding constructor = (MethodBinding) binding; 335 int level= matchConstructor(constructor); 336 if (level== IMPOSSIBLE_MATCH) { 337 if (constructor != constructor.original()) { 338 level= matchConstructor(constructor.original()); 339 } 340 } 341 return level; 342 } 343 protected int resolveLevel(ConstructorDeclaration constructor, boolean checkDeclarations) { 344 int referencesLevel = IMPOSSIBLE_MATCH; 345 if (this.pattern.findReferences) { 346 ExplicitConstructorCall constructorCall = constructor.constructorCall; 347 if (constructorCall != null && constructorCall.accessMode == ExplicitConstructorCall.ImplicitSuper) { 348 int callCount = (constructorCall.arguments == null) ? 0 : constructorCall.arguments.length; 350 int patternCount = (this.pattern.parameterSimpleNames == null) ? 0 : this.pattern.parameterSimpleNames.length; 351 if (patternCount != callCount) { 352 referencesLevel = IMPOSSIBLE_MATCH; 353 } else { 354 referencesLevel = resolveLevel(constructorCall.binding); 355 if (referencesLevel == ACCURATE_MATCH) return ACCURATE_MATCH; } 357 } 358 } 359 if (!checkDeclarations) return referencesLevel; 360 361 int declarationsLevel = this.pattern.findDeclarations ? resolveLevel(constructor.binding) : IMPOSSIBLE_MATCH; 362 return referencesLevel >= declarationsLevel ? referencesLevel : declarationsLevel; } 364 protected int resolveLevel(TypeDeclaration type) { 365 AbstractMethodDeclaration[] methods = type.methods; 367 if (methods != null) { 368 for (int i = 0, length = methods.length; i < length; i++) { 369 AbstractMethodDeclaration method = methods[i]; 370 if (method.isDefaultConstructor() && method.sourceStart < type.bodyStart) return resolveLevel((ConstructorDeclaration) method, false); 372 } 373 } 374 return IMPOSSIBLE_MATCH; 375 } 376 public String toString() { 377 return "Locator for " + this.pattern.toString(); } 379 } 380 | Popular Tags |