| /* |
| * Copyright (c) 2013, the Dart project authors. |
| * |
| * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except |
| * in compliance with the License. You may obtain a copy of the License at |
| * |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.dart.engine.internal.element.member; |
| |
| import com.google.dart.engine.ast.MethodDeclaration; |
| import com.google.dart.engine.context.AnalysisException; |
| import com.google.dart.engine.element.ClassElement; |
| import com.google.dart.engine.element.Element; |
| import com.google.dart.engine.element.ElementVisitor; |
| import com.google.dart.engine.element.MethodElement; |
| import com.google.dart.engine.element.ParameterElement; |
| import com.google.dart.engine.type.FunctionType; |
| import com.google.dart.engine.type.InterfaceType; |
| import com.google.dart.engine.type.Type; |
| |
| /** |
| * Instances of the class {@code MethodMember} represent a method element defined in a parameterized |
| * type where the values of the type parameters are known. |
| */ |
| public class MethodMember extends ExecutableMember implements MethodElement { |
| /** |
| * If the given method's type is different when any type parameters from the defining type's |
| * declaration are replaced with the actual type arguments from the defining type, create a method |
| * member representing the given method. Return the member that was created, or the base method if |
| * no member was created. |
| * |
| * @param baseMethod the base method for which a member might be created |
| * @param definingType the type defining the parameters and arguments to be used in the |
| * substitution |
| * @return the method element that will return the correctly substituted types |
| */ |
| public static MethodElement from(MethodElement baseMethod, InterfaceType definingType) { |
| if (baseMethod == null || definingType.getTypeArguments().length == 0) { |
| return baseMethod; |
| } |
| FunctionType baseType = baseMethod.getType(); |
| Type[] argumentTypes = definingType.getTypeArguments(); |
| Type[] parameterTypes = definingType.getElement().getType().getTypeArguments(); |
| FunctionType substitutedType = baseType.substitute(argumentTypes, parameterTypes); |
| if (baseType.equals(substitutedType)) { |
| return baseMethod; |
| } |
| // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more |
| // memory but speed up some operations. We need to see how often the type is being re-computed. |
| return new MethodMember(baseMethod, definingType); |
| } |
| |
| /** |
| * Initialize a newly created element to represent a method of the given parameterized type. |
| * |
| * @param baseElement the element on which the parameterized element was created |
| * @param definingType the type in which the element is defined |
| */ |
| public MethodMember(MethodElement baseElement, InterfaceType definingType) { |
| super(baseElement, definingType); |
| } |
| |
| @Override |
| public <R> R accept(ElementVisitor<R> visitor) { |
| return visitor.visitMethodElement(this); |
| } |
| |
| @Override |
| public MethodElement getBaseElement() { |
| return (MethodElement) super.getBaseElement(); |
| } |
| |
| @Override |
| public ClassElement getEnclosingElement() { |
| return getBaseElement().getEnclosingElement(); |
| } |
| |
| @Override |
| public MethodDeclaration getNode() throws AnalysisException { |
| return getBaseElement().getNode(); |
| } |
| |
| @Override |
| public boolean isAbstract() { |
| return getBaseElement().isAbstract(); |
| } |
| |
| @Override |
| public String toString() { |
| MethodElement baseElement = getBaseElement(); |
| ParameterElement[] parameters = getParameters(); |
| FunctionType type = getType(); |
| StringBuilder builder = new StringBuilder(); |
| builder.append(baseElement.getEnclosingElement().getDisplayName()); |
| builder.append("."); |
| builder.append(baseElement.getDisplayName()); |
| builder.append("("); |
| int parameterCount = parameters.length; |
| for (int i = 0; i < parameterCount; i++) { |
| if (i > 0) { |
| builder.append(", "); |
| } |
| builder.append(parameters[i]).toString(); |
| } |
| builder.append(")"); |
| if (type != null) { |
| builder.append(Element.RIGHT_ARROW); |
| builder.append(type.getReturnType()); |
| } |
| return builder.toString(); |
| } |
| } |