| /******************************************************************************* |
| * Copyright (c) 2000, 2010 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.core.search.matching; |
| |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.internal.compiler.ast.*; |
| import org.eclipse.jdt.internal.compiler.lookup.Binding; |
| import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; |
| import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; |
| import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; |
| |
| /** |
| * Search engine locator for type parameters matches. |
| */ |
| public class TypeParameterLocator extends PatternLocator { |
| |
| protected TypeParameterPattern pattern; |
| |
| public TypeParameterLocator(TypeParameterPattern pattern) { |
| super(pattern); |
| this.pattern = pattern; |
| } |
| |
| /* |
| * Verify whether a type reference matches name pattern. |
| * Type parameter references (i.e. type arguments) are compiler type reference nodes |
| */ |
| public int match(TypeReference node, MatchingNodeSet nodeSet) { |
| if (this.pattern.findReferences) { |
| if (node instanceof SingleTypeReference) { // Type parameter cannot be qualified |
| if (matchesName(this.pattern.name, ((SingleTypeReference) node).token)) { |
| int level = this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH; |
| return nodeSet.addMatch(node, level); |
| } |
| } |
| } |
| return IMPOSSIBLE_MATCH; |
| } |
| |
| |
| /* |
| * Verify whether a type parameter matches name pattern. |
| */ |
| public int match(TypeParameter node, MatchingNodeSet nodeSet) { |
| if (this.pattern.findDeclarations) { |
| if (matchesName(this.pattern.name, node.name)) { |
| int level = this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH; |
| return nodeSet.addMatch(node, level); |
| } |
| } |
| return IMPOSSIBLE_MATCH; |
| } |
| |
| /* |
| * While searching for references, need to match all containers as we can have references in javadoc comments. |
| * Otherwise, only class or method container can declare type parameters. |
| */ |
| protected int matchContainer() { |
| if (this.pattern.findReferences) { |
| return ALL_CONTAINER; |
| } |
| return CLASS_CONTAINER | METHOD_CONTAINER; |
| } |
| |
| /* |
| * Verify that a type variable binding match pattern infos. |
| * For types, only look at declaring member name. |
| * For methods, also look at declaring class and parameters type names |
| */ |
| protected int matchTypeParameter(TypeVariableBinding variable, boolean matchName) { |
| if (variable == null || variable.declaringElement == null) return INACCURATE_MATCH; |
| if (variable.declaringElement instanceof ReferenceBinding) { |
| ReferenceBinding refBinding = (ReferenceBinding) variable.declaringElement; |
| if (matchesName(refBinding.sourceName, this.pattern.declaringMemberName)) { |
| return ACCURATE_MATCH; |
| } |
| } else if (variable.declaringElement instanceof MethodBinding) { |
| MethodBinding methBinding = (MethodBinding) variable.declaringElement; |
| if (matchesName(methBinding.declaringClass.sourceName, this.pattern.methodDeclaringClassName) && |
| (methBinding.isConstructor() || matchesName(methBinding.selector, this.pattern.declaringMemberName))) { |
| int length = this.pattern.methodArgumentTypes==null ? 0 : this.pattern.methodArgumentTypes.length; |
| if (methBinding.parameters == null) { |
| if (length == 0) return ACCURATE_MATCH; |
| } else if (methBinding.parameters.length == length){ |
| for (int i=0; i<length; i++) { |
| if (!matchesName(methBinding.parameters[i].shortReadableName(), this.pattern.methodArgumentTypes[i])) { |
| return IMPOSSIBLE_MATCH; |
| } |
| } |
| return ACCURATE_MATCH; |
| } |
| } |
| } |
| return IMPOSSIBLE_MATCH; |
| } |
| |
| protected int referenceType() { |
| return IJavaElement.TYPE_PARAMETER; |
| } |
| |
| /* |
| * Resolve level for a possible matching node. |
| * Only type references while searching references and type parameters |
| * while searching declarations are valid. |
| */ |
| public int resolveLevel(ASTNode possibleMatchingNode) { |
| if (this.pattern.findReferences) { |
| if (possibleMatchingNode instanceof SingleTypeReference) { |
| return resolveLevel(((SingleTypeReference) possibleMatchingNode).resolvedType); |
| } |
| } |
| if (this.pattern.findDeclarations) { |
| if (possibleMatchingNode instanceof TypeParameter) { |
| return matchTypeParameter(((TypeParameter) possibleMatchingNode).binding, true); |
| } |
| } |
| return IMPOSSIBLE_MATCH; |
| } |
| |
| /* |
| * Resolve level for a binding. |
| * Only type variable bindings are valid. |
| */ |
| public int resolveLevel(Binding binding) { |
| if (binding == null) return INACCURATE_MATCH; |
| if (!(binding instanceof TypeVariableBinding)) return IMPOSSIBLE_MATCH; |
| |
| return matchTypeParameter((TypeVariableBinding) binding, true); |
| } |
| |
| public String toString() { |
| return "Locator for " + this.pattern.toString(); //$NON-NLS-1$ |
| } |
| } |