| /* |
| * 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.core.ext.typeinfo.NotFoundException; |
| |
| /** |
| * Represents a wildcard type argument to a parameterized type. |
| */ |
| public class JWildcardType extends JDelegatingClassType implements |
| com.google.gwt.core.ext.typeinfo.JWildcardType { |
| |
| private final BoundType boundType; |
| private JClassType[] lazyLowerBounds; |
| private JClassType[] lazyUpperBounds; |
| |
| JWildcardType(BoundType boundType, JClassType typeBound) { |
| this.boundType = boundType; |
| super.setBaseType(typeBound); |
| } |
| |
| @Override |
| public JField findField(String name) { |
| return getBaseType().findField(name); |
| } |
| |
| @Override |
| public JMethod findMethod(String name, JType[] paramTypes) { |
| return getBaseType().findMethod(name, paramTypes); |
| } |
| |
| @Override |
| public BoundType getBoundType() { |
| return boundType; |
| } |
| |
| @Override |
| public JClassType getErasedType() { |
| return getUpperBound().getErasedType(); |
| } |
| |
| @Override |
| public JField getField(String name) { |
| return getBaseType().getField(name); |
| } |
| |
| @Override |
| public JField[] getFields() { |
| return getBaseType().getFields(); |
| } |
| |
| @Override |
| public JClassType getFirstBound() { |
| return getBaseType(); |
| } |
| |
| /** |
| * Returns the lower bounds of this wildcard type. If no lower bounds were |
| * declared, an empty array is returned. |
| * |
| * @return the lower bounds of this wildcard type |
| */ |
| @Override |
| public JClassType[] getLowerBounds() { |
| if (lazyLowerBounds == null) { |
| if (isUpperBound()) { |
| lazyLowerBounds = TypeOracle.NO_JCLASSES; |
| } else { |
| lazyLowerBounds = new JClassType[]{getFirstBound()}; |
| } |
| } |
| return lazyLowerBounds; |
| } |
| |
| @Override |
| public JMethod getMethod(String name, JType[] paramTypes) |
| throws NotFoundException { |
| return getBaseType().getMethod(name, paramTypes); |
| } |
| |
| @Override |
| public JMethod[] getMethods() { |
| return getBaseType().getMethods(); |
| } |
| |
| @Override |
| public String getQualifiedBinaryName() { |
| // TODO(jat): !! does a binary name have meaning for a wildcard? |
| return toString(true); |
| } |
| |
| @Override |
| public String getQualifiedSourceName() { |
| return toString(false); |
| } |
| |
| @Override |
| public String getSimpleSourceName() { |
| return toString(true); |
| } |
| |
| @Override |
| public JClassType[] getSubtypes() { |
| if (isUpperBound()) { |
| return getFirstBound().getSubtypes(); |
| } |
| |
| // We are not sure what the correct behavior should be for lower bound |
| // wildcards. ? super Number contains ? super T for all T extends Number, |
| // but it also includes T for Number extends T. For example, Object is a |
| // subtype. |
| return TypeOracle.NO_JCLASSES; |
| } |
| |
| @Override |
| public JClassType getSuperclass() { |
| if (isUpperBound()) { |
| // The superclass of an upper bound is the upper bound. |
| return getFirstBound(); |
| } |
| |
| // The only safe superclass for a ? super T is Object. |
| return getOracle().getJavaLangObject(); |
| } |
| |
| @Override |
| public JClassType getUpperBound() { |
| if (isUpperBound()) { |
| return getFirstBound(); |
| } |
| |
| return getOracle().getJavaLangObject(); |
| } |
| |
| /** |
| * Returns the upper bounds of this wildcard type. If no upper bounds were |
| * declared, an array containing {@link Object} is returned. |
| * |
| * @return the upper bounds of this wildcard type |
| */ |
| @Override |
| public JClassType[] getUpperBounds() { |
| if (lazyUpperBounds == null) { |
| if (isUpperBound()) { |
| lazyUpperBounds = new JClassType[]{getFirstBound()}; |
| } else { |
| // Object is the default upper bound. |
| lazyUpperBounds = new JClassType[]{getOracle().getJavaLangObject()}; |
| } |
| } |
| |
| return lazyUpperBounds; |
| } |
| |
| @Override |
| public JGenericType isGenericType() { |
| return null; |
| } |
| |
| @Override |
| public JParameterizedType isParameterized() { |
| return null; |
| } |
| |
| @Override |
| public JRawType isRawType() { |
| return null; |
| } |
| |
| @Override |
| public JWildcardType isWildcard() { |
| return this; |
| } |
| |
| @Override |
| JClassType getSubstitutedType(JParameterizedType parameterizedType) { |
| return getOracle().getWildcardType(boundType, |
| getFirstBound().getSubstitutedType(parameterizedType)); |
| } |
| |
| private boolean isUnbound() { |
| return boundType == BoundType.UNBOUND; |
| } |
| |
| private boolean isUpperBound() { |
| return boundType != BoundType.SUPER; |
| } |
| |
| private String toString(boolean simpleName) { |
| String str = "?"; |
| if (isUnbound()) { |
| return str; |
| } else { |
| str += (isUpperBound() ? " extends " : " super "); |
| if (simpleName) { |
| return str + getFirstBound().getSimpleSourceName(); |
| } else { |
| return str + getFirstBound().getParameterizedQualifiedSourceName(); |
| } |
| } |
| } |
| } |