1 /*******************************************************************************
2  * Copyright (c) 2007 - 2017 BEA Systems, Inc. and others
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *    Walter Harley - initial API and implementation
13  *    IBM Corporation - fix for 342598, 382590
14  *    Jean-Marie Henaff <jmhenaff@google.com> (Google) - Bug 481555
15  *******************************************************************************/
16 
17 package org.eclipse.jdt.internal.compiler.apt.model;
18 
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22 
23 import javax.lang.model.element.Element;
24 import javax.lang.model.element.TypeElement;
25 import javax.lang.model.type.ArrayType;
26 import javax.lang.model.type.DeclaredType;
27 import javax.lang.model.type.ExecutableType;
28 import javax.lang.model.type.NoType;
29 import javax.lang.model.type.NullType;
30 import javax.lang.model.type.PrimitiveType;
31 import javax.lang.model.type.TypeKind;
32 import javax.lang.model.type.TypeMirror;
33 import javax.lang.model.type.WildcardType;
34 import javax.lang.model.util.Types;
35 
36 import org.eclipse.jdt.core.compiler.CharOperation;
37 import org.eclipse.jdt.internal.compiler.apt.dispatch.BaseProcessingEnvImpl;
38 import org.eclipse.jdt.internal.compiler.ast.Wildcard;
39 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
40 import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
41 import org.eclipse.jdt.internal.compiler.lookup.Binding;
42 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
43 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
44 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
45 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
46 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
47 import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
48 
49 /**
50  * Utilities for working with types (as opposed to elements).
51  * There is one of these for every ProcessingEnvironment.
52  */
53 public class TypesImpl implements Types {
54 
55     private final BaseProcessingEnvImpl _env;
56 
57     /*
58      * The processing env creates and caches a TypesImpl.  Other clients should
59      * not create their own; they should ask the env for it.
60      */
TypesImpl(BaseProcessingEnvImpl env)61     public TypesImpl(BaseProcessingEnvImpl env) {
62         _env = env;
63     }
64 
65     /* (non-Javadoc)
66      * @see javax.lang.model.util.Types#asElement(javax.lang.model.type.TypeMirror)
67      */
68     @Override
asElement(TypeMirror t)69     public Element asElement(TypeMirror t) {
70         switch(t.getKind()) {
71         case DECLARED :
72         case TYPEVAR :
73             return _env.getFactory().newElement(((TypeMirrorImpl)t).binding());
74         default:
75             break;
76         }
77         return null;
78     }
79 
80     @Override
asMemberOf(DeclaredType containing, Element element)81 	public TypeMirror asMemberOf(DeclaredType containing, Element element) {
82 		// throw new UnsupportedOperationException("NYI: TypesImpl.asMemberOf("
83 		// + containing + ", " + element + ")"); //$NON-NLS-1$ //$NON-NLS-2$
84 		// //$NON-NLS-3$
85 		ElementImpl elementImpl = (ElementImpl) element;
86 		DeclaredTypeImpl declaredTypeImpl = (DeclaredTypeImpl) containing;
87 		ReferenceBinding referenceBinding = (ReferenceBinding) declaredTypeImpl._binding;
88 		TypeMirror typeMirror;
89 
90 		switch (element.getKind()) {
91 		case CONSTRUCTOR:
92 		case METHOD:
93 			typeMirror = findMemberInHierarchy(referenceBinding, elementImpl._binding, new MemberInTypeFinder() {
94 				@Override
95 				public TypeMirror find(ReferenceBinding typeBinding, Binding memberBinding) {
96 					MethodBinding methodBinding = ((MethodBinding) memberBinding);
97 					for (MethodBinding method : typeBinding.methods()) {
98 						if (CharOperation.equals(method.selector, methodBinding.selector)
99 								&& (method.original() == methodBinding
100 										|| method.areParameterErasuresEqual(methodBinding))) {
101 							return TypesImpl.this._env.getFactory().newTypeMirror(method);
102 						}
103 					}
104 					return null;
105 				}
106 			});
107 
108 			if (typeMirror != null) {
109 				return typeMirror;
110 			}
111 			break;
112 		case TYPE_PARAMETER:
113 			typeMirror = findMemberInHierarchy(referenceBinding, elementImpl._binding, new MemberInTypeFinder() {
114 				@Override
115 				public TypeMirror find(ReferenceBinding typeBinding, Binding memberBinding) {
116 					if (typeBinding instanceof ParameterizedTypeBinding) {
117 						TypeVariableBinding variableBinding = ((TypeVariableBinding) memberBinding);
118 						ReferenceBinding binding = ((ParameterizedTypeBinding) typeBinding).genericType();
119 						if (variableBinding.declaringElement == binding) { // check in advance avoid looking into type parameters unnecessarily.
120 							TypeVariableBinding[] typeVariables = binding.typeVariables();
121 							TypeBinding[] typeArguments = ((ParameterizedTypeBinding) typeBinding).typeArguments();
122 							if (typeVariables.length == typeArguments.length) {
123 								for(int i = 0; i < typeVariables.length; i++) {
124 									if (typeVariables[i] == memberBinding) {
125 										return TypesImpl.this._env.getFactory().newTypeMirror(typeArguments[i]);
126 									}
127 								}
128 							}
129 						}
130 					}
131 					return null;
132 				}
133 			});
134 
135 			if (typeMirror != null) {
136 				return typeMirror;
137 			}
138 			break;
139 		case FIELD:
140 		case ENUM_CONSTANT:
141 		case RECORD_COMPONENT:
142 			typeMirror = findMemberInHierarchy(referenceBinding, elementImpl._binding, new MemberInTypeFinder() {
143 				@Override
144 				public TypeMirror find(ReferenceBinding typeBinding, Binding memberBinding) {
145 					FieldBinding fieldBinding = (FieldBinding) memberBinding;
146 					for (FieldBinding field : typeBinding.fields()) {
147 						if (CharOperation.equals(field.name, fieldBinding.name)) {
148 							return TypesImpl.this._env.getFactory().newTypeMirror(field);
149 						}
150 					}
151 					return null;
152 				}
153 			});
154 
155 			if (typeMirror != null) {
156 				return typeMirror;
157 			}
158 			break;
159 		case ENUM:
160 		case ANNOTATION_TYPE:
161 		case INTERFACE:
162 		case CLASS:
163 		case RECORD:
164 			typeMirror = findMemberInHierarchy(referenceBinding, elementImpl._binding, new MemberInTypeFinder() {
165 				@Override
166 				public TypeMirror find(ReferenceBinding typeBinding, Binding memberBinding) {
167 					ReferenceBinding elementBinding = (ReferenceBinding) memberBinding;
168 					// If referenceBinding is a ParameterizedTypeBinding, this
169 					// will return only ParameterizedTypeBindings
170 					// for member types, even if the member happens to be a
171 					// static nested class. That's probably a bug;
172 					// static nested classes are not parameterized by their
173 					// outer class.
174 					for (ReferenceBinding memberReferenceBinding : typeBinding.memberTypes()) {
175 						if (CharOperation.equals(elementBinding.compoundName, memberReferenceBinding.compoundName)) {
176 							return TypesImpl.this._env.getFactory().newTypeMirror(memberReferenceBinding);
177 						}
178 					}
179 					return null;
180 				}
181 			});
182 
183 			if (typeMirror != null) {
184 				return typeMirror;
185 			}
186 			break;
187 		default:
188 			throw new IllegalArgumentException("element " + element + //$NON-NLS-1$
189 					" has unrecognized element kind " + element.getKind()); //$NON-NLS-1$
190 		}
191 		throw new IllegalArgumentException("element " + element + //$NON-NLS-1$
192 				" is not a member of the containing type " + containing + //$NON-NLS-1$
193 				" nor any of its superclasses"); //$NON-NLS-1$
194 	}
195 
196 	private static interface MemberInTypeFinder {
find(ReferenceBinding typeBinding, Binding memberBinding)197 		TypeMirror find(ReferenceBinding typeBinding, Binding memberBinding);
198 	}
199 
findMemberInHierarchy(ReferenceBinding typeBinding, Binding memberBinding, MemberInTypeFinder finder)200 	private TypeMirror findMemberInHierarchy(ReferenceBinding typeBinding, Binding memberBinding,
201 			MemberInTypeFinder finder) {
202 		TypeMirror result = null;
203 
204 		if (typeBinding == null) {
205 			return null;
206 		}
207 
208 		result = finder.find(typeBinding, memberBinding);
209 		if (result != null) {
210 			return result;
211 		}
212 
213 		result = findMemberInHierarchy(typeBinding.superclass(), memberBinding, finder);
214 		if (result != null) {
215 			return result;
216 		}
217 
218 		for (ReferenceBinding superInterface : typeBinding.superInterfaces()) {
219 			result = findMemberInHierarchy(superInterface, memberBinding, finder);
220 			if (result != null) {
221 				return result;
222 			}
223 		}
224 
225 		return null;
226 	}
validateRealType(TypeMirror t)227 	private void validateRealType(TypeMirror t) {
228 		switch (t.getKind()) {
229 			case EXECUTABLE:
230 			case PACKAGE:
231 			case MODULE:
232 				throw new IllegalArgumentException(
233 						"Executable, package and module are illegal argument for Types.contains(..)"); //$NON-NLS-1$
234 			default:
235 				break;
236 		}
237 	}
validateRealTypes(TypeMirror t1, TypeMirror t2)238 	private void validateRealTypes(TypeMirror t1, TypeMirror t2) {
239 		validateRealType(t1);
240 		validateRealType(t2);
241 	}
242 
243     @Override
boxedClass(PrimitiveType p)244     public TypeElement boxedClass(PrimitiveType p) {
245         PrimitiveTypeImpl primitiveTypeImpl = (PrimitiveTypeImpl) p;
246         BaseTypeBinding baseTypeBinding = (BaseTypeBinding)primitiveTypeImpl._binding;
247         TypeBinding boxed = _env.getLookupEnvironment().computeBoxingType(baseTypeBinding);
248         return (TypeElement) _env.getFactory().newElement(boxed);
249     }
250 
251     @Override
capture(TypeMirror t)252     public TypeMirror capture(TypeMirror t) {
253     	validateRealType(t);
254     	TypeMirrorImpl typeMirrorImpl = (TypeMirrorImpl) t;
255     	if (typeMirrorImpl._binding instanceof ParameterizedTypeBinding) {
256     		throw new UnsupportedOperationException("NYI: TypesImpl.capture(...)"); //$NON-NLS-1$
257     	}
258         return t;
259     }
260 
261     @Override
contains(TypeMirror t1, TypeMirror t2)262     public boolean contains(TypeMirror t1, TypeMirror t2) {
263     	validateRealTypes(t1, t2);
264         throw new UnsupportedOperationException("NYI: TypesImpl.contains(" + t1 + ", " + t2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
265     }
266 
267     @Override
directSupertypes(TypeMirror t)268     public List<? extends TypeMirror> directSupertypes(TypeMirror t) {
269     	validateRealType(t);
270         TypeMirrorImpl typeMirrorImpl = (TypeMirrorImpl) t;
271         Binding binding = typeMirrorImpl._binding;
272         if (binding instanceof ReferenceBinding) {
273             ReferenceBinding referenceBinding = (ReferenceBinding) binding;
274             ArrayList<TypeMirror> list = new ArrayList<>();
275             ReferenceBinding superclass = referenceBinding.superclass();
276             if (superclass != null) {
277                 list.add(this._env.getFactory().newTypeMirror(superclass));
278             }
279             for (ReferenceBinding interfaceBinding : referenceBinding.superInterfaces()) {
280                 list.add(this._env.getFactory().newTypeMirror(interfaceBinding));
281             }
282             return Collections.unmodifiableList(list);
283         }
284         return Collections.emptyList();
285     }
286 
287     @Override
erasure(TypeMirror t)288     public TypeMirror erasure(TypeMirror t) {
289     	validateRealType(t);
290         TypeMirrorImpl typeMirrorImpl = (TypeMirrorImpl) t;
291         Binding binding = typeMirrorImpl._binding;
292         if (binding instanceof ReferenceBinding) {
293         	TypeBinding type = ((ReferenceBinding) binding).erasure();
294         	if (type.isGenericType()) {
295         		type = _env.getLookupEnvironment().convertToRawType(type, false);
296         	}
297             return _env.getFactory().newTypeMirror(type);
298         }
299         if (binding instanceof ArrayBinding) {
300             TypeBinding typeBinding = (TypeBinding) binding;
301             TypeBinding leafType = typeBinding.leafComponentType().erasure();
302             if (leafType.isGenericType()) {
303             	leafType = _env.getLookupEnvironment().convertToRawType(leafType, false);
304             }
305             return _env.getFactory().newTypeMirror(
306                     this._env.getLookupEnvironment().createArrayType(leafType,
307                             typeBinding.dimensions()));
308         }
309         return t;
310     }
311 
312     @Override
getArrayType(TypeMirror componentType)313     public ArrayType getArrayType(TypeMirror componentType) {
314         TypeMirrorImpl typeMirrorImpl = (TypeMirrorImpl) componentType;
315         TypeBinding typeBinding = (TypeBinding) typeMirrorImpl._binding;
316         return (ArrayType) _env.getFactory().newTypeMirror(
317                 this._env.getLookupEnvironment().createArrayType(
318                         typeBinding.leafComponentType(),
319                         typeBinding.dimensions() + 1));
320     }
321 
322     /*
323      * (non-Javadoc)
324      * Create a type instance by parameterizing a type element. If the element is a member type,
325      * its container won't be parameterized (if it needs to be, you would need to use the form of
326      * getDeclaredType that takes a container TypeMirror). If typeArgs is empty, and typeElem
327      * is not generic, then you should use TypeElem.asType().  If typeArgs is empty and typeElem
328      * is generic, this method will create the raw type.
329      */
330     @Override
getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs)331     public DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) {
332         int typeArgsLength = typeArgs.length;
333         TypeElementImpl typeElementImpl = (TypeElementImpl) typeElem;
334         ReferenceBinding elementBinding = (ReferenceBinding) typeElementImpl._binding;
335         TypeVariableBinding[] typeVariables = elementBinding.typeVariables();
336         int typeVariablesLength = typeVariables.length;
337         if (typeArgsLength == 0) {
338             if (elementBinding.isGenericType()) {
339                 // per javadoc,
340                 return (DeclaredType) _env.getFactory().newTypeMirror(this._env.getLookupEnvironment().createRawType(elementBinding, null));
341             }
342             return (DeclaredType)typeElem.asType();
343         } else if (typeArgsLength != typeVariablesLength) {
344             throw new IllegalArgumentException("Number of typeArguments doesn't match the number of formal parameters of typeElem"); //$NON-NLS-1$
345         }
346         TypeBinding[] typeArguments = new TypeBinding[typeArgsLength];
347         for (int i = 0; i < typeArgsLength; i++) {
348             TypeMirrorImpl typeMirrorImpl = (TypeMirrorImpl) typeArgs[i];
349             Binding binding = typeMirrorImpl._binding;
350             if (!(binding instanceof TypeBinding)) {
351                 throw new IllegalArgumentException("Invalid type argument: " + typeMirrorImpl); //$NON-NLS-1$
352             }
353             typeArguments[i] = (TypeBinding) binding;
354         }
355 
356         ReferenceBinding enclosing = elementBinding.enclosingType();
357         if (enclosing != null) {
358             enclosing = this._env.getLookupEnvironment().createRawType(enclosing, null);
359         }
360 
361         return (DeclaredType) _env.getFactory().newTypeMirror(
362                 this._env.getLookupEnvironment().createParameterizedType(elementBinding, typeArguments, enclosing));
363     }
364 
365     /* (non-Javadoc)
366      * Create a specific type from a member element. The containing type can be parameterized,
367      * e.g. Outer<String>.Inner, but it cannot be generic, i.e., Outer<T>.Inner. It only makes
368      * sense to use this method when the member element is parameterized by its container; so,
369      * for example, it makes sense for an inner class but not for a static member class.
370      * Otherwise you should just use getDeclaredType(TypeElement, TypeMirror ...), if you need
371      * to specify type arguments, or TypeElement.asType() directly, if not.
372      */
373     @Override
getDeclaredType(DeclaredType containing, TypeElement typeElem, TypeMirror... typeArgs)374     public DeclaredType getDeclaredType(DeclaredType containing, TypeElement typeElem,
375             TypeMirror... typeArgs) {
376         int typeArgsLength = typeArgs.length;
377         TypeElementImpl typeElementImpl = (TypeElementImpl) typeElem;
378         ReferenceBinding elementBinding = (ReferenceBinding) typeElementImpl._binding;
379         TypeVariableBinding[] typeVariables = elementBinding.typeVariables();
380         int typeVariablesLength = typeVariables.length;
381         DeclaredTypeImpl declaredTypeImpl = (DeclaredTypeImpl) containing;
382         ReferenceBinding enclosingType = (ReferenceBinding) declaredTypeImpl._binding;
383         if (typeArgsLength == 0) {
384             if (elementBinding.isGenericType()) {
385                 // e.g., Outer.Inner<T> but T is not specified
386                 // Per javadoc on interface, must return the raw type Outer.Inner
387                 return (DeclaredType) _env.getFactory().newTypeMirror(
388                         _env.getLookupEnvironment().createRawType(elementBinding, enclosingType));
389             } else {
390                 // e.g., Outer<Long>.Inner
391                 ParameterizedTypeBinding ptb = _env.getLookupEnvironment().createParameterizedType(elementBinding, null, enclosingType);
392                 return (DeclaredType) _env.getFactory().newTypeMirror(ptb);
393             }
394         } else if (typeArgsLength != typeVariablesLength) {
395             throw new IllegalArgumentException("Number of typeArguments doesn't match the number of formal parameters of typeElem"); //$NON-NLS-1$
396         }
397         TypeBinding[] typeArguments = new TypeBinding[typeArgsLength];
398         for (int i = 0; i < typeArgsLength; i++) {
399             TypeMirrorImpl typeMirrorImpl = (TypeMirrorImpl) typeArgs[i];
400             Binding binding = typeMirrorImpl._binding;
401             if (!(binding instanceof TypeBinding)) {
402                 throw new IllegalArgumentException("Invalid type for a type arguments : " + typeMirrorImpl); //$NON-NLS-1$
403             }
404             typeArguments[i] = (TypeBinding) binding;
405         }
406         return (DeclaredType) _env.getFactory().newTypeMirror(
407                 this._env.getLookupEnvironment().createParameterizedType(elementBinding, typeArguments, enclosingType));
408     }
409 
410     @Override
getNoType(TypeKind kind)411     public NoType getNoType(TypeKind kind) {
412         return _env.getFactory().getNoType(kind);
413     }
414 
415     @Override
getNullType()416     public NullType getNullType() {
417         return _env.getFactory().getNullType();
418     }
419 
420     @Override
getPrimitiveType(TypeKind kind)421     public PrimitiveType getPrimitiveType(TypeKind kind) {
422         return _env.getFactory().getPrimitiveType(kind);
423     }
424 
425     @Override
getWildcardType(TypeMirror extendsBound, TypeMirror superBound)426     public WildcardType getWildcardType(TypeMirror extendsBound, TypeMirror superBound) {
427         if (extendsBound != null && superBound != null) {
428             throw new IllegalArgumentException("Extends and super bounds cannot be set at the same time"); //$NON-NLS-1$
429         }
430         if (extendsBound != null) {
431             TypeMirrorImpl extendsBoundMirrorType = (TypeMirrorImpl) extendsBound;
432             TypeBinding typeBinding = (TypeBinding) extendsBoundMirrorType._binding;
433             return (WildcardType) _env.getFactory().newTypeMirror(
434                     this._env.getLookupEnvironment().createWildcard(
435                             null,
436                             0,
437                             typeBinding,
438                             null,
439                             Wildcard.EXTENDS));
440         }
441         if (superBound != null) {
442             TypeMirrorImpl superBoundMirrorType = (TypeMirrorImpl) superBound;
443             TypeBinding typeBinding = (TypeBinding) superBoundMirrorType._binding;
444             return new WildcardTypeImpl(_env, this._env.getLookupEnvironment().createWildcard(
445                     null,
446                     0,
447                     typeBinding,
448                     null,
449                     Wildcard.SUPER));
450         }
451         return new WildcardTypeImpl(_env, this._env.getLookupEnvironment().createWildcard(
452                 null,
453                 0,
454                 null,
455                 null,
456                 Wildcard.UNBOUND));
457     }
458 
459     /* (non-Javadoc)
460      * @return true if a value of type t1 can be assigned to a variable of type t2, i.e., t2 = t1.
461      */
462     @Override
isAssignable(TypeMirror t1, TypeMirror t2)463     public boolean isAssignable(TypeMirror t1, TypeMirror t2) {
464     	validateRealTypes(t1, t2);
465         if (!(t1 instanceof TypeMirrorImpl) || !(t2 instanceof TypeMirrorImpl)) {
466         	return false;
467         }
468         Binding b1 = ((TypeMirrorImpl)t1).binding();
469         Binding b2 = ((TypeMirrorImpl)t2).binding();
470         if (!(b1 instanceof TypeBinding) || !(b2 instanceof TypeBinding)) {
471             // package, method, import, etc.
472             throw new IllegalArgumentException();
473         }
474         if (((TypeBinding)b1).isCompatibleWith((TypeBinding)b2)) {
475             return true;
476         }
477 
478         TypeBinding convertedType = _env.getLookupEnvironment().computeBoxingType((TypeBinding)b1);
479         return null != convertedType && convertedType.isCompatibleWith((TypeBinding)b2);
480     }
481 
482     @Override
isSameType(TypeMirror t1, TypeMirror t2)483     public boolean isSameType(TypeMirror t1, TypeMirror t2) {
484         if (t1 instanceof NoTypeImpl) {
485             if (t2 instanceof NoTypeImpl) {
486                 return ((NoTypeImpl) t1).getKind() == ((NoTypeImpl) t2).getKind();
487             }
488             return false;
489         } else if (t2 instanceof NoTypeImpl) {
490             return false;
491         }
492         if (t1.getKind() == TypeKind.WILDCARD || t2.getKind() == TypeKind.WILDCARD) {
493             // Wildcard types are never equal, according to the spec of this method
494             return false;
495         }
496         if (t1 == t2) {
497             return true;
498         }
499         if (!(t1 instanceof TypeMirrorImpl) || !(t2 instanceof TypeMirrorImpl)) {
500             return false;
501         }
502         Binding b1 = ((TypeMirrorImpl)t1).binding();
503         Binding b2 = ((TypeMirrorImpl)t2).binding();
504 
505         if (b1 == b2) {
506             return true;
507         }
508         if (!(b1 instanceof TypeBinding) || !(b2 instanceof TypeBinding)) {
509             return false;
510         }
511         TypeBinding type1 = ((TypeBinding) b1);
512         TypeBinding type2 = ((TypeBinding) b2);
513         if (TypeBinding.equalsEquals(type1,  type2))
514         	return true;
515         return CharOperation.equals(type1.computeUniqueKey(), type2.computeUniqueKey());
516     }
517 
518     @Override
isSubsignature(ExecutableType m1, ExecutableType m2)519     public boolean isSubsignature(ExecutableType m1, ExecutableType m2) {
520         MethodBinding methodBinding1 = (MethodBinding) ((ExecutableTypeImpl) m1)._binding;
521         MethodBinding methodBinding2 = (MethodBinding) ((ExecutableTypeImpl) m2)._binding;
522         if (!CharOperation.equals(methodBinding1.selector, methodBinding2.selector))
523             return false;
524         return methodBinding1.areParameterErasuresEqual(methodBinding2) && methodBinding1.areTypeVariableErasuresEqual(methodBinding2);
525     }
526 
527     /* (non-Javadoc)
528      * @return true if t1 is a subtype of t2, or if t1 == t2.
529      */
530     @Override
isSubtype(TypeMirror t1, TypeMirror t2)531     public boolean isSubtype(TypeMirror t1, TypeMirror t2) {
532     	validateRealTypes(t1, t2);
533         if (t1 instanceof NoTypeImpl) {
534             if (t2 instanceof NoTypeImpl) {
535                 return ((NoTypeImpl) t1).getKind() == ((NoTypeImpl) t2).getKind();
536             }
537             return false;
538         } else if (t2 instanceof NoTypeImpl) {
539             return false;
540         }
541         if (!(t1 instanceof TypeMirrorImpl) || !(t2 instanceof TypeMirrorImpl)) {
542         	throw new IllegalArgumentException();
543         }
544         if (t1 == t2) {
545             return true;
546         }
547         Binding b1 = ((TypeMirrorImpl)t1).binding();
548         Binding b2 = ((TypeMirrorImpl)t2).binding();
549         if (b1 == b2) {
550             return true;
551         }
552         if (!(b1 instanceof TypeBinding) || !(b2 instanceof TypeBinding)) {
553             // package, method, import, etc.
554         	 throw new IllegalArgumentException();
555         }
556         if (b1.kind() == Binding.BASE_TYPE || b2.kind() == Binding.BASE_TYPE) {
557             if (b1.kind() != b2.kind()) {
558                 return false;
559             }
560             else {
561                 // for primitives, compatibility implies subtype
562                 return ((TypeBinding)b1).isCompatibleWith((TypeBinding)b2);
563             }
564         }
565         return ((TypeBinding)b1).isCompatibleWith((TypeBinding)b2);
566     }
567 
568     @Override
unboxedType(TypeMirror t)569     public PrimitiveType unboxedType(TypeMirror t) {
570         if (!(((TypeMirrorImpl)t)._binding instanceof ReferenceBinding)) {
571             // Not an unboxable type - could be primitive, array, not a type at all, etc.
572             throw new IllegalArgumentException("Given type mirror cannot be unboxed"); //$NON-NLS-1$
573         }
574         ReferenceBinding boxed = (ReferenceBinding)((TypeMirrorImpl)t)._binding;
575         TypeBinding unboxed = _env.getLookupEnvironment().computeBoxingType(boxed);
576         if (unboxed.kind() != Binding.BASE_TYPE) {
577             // No boxing conversion was found
578             throw new IllegalArgumentException();
579         }
580         return (PrimitiveType) _env.getFactory().newTypeMirror((BaseTypeBinding)unboxed);
581     }
582 
583 }
584