Index: dart/compiler/java/com/google/dart/compiler/type/Types.java |
diff --git a/dart/compiler/java/com/google/dart/compiler/type/Types.java b/dart/compiler/java/com/google/dart/compiler/type/Types.java |
deleted file mode 100644 |
index 8e83daf9a3bd62d52752853f8f0741ede31b9d9e..0000000000000000000000000000000000000000 |
--- a/dart/compiler/java/com/google/dart/compiler/type/Types.java |
+++ /dev/null |
@@ -1,817 +0,0 @@ |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-package com.google.dart.compiler.type; |
- |
-import com.google.common.annotations.VisibleForTesting; |
-import com.google.common.base.Function; |
-import com.google.common.base.Predicate; |
-import com.google.common.collect.ImmutableList; |
-import com.google.common.collect.Iterables; |
-import com.google.common.collect.Lists; |
-import com.google.common.collect.MapMaker; |
-import com.google.common.collect.Maps; |
-import com.google.common.collect.Sets; |
-import com.google.dart.compiler.ast.DartNewExpression; |
-import com.google.dart.compiler.ast.DartNode; |
-import com.google.dart.compiler.ast.DartPropertyAccess; |
-import com.google.dart.compiler.ast.DartTypeNode; |
-import com.google.dart.compiler.resolver.ClassElement; |
-import com.google.dart.compiler.resolver.CoreTypeProvider; |
-import com.google.dart.compiler.resolver.Element; |
-import com.google.dart.compiler.resolver.FunctionAliasElement; |
-import com.google.dart.compiler.resolver.ResolutionErrorListener; |
-import com.google.dart.compiler.resolver.TypeVariableElement; |
-import com.google.dart.compiler.resolver.VariableElement; |
-import com.google.dart.compiler.type.InterfaceType.Member; |
- |
-import java.lang.reflect.InvocationHandler; |
-import java.lang.reflect.Method; |
-import java.lang.reflect.Proxy; |
-import java.util.ArrayList; |
-import java.util.Collections; |
-import java.util.HashSet; |
-import java.util.Iterator; |
-import java.util.LinkedHashMap; |
-import java.util.LinkedList; |
-import java.util.List; |
-import java.util.Map; |
-import java.util.Map.Entry; |
-import java.util.Set; |
- |
-/** |
- * Utility class for types. |
- */ |
-public class Types { |
- private static Map<Type, Map<TypeQuality, Type>> inferredTypes = new MapMaker().weakKeys().makeMap(); |
- private final CoreTypeProvider typeProvider; |
- |
- private Types(CoreTypeProvider typeProvider) { // Prevent subclassing. |
- this.typeProvider = typeProvider; |
- } |
- |
- public Type leastUpperBound(Type t, Type s) { |
- if (isSubtype(t, s)) { |
- return s; |
- } else if (isSubtype(s, t)) { |
- return t; |
- } else { |
- List<InterfaceType> tTypes = getSuperTypes(t); |
- List<InterfaceType> sTypes = getSuperTypes(s); |
- for (InterfaceType tType : tTypes) { |
- if (sTypes.contains(tType)) { |
- return tType; |
- } |
- } |
- return typeProvider.getObjectType(); |
- } |
- } |
- |
- public Type intersection(Type t, Type s) { |
- return intersection(ImmutableList.of(t, s)); |
- } |
- |
- public static TypeQuality getIntersectionQuality(Type t, Type s) { |
- return getIntersectionQuality(ImmutableList.of(t, s)); |
- } |
- |
- public static TypeQuality getIntersectionQuality(List<Type> types) { |
- Type singleType = null; |
- for (Type type : types) { |
- if (singleType == null) { |
- singleType = type; |
- } else if (singleType != type) { |
- return TypeQuality.INFERRED; |
- } |
- } |
- return TypeQuality.INFERRED_EXACT; |
- } |
- |
- public Type intersection(List<Type> types) { |
- // exclude 'dynamic' type |
- { |
- List<Type> newTypes = Lists.newArrayList(); |
- for (Type type : types) { |
- if (TypeKind.of(type) != TypeKind.DYNAMIC) { |
- newTypes.add(type); |
- } |
- } |
- types = newTypes; |
- } |
- // no types, so Dynamic |
- if (types.isEmpty()) { |
- return typeProvider.getDynamicType(); |
- } |
- // prepare all super types |
- List<List<InterfaceType>> superTypesLists = Lists.newArrayList(); |
- List<Map<InterfaceType, InterfaceType>> superTypesMaps = Lists.newArrayList(); |
- for (Type type : types) { |
- List<InterfaceType> superTypes = getSuperTypes(type); |
- superTypesLists.add(superTypes); |
- Map<InterfaceType, InterfaceType> superTypesMap = Maps.newHashMap(); |
- for (InterfaceType superType : superTypes) { |
- superTypesMap.put(superType.asRawType(), superType); |
- } |
- superTypesMaps.add(superTypesMap); |
- } |
- // find intersection of super types |
- LinkedList<InterfaceType> interTypes = Lists.newLinkedList(); |
- if (superTypesLists.size() > 0) { |
- for (InterfaceType superType : superTypesLists.get(0)) { |
- boolean inAll = true; |
- for (Map<InterfaceType, InterfaceType> otherTypesMap : superTypesMaps) { |
- InterfaceType superTypeRaw = superType.asRawType(); |
- InterfaceType otherType = otherTypesMap.get(superTypeRaw); |
- // no such raw type, exclude from intersection |
- if (otherType == null) { |
- inAll = false; |
- break; |
- } |
- // if not raw, choose type arguments |
- if (!superType.getArguments().isEmpty()) { |
- InterfaceType t0 = superType; |
- InterfaceType t1 = otherType; |
- // if two-way sub-type, then has Dynamic(s), choose with least number |
- if (isSubtype(t0, t1) && isSubtype(t1, t0)) { |
- int dynamics0 = getDynamicArgumentsCount(t0); |
- int dynamics1 = getDynamicArgumentsCount(t1); |
- if (dynamics0 < dynamics1) { |
- superType = t0; |
- } else { |
- superType = t1; |
- } |
- continue; |
- } |
- // use super-type of t0 and t1 |
- if (isSubtype(t0, t1)) { |
- superType = t1; |
- } |
- if (isSubtype(t1, t0)) { |
- superType = t0; |
- } |
- } |
- } |
- if (inAll && !interTypes.contains(superType)) { |
- interTypes.add(superType); |
- } |
- } |
- } |
- // try to remove sub-types already covered by existing types |
- for (Iterator<InterfaceType> i = interTypes.descendingIterator(); i.hasNext();) { |
- InterfaceType subType = i.next(); |
- boolean hasSuperType = false; |
- for (InterfaceType superType : interTypes) { |
- if (superType != subType && isSubtype(superType, subType)) { |
- hasSuperType = true; |
- break; |
- } |
- } |
- if (hasSuperType) { |
- i.remove(); |
- } |
- } |
- // use single type |
- if (interTypes.size() == 0) { |
- return typeProvider.getObjectType(); |
- } |
- if (interTypes.size() == 1) { |
- return interTypes.get(0); |
- } |
- // create union |
- return unionTypes(interTypes); |
- } |
- |
- /** |
- * @return the {@link InterfaceType} which is union of given ones. |
- */ |
- public InterfaceType unionTypes(List<InterfaceType> types) { |
- return new InterfaceTypeUnionImplementation(types); |
- } |
- |
- /** |
- * @return the number of <code>Dynamic</code> type arguments in given {@link InterfaceType}. |
- */ |
- private static int getDynamicArgumentsCount(InterfaceType t) { |
- return Iterables.size(Iterables.filter(t.getArguments(), new Predicate<Type>() { |
- public boolean apply(Type arg) { |
- return TypeKind.of(arg) == TypeKind.DYNAMIC; |
- } |
- })); |
- } |
- |
- /** |
- * @return list of the super-types (if class type given) or super-interfaces (if interface type |
- * given) from most specific to least specific. |
- */ |
- private static List<InterfaceType> getSuperTypes(Type type) { |
- List<InterfaceType> types = Lists.newArrayList(); |
- if (type instanceof InterfaceType) { |
- InterfaceType interfaceType = (InterfaceType) type; |
- types.add(interfaceType); |
- for (InterfaceType intf : interfaceType.getElement().getInterfaces()) { |
- intf = asSupertype(interfaceType, intf); |
- types.addAll(getSuperTypes(intf)); |
- } |
- for (InterfaceType mixin : interfaceType.getElement().getMixins()) { |
- mixin = asSupertype(interfaceType, mixin); |
- types.add(mixin); |
- } |
- if (!interfaceType.getElement().isInterface()) { |
- InterfaceType superClass = interfaceType.getElement().getSupertype(); |
- superClass= asSupertype(interfaceType, superClass); |
- types.addAll(getSuperTypes(superClass)); |
- } |
- } |
- return types; |
- } |
- |
- /** |
- * Return an interface type representing the given interface, function or |
- * variable type. |
- * @return An interface type or null if the argument is neither an interface |
- * function or variable type. |
- */ |
- public InterfaceType getInterfaceType(Type type) { |
- switch (TypeKind.of(type)) { |
- case VARIABLE: { |
- TypeVariableElement element = ((TypeVariable) type).getTypeVariableElement(); |
- if (element.getBound() == null) { |
- return typeProvider.getObjectType(); |
- } else { |
- return getInterfaceType(element.getBound()); |
- } |
- } |
- case FUNCTION: |
- case FUNCTION_ALIAS: |
- return typeProvider.getFunctionType(); |
- case INTERFACE: |
- return (InterfaceType) type; |
- case DYNAMIC: |
- case NONE: |
- case VOID: |
- default: |
- return null; |
- } |
- } |
- |
- /** |
- * Returns true if t is a subtype of s. |
- */ |
- public boolean isSubtype(Type t, Type s) { |
- if (t.getKind().equals(TypeKind.DYNAMIC)) { |
- return true; |
- } |
- switch (s.getKind()) { |
- case DYNAMIC: |
- return true; |
- |
- case INTERFACE: |
- return isSubtypeOfInterface(t, (InterfaceType) s); |
- |
- case FUNCTION_ALIAS: |
- return isSubtypeOfAlias(t, (FunctionAliasType) s); |
- |
- case FUNCTION: |
- switch (t.getKind()) { |
- case FUNCTION_ALIAS: |
- return isSubtypeOfFunction(asFunctionType((FunctionAliasType) t), (FunctionType) s); |
- |
- case FUNCTION: |
- return isSubtypeOfFunction((FunctionType) t, (FunctionType) s); |
- |
- default: |
- return false; |
- } |
- |
- case VARIABLE: |
- return isSubtypeOfTypeVariable(t, (TypeVariable) s); |
- |
- case VOID: |
- return t.equals(s); |
- |
- default: |
- throw new AssertionError(s.getKind()); |
- } |
- } |
- |
- static FunctionType asFunctionType(FunctionAliasType alias) { |
- FunctionAliasElement element = alias.getElement(); |
- FunctionType type = |
- (FunctionType) element.getFunctionType().subst(alias.getArguments(), |
- element.getTypeParameters()); |
- return type; |
- } |
- |
- private boolean isSubtypeOfAlias(Type t, FunctionAliasType s) { |
- if (isSubtypeOfInterface(t, s)) { |
- return true; |
- } |
- if (t.getKind() == TypeKind.VARIABLE) { |
- Type bound = ((TypeVariable) t).getTypeVariableElement().getBound(); |
- if (bound != null) { |
- return isSubtype(bound, s); |
- } |
- return true; |
- } |
- if (t.getKind() == TypeKind.FUNCTION_ALIAS) { |
- return isSubtypeOfFunction(asFunctionType((FunctionAliasType) t), asFunctionType(s)); |
- } |
- // class has method call() |
- if (t.getKind() == TypeKind.INTERFACE) { |
- InterfaceType ti = (InterfaceType) t; |
- Member callMember = ti.lookupMember("call"); |
- return callMember != null && isSubtype(callMember.getType(), asFunctionType(s)); |
- } |
- return false; |
- } |
- |
- private boolean isSubtypeOfTypeVariable(Type t, TypeVariable sv) { |
- // May be same type variable. |
- if (sv.equals(t)) { |
- return true; |
- } |
- // May be "T extends S". |
- if (t.getKind() == TypeKind.VARIABLE) { |
- TypeVariable tv = (TypeVariable) t; |
- Type tBound = tv.getTypeVariableElement().getBound(); |
- if (tBound != null && tBound.getKind() == TypeKind.VARIABLE) { |
- // Prevent cycle. |
- if (tBound.equals(t)) { |
- return false; |
- } |
- // Check bound. |
- return isSubtype(tBound, sv); |
- } |
- } |
- // May be concrete InterfaceType. |
- if (t.getKind() == TypeKind.INTERFACE) { |
- InterfaceType ti = (InterfaceType) t; |
- Type sBound = sv.getTypeVariableElement().getBound(); |
- if (sBound == null) { |
- return true; |
- } |
- // Prevent cycle. |
- if (sBound.equals(sv)) { |
- return false; |
- } |
- if (sBound.getKind() == TypeKind.INTERFACE) { |
- return isSubtype(ti, sBound); |
- } |
- } |
- // no |
- return false; |
- } |
- |
- private boolean isSubtypeOfInterface(Type t, InterfaceType s) { |
- // Special handling for union. |
- if (t instanceof InterfaceTypeUnion) { |
- InterfaceTypeUnion tUnion = (InterfaceTypeUnion) t; |
- for (InterfaceType unionPart : tUnion.getTypes()) { |
- if (isSubtype(unionPart, s)) { |
- return true; |
- } |
- } |
- return false; |
- } |
- |
- // class "t" implements call() and "s" is Function |
- if (TypeKind.of(t) == TypeKind.INTERFACE && typeProvider != null |
- && s == typeProvider.getFunctionType()) { |
- InterfaceType ti = (InterfaceType) t; |
- if (ti.lookupMember("call") != null) { |
- return true; |
- } |
- } |
- |
- // Try to cast "t" to "s". |
- final Type sup = asInstanceOf(t, s.getElement()); |
- if (TypeKind.of(sup) == TypeKind.INTERFACE) { |
- InterfaceType ti = (InterfaceType) sup; |
- assert ti.getElement().equals(s.getElement()); |
- if (ti.isRaw() || s.isRaw()) { |
- return true; |
- } |
- // Type arguments are covariant. |
- return areSubtypes(ti.getArguments().iterator(), s.getArguments().iterator()); |
- } |
- return false; |
- } |
- |
- /** |
- * Implement the Dart function subtype rule. Unlike the classic arrow rule (return type is |
- * covariant, and parameter types are contravariant), in Dart they must just be assignable. |
- */ |
- private boolean isSubtypeOfFunction(FunctionType t, FunctionType s) { |
- if (s.getKind() == TypeKind.DYNAMIC || t.getKind() == TypeKind.DYNAMIC) { |
- return true; |
- } |
- // Classic: return type is covariant; Dart: assignable. |
- if (!isAssignable(t.getReturnType(), s.getReturnType())) { |
- // A function that returns a value can be used as a function where you ignore the value. |
- if (!s.getReturnType().equals(typeProvider.getVoidType())) { |
- return false; |
- } |
- } |
- Type tRest = t.getRest(); |
- Type sRest = s.getRest(); |
- if ((tRest == null) != (sRest == null)) { |
- return false; |
- } |
- if (tRest != null) { |
- // Classic: parameter types are contravariant; Dart: assignable. |
- if (!isAssignable(sRest, tRest)) { |
- return false; |
- } |
- } |
- |
- { |
- Map<String, Type> sOpti = s.getOptionalParameterTypes(); |
- Map<String, Type> tOpti = t.getOptionalParameterTypes(); |
- if (tOpti.size() < sOpti.size()) { |
- return false; |
- } |
- Iterator<Entry<String, Type>> tList = tOpti.entrySet().iterator(); |
- Iterator<Entry<String, Type>> sList = sOpti.entrySet().iterator(); |
- while (sList.hasNext()) { |
- if (!tList.hasNext()) { |
- return false; |
- } |
- Entry<String, Type> sEntry = sList.next(); |
- Entry<String, Type> tEntry = tList.next(); |
- if (!isAssignable(tEntry.getValue(), sEntry.getValue())) { |
- return false; |
- } |
- } |
- } |
- |
- Map<String, Type> tNamed = t.getNamedParameterTypes(); |
- Map<String, Type> sNamed = s.getNamedParameterTypes(); |
- if (tNamed.isEmpty() && !sNamed.isEmpty()) { |
- return false; |
- } |
- |
- // T's named parameters must be in the same order and assignable to S's but |
- // maybe a superset. |
- if (!sNamed.isEmpty()) { |
- LinkedHashMap<String,Type> tMap = (LinkedHashMap<String, Type>)(tNamed); |
- LinkedHashMap<String,Type> sMap = (LinkedHashMap<String, Type>)(sNamed); |
- if (!tMap.keySet().containsAll(sMap.keySet())) { |
- return false; |
- } |
- for (Entry<String, Type> entry : sMap.entrySet()) { |
- String name = entry.getKey(); |
- Type sType = sMap.get(name); |
- Type tType = tMap.get(name); |
- if (!isAssignable(tType, sType)) { |
- return false; |
- } |
- } |
-// Iterator<Entry<String, Type>> tList = tMap.entrySet().iterator(); |
-// Iterator<Entry<String, Type>> sList = sMap.entrySet().iterator(); |
-// // t named parameters must start with the named parameters of s |
-// while (sList.hasNext()) { |
-// if (!tList.hasNext()) { |
-// return false; |
-// } |
-// Entry<String, Type> sEntry = sList.next(); |
-// Entry<String, Type> tEntry = tList.next(); |
-// if (!sEntry.getKey().equals(tEntry.getKey())) { |
-// return false; |
-// } |
-// // Classic: parameter types are contravariant; Dart: assignable. |
-// if (!isAssignable(tEntry.getValue(), sEntry.getValue())) { |
-// return false; |
-// } |
-// } |
- } |
- |
- // Classic: parameter types are contravariant; Dart: assignable. |
- return areAssignable(s.getParameterTypes().iterator(), t.getParameterTypes().iterator()); |
- } |
- |
- private boolean areSubtypes(Iterator<? extends Type> t, Iterator<? extends Type> s) { |
- while (t.hasNext() && s.hasNext()) { |
- if (!isSubtype(t.next(), s.next())) { |
- return false; |
- } |
- } |
- |
- // O(1) check to assert t and s are of same size. |
- return t.hasNext() == s.hasNext(); |
- } |
- |
- private boolean areAssignable(Iterator<? extends Type> t, Iterator<? extends Type> s) { |
- while (t.hasNext() && s.hasNext()) { |
- if (!isAssignable(t.next(), s.next())) { |
- return false; |
- } |
- } |
- |
- // O(1) check to assert t and s are of same size. |
- return t.hasNext() == s.hasNext(); |
- } |
- |
- /** |
- * Returns true if s is assignable to t. |
- */ |
- public boolean isAssignable(Type t, Type s) { |
- t.getClass(); // Quick null check. |
- s.getClass(); // Quick null check. |
- return isSubtype(t, s) || isSubtype(s, t); |
- } |
- |
- /** |
- * Translates the given type into an instantiation of the given |
- * element. This is done by walking the supertype hierarchy and |
- * substituting in the appropriate type arguments. |
- * |
- * <p>For example, if {@code GrowableArray<T>} is a subtype of |
- * {@code Array<T>}, then |
- * {@code asInstanceOf("GrowableArray<String>", "Array")} would |
- * return {@code Array<String>} |
- * |
- * @return null if t is not a subtype of element |
- */ |
- @VisibleForTesting |
- public InterfaceType asInstanceOf(Type t, ClassElement element) { |
- return checkedAsInstanceOf(t, element, new HashSet<TypeVariable>(), new HashSet<Type>()); |
- } |
- |
- private InterfaceType checkedAsInstanceOf(Type t, ClassElement element, |
- Set<TypeVariable> variablesReferenced, Set<Type> checkedTypes) { |
- // check for recursion |
- if (checkedTypes.contains(t)) { |
- return null; |
- } |
- checkedTypes.add(t); |
- // check current Type |
- switch (TypeKind.of(t)) { |
- case FUNCTION_ALIAS: |
- case INTERFACE: { |
- if (t.getElement().equals(element)) { |
- return (InterfaceType) t; |
- } |
- InterfaceType ti = (InterfaceType) t; |
- ClassElement tElement = ti.getElement(); |
- InterfaceType supertype = tElement.getSupertype(); |
- // super type |
- if (supertype != null) { |
- InterfaceType result = checkedAsInstanceOf(asSupertype(ti, supertype), element, |
- variablesReferenced, checkedTypes); |
- if (result != null) { |
- return result; |
- } |
- } |
- // interfaces |
- for (InterfaceType intf : tElement.getInterfaces()) { |
- InterfaceType result = checkedAsInstanceOf(asSupertype(ti, intf), element, |
- variablesReferenced, checkedTypes); |
- if (result != null) { |
- return result; |
- } |
- } |
- // mixins |
- for (InterfaceType mixin : tElement.getMixins()) { |
- if (mixin.getElement().equals(element)) { |
- return asSupertype(ti, mixin); |
- } |
- } |
- // no |
- return null; |
- } |
- case FUNCTION: { |
- Element e = t.getElement(); |
- switch (e.getKind()) { |
- case CLASS: |
- // e should be the interface Function in the core library. See the |
- // documentation comment on FunctionType. |
- InterfaceType ti = (InterfaceType) e.getType(); |
- return checkedAsInstanceOf(ti, element, variablesReferenced, checkedTypes); |
- default: |
- return null; |
- } |
- } |
- case VARIABLE: { |
- TypeVariable v = (TypeVariable) t; |
- Type bound = v.getTypeVariableElement().getBound(); |
- // Check for previously encountered variables to avoid getting stuck in an infinite loop. |
- if (variablesReferenced.contains(v)) { |
- if (bound instanceof InterfaceType) { |
- return (InterfaceType) bound; |
- } |
- return typeProvider.getObjectType(); |
- } |
- variablesReferenced.add(v); |
- return checkedAsInstanceOf(bound, element, variablesReferenced, checkedTypes); |
- } |
- default: |
- return null; |
- } |
- } |
- |
- private static InterfaceType asSupertype(InterfaceType type, InterfaceType supertype) { |
- if (supertype == null) { |
- return null; |
- } |
- if (type.isRaw()) { |
- return supertype.asRawType(); |
- } |
- List<Type> arguments = type.getArguments(); |
- List<Type> parameters = type.getElement().getTypeParameters(); |
- return supertype.subst(arguments, parameters); |
- } |
- |
- static void printTypesOn(StringBuilder sb, List<Type> types, |
- String start, String end) { |
- sb.append(start); |
- boolean first = true; |
- for (Type argument : types) { |
- if (!first) { |
- sb.append(", "); |
- } |
- sb.append(argument); |
- first = false; |
- } |
- sb.append(end); |
- } |
- |
- public static List<Type> subst(List<Type> types, |
- List<Type> arguments, List<Type> parameters) { |
- ArrayList<Type> result = new ArrayList<Type>(types.size()); |
- for (Type type : types) { |
- result.add(type.subst(arguments, parameters)); |
- } |
- return result; |
- } |
- |
- public static FunctionType makeFunctionType(ResolutionErrorListener listener, |
- ClassElement element, |
- List<VariableElement> parameters, |
- Type returnType) { |
- List<Type> parameterTypes = new ArrayList<Type>(parameters.size()); |
- Map<String, Type> optionalParameterTypes = null; |
- Map<String, Type> namedParameterTypes = null; |
- Type restParameter = null; |
- for (VariableElement parameter : parameters) { |
- Type type = parameter.getType(); |
- // TODO(scheglov) one we will make optional parameter not named, |
- // check isOptional() before isNamed() |
- if (parameter.isNamed()) { |
- if (namedParameterTypes == null) { |
- namedParameterTypes = new LinkedHashMap<String, Type>(); |
- } |
- namedParameterTypes.put(parameter.getName(), type); |
- } else if (parameter.isOptional()) { |
- if (optionalParameterTypes == null) { |
- optionalParameterTypes = new LinkedHashMap<String, Type>(); |
- } |
- optionalParameterTypes.put(parameter.getName(), type); |
- } else { |
- parameterTypes.add(type); |
- } |
- } |
- return FunctionTypeImplementation.of(element, parameterTypes, optionalParameterTypes, |
- namedParameterTypes, restParameter, returnType); |
- } |
- |
- public static Types getInstance(CoreTypeProvider typeProvider) { |
- return new Types(typeProvider); |
- } |
- |
- public static InterfaceType interfaceType(ClassElement element, List<Type> arguments) { |
- return new InterfaceTypeImplementation(element, arguments); |
- } |
- |
- public static FunctionAliasType functionAliasType(FunctionAliasElement element, |
- List<TypeVariable> typeVariables) { |
- return new FunctionAliasTypeImplementation(element, |
- Collections.<Type>unmodifiableList(typeVariables)); |
- } |
- |
- public static TypeVariable typeVariable(TypeVariableElement element) { |
- return new TypeVariableImplementation(element); |
- } |
- |
- public static DynamicType newDynamicType() { |
- return new DynamicTypeImplementation(); |
- } |
- |
- public static InterfaceType ensureInterface(Type type) { |
- TypeKind kind = TypeKind.of(type); |
- switch (kind) { |
- case INTERFACE: |
- return (InterfaceType) type; |
- case NONE: |
- case DYNAMIC: |
- return null; |
- default: |
- throw new AssertionError("unexpected kind " + kind); |
- } |
- } |
- |
- public static Type newVoidType() { |
- return new VoidType(); |
- } |
- |
- /** |
- * Returns the type node corresponding to the instantiated class or interface. |
- */ |
- public static DartTypeNode constructorTypeNode(DartNewExpression node) { |
- DartNode constructor = node.getConstructor(); |
- if (constructor instanceof DartPropertyAccess) { |
- return (DartTypeNode) ((DartPropertyAccess) constructor).getQualifier(); |
- } else { |
- return (DartTypeNode) constructor; |
- } |
- } |
- |
- /** |
- * Returns the interface type being instantiated by the given node. |
- */ |
- public static InterfaceType constructorType(DartNewExpression node) { |
- DartTypeNode typeNode = constructorTypeNode(node); |
- return (InterfaceType) typeNode.getType(); |
- } |
- |
- /** |
- * @return the wrapper of the given {@link Type} with {@link TypeQuality#INFERRED}. |
- */ |
- public static Type makeInferred(Type type) { |
- return makeInferred(type, TypeQuality.INFERRED); |
- } |
- |
- /** |
- * @return the wrapper of the given {@link Type} with {@link TypeQuality#INFERRED_EXACT}. |
- */ |
- public static Type makeInferredExact(Type type) { |
- return makeInferred(type, TypeQuality.INFERRED_EXACT); |
- } |
- |
- /** |
- * @return the wrapper of the given {@link Type} with given {@link TypeQuality}. |
- */ |
- public static Type makeInferred(Type type, TypeQuality quality) { |
- if (type == null) { |
- return null; |
- } |
- if (type.getQuality().ordinal() > quality.ordinal()) { |
- return type; |
- } |
- if (quality == TypeQuality.EXACT) { |
- return type; |
- } |
- Set<Class<?>> interfaceSet = getAllImplementedInterfaces(type.getClass()); |
- if (!interfaceSet.isEmpty()) { |
- Class<?>[] interfaces = interfaceSet.toArray(new Class[interfaceSet.size()]); |
- return makeInferred(type, interfaces, quality); |
- } |
- return type; |
- } |
- |
- private static Type makeInferred(final Type type, Class<?>[] interfaces, final TypeQuality quality) { |
- Map<TypeQuality, Type> inferredMap = inferredTypes.get(type); |
- if (inferredMap == null) { |
- inferredMap = new MapMaker().weakValues().makeMap(); |
- inferredTypes.put(type, inferredMap); |
- } |
- Type inferred = inferredMap.get(quality); |
- if (inferred == null) { |
- inferred = (Type) Proxy.newProxyInstance(type.getClass().getClassLoader(), |
- interfaces, new InvocationHandler() { |
- @Override |
- @SuppressWarnings("unchecked") |
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
- if (args == null && method.getName().equals("getQuality")) { |
- return quality; |
- } |
- if (type instanceof FunctionType) { |
- if (args == null && method.getName().equals("getParameterTypes")) { |
- List<Type> originalTypes = (List<Type>) method.invoke(type, args); |
- return Lists.transform(originalTypes, new Function<Type, Type>() { |
- public Type apply(Type input) { |
- return makeInferred(input, quality); |
- } |
- }); |
- } |
- } |
- return method.invoke(type, args); |
- } |
- }); |
- inferredMap.put(quality, inferred); |
- } |
- return inferred; |
- } |
- |
- /** |
- * @return all interfaces implemented by given {@link Class}. |
- */ |
- private static Set<Class<?>> getAllImplementedInterfaces(Class<?> c) { |
- Set<Class<?>> result = Sets.newHashSet(); |
- for (Class<?> intf : c.getInterfaces()) { |
- result.add(intf); |
- result.addAll(getAllImplementedInterfaces(intf)); |
- } |
- return result; |
- } |
-} |