| /* |
| * Copyright 2008 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 |
| * |
| * 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.gwt.dev.javac.typemodel; |
| |
| import com.google.gwt.core.ext.typeinfo.JType; |
| import com.google.gwt.dev.util.StringInterner; |
| import com.google.gwt.dev.util.collect.Lists; |
| |
| import java.lang.annotation.Annotation; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * Common superclass for {@link JMethod} and {@link JConstructor}. |
| */ |
| public abstract class JAbstractMethod implements |
| com.google.gwt.core.ext.typeinfo.JAbstractMethod { |
| |
| private final Annotations annotations; |
| |
| private boolean isVarArgs = false; |
| |
| private int modifierBits; |
| |
| private final String name; |
| |
| private List<JParameter> params = Lists.create(); |
| |
| private String[] realParameterNames = null; |
| |
| private List<JClassType> thrownTypes = Lists.create(); |
| |
| private List<JTypeParameter> typeParams = Lists.create(); |
| |
| JAbstractMethod(JAbstractMethod srcMethod) { |
| this.annotations = new Annotations(srcMethod.annotations); |
| this.isVarArgs = srcMethod.isVarArgs; |
| this.modifierBits = srcMethod.modifierBits; |
| this.name = srcMethod.name; |
| } |
| |
| // Only the builder can construct |
| JAbstractMethod(String name, |
| Map<Class<? extends Annotation>, Annotation> declaredAnnotations, |
| JTypeParameter[] jtypeParameters) { |
| this.name = StringInterner.get().intern(name); |
| annotations = new Annotations(declaredAnnotations); |
| |
| if (jtypeParameters != null) { |
| typeParams = Lists.create(jtypeParameters); |
| } |
| } |
| |
| public JParameter findParameter(String name) { |
| for (JParameter param : params) { |
| if (param.getName().equals(name)) { |
| return param; |
| } |
| } |
| return null; |
| } |
| |
| public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { |
| return annotations.getAnnotation(annotationClass); |
| } |
| |
| public Annotation[] getAnnotations() { |
| return annotations.getAnnotations(); |
| } |
| |
| public Annotation[] getDeclaredAnnotations() { |
| return annotations.getDeclaredAnnotations(); |
| } |
| |
| /** |
| * Gets the type in which this method or constructor was declared. |
| */ |
| public abstract JClassType getEnclosingType(); |
| |
| public JType[] getErasedParameterTypes() { |
| JType[] types = new JType[params.size()]; |
| for (int i = 0; i < types.length; ++i) { |
| types[i] = params.get(i).getType().getErasedType(); |
| } |
| return types; |
| } |
| |
| /** |
| * Returns a string contating a JSNI reference to the method. |
| * |
| * @return <code>@package.Class::method(Lpackage/Param;...)</code> |
| */ |
| public abstract String getJsniSignature(); |
| |
| @Deprecated |
| public final String[][] getMetaData(String tagName) { |
| return TypeOracle.NO_STRING_ARR_ARR; |
| } |
| |
| @Deprecated |
| public final String[] getMetaDataTags() { |
| return TypeOracle.NO_STRINGS; |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public JParameter[] getParameters() { |
| // TODO(jat): where do we handle fake arg names? |
| return params.toArray(TypeOracle.NO_JPARAMS); |
| } |
| |
| public JType[] getParameterTypes() { |
| final JType[] paramTypes = new JType[params.size()]; |
| for (int i = 0; i < paramTypes.length; ++i) { |
| paramTypes[i] = params.get(i).getType(); |
| } |
| return paramTypes; |
| } |
| |
| public abstract String getReadableDeclaration(); |
| |
| public JClassType[] getThrows() { |
| return thrownTypes.toArray(TypeOracle.NO_JCLASSES); |
| } |
| |
| public JTypeParameter[] getTypeParameters() { |
| return typeParams.toArray(new JTypeParameter[typeParams.size()]); |
| } |
| |
| public JAnnotationMethod isAnnotationMethod() { |
| return null; |
| } |
| |
| public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { |
| return annotations.isAnnotationPresent(annotationClass); |
| } |
| |
| public abstract JConstructor isConstructor(); |
| |
| public boolean isDefaultAccess() { |
| return 0 == (modifierBits & (TypeOracle.MOD_PUBLIC | TypeOracle.MOD_PRIVATE | TypeOracle.MOD_PROTECTED)); |
| } |
| |
| public abstract JMethod isMethod(); |
| |
| public boolean isPrivate() { |
| return 0 != (modifierBits & TypeOracle.MOD_PRIVATE); |
| } |
| |
| public boolean isProtected() { |
| return 0 != (modifierBits & TypeOracle.MOD_PROTECTED); |
| } |
| |
| public boolean isPublic() { |
| return 0 != (modifierBits & TypeOracle.MOD_PUBLIC); |
| } |
| |
| public boolean isVarArgs() { |
| return isVarArgs; |
| } |
| |
| protected int getModifierBits() { |
| return modifierBits; |
| } |
| |
| protected void toStringParamsAndThrows(StringBuilder sb) { |
| sb.append("("); |
| boolean needComma = false; |
| for (int i = 0, c = params.size(); i < c; ++i) { |
| JParameter param = params.get(i); |
| if (needComma) { |
| sb.append(", "); |
| } else { |
| needComma = true; |
| } |
| if (isVarArgs() && i == c - 1) { |
| JArrayType arrayType = (JArrayType) param.getType().isArray(); |
| assert (arrayType != null); |
| sb.append(arrayType.getComponentType().getParameterizedQualifiedSourceName()); |
| sb.append("..."); |
| } else { |
| sb.append(param.getType().getParameterizedQualifiedSourceName()); |
| } |
| sb.append(" "); |
| sb.append(param.getName()); |
| } |
| sb.append(")"); |
| |
| if (!thrownTypes.isEmpty()) { |
| sb.append(" throws "); |
| needComma = false; |
| for (JClassType thrownType : thrownTypes) { |
| if (needComma) { |
| sb.append(", "); |
| } else { |
| needComma = true; |
| } |
| sb.append(thrownType.getParameterizedQualifiedSourceName()); |
| } |
| } |
| } |
| |
| protected void toStringTypeParams(StringBuilder sb) { |
| sb.append("<"); |
| boolean needComma = false; |
| for (JTypeParameter typeParam : typeParams) { |
| if (needComma) { |
| sb.append(", "); |
| } else { |
| needComma = true; |
| } |
| sb.append(typeParam.getQualifiedSourceName()); |
| } |
| sb.append(">"); |
| } |
| |
| void addModifierBits(int bits) { |
| modifierBits |= bits; |
| } |
| |
| void addParameter(JParameter param) { |
| params = Lists.add(params, param); |
| } |
| |
| void addThrows(JClassType type) { |
| thrownTypes = Lists.add(thrownTypes, type); |
| } |
| |
| // Called only by a JParameter, passing itself as a reference for lookup. |
| String getRealParameterName(JParameter parameter) { |
| if (realParameterNames == null) { |
| fetchRealParameterNames(); |
| } |
| int n = params.size(); |
| for (int i = 0; i < n; ++i) { |
| // Identity tests are ok since identity is durable within an oracle. |
| if (params.get(i) == parameter) { |
| String realParameterName; |
| if (realParameterNames == null) { |
| realParameterName = StringInterner.get().intern("arg" + i); |
| } else { |
| realParameterName = StringInterner.get().intern(realParameterNames[i]); |
| } |
| return realParameterName; |
| } |
| } |
| // TODO: report error if we are asked for an unknown JParameter? |
| return null; |
| } |
| |
| boolean hasParamTypes(JType[] paramTypes) { |
| if (params.size() != paramTypes.length) { |
| return false; |
| } |
| |
| for (int i = 0; i < paramTypes.length; i++) { |
| JParameter candidate = params.get(i); |
| // Identity tests are ok since identity is durable within an oracle. |
| // |
| if (candidate.getType() != paramTypes[i]) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| void setVarArgs() { |
| isVarArgs = true; |
| } |
| |
| private void fetchRealParameterNames() { |
| realParameterNames = getEnclosingType().getOracle().getJavaSourceParser().getArguments( |
| this); |
| } |
| } |