1 /*******************************************************************************
2  * Copyright (c) 2000, 2016 IBM Corporation 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  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types;
15 
16 import java.util.ArrayList;
17 import java.util.List;
18 import java.util.Map;
19 
20 import org.eclipse.core.runtime.Assert;
21 
22 import org.eclipse.jdt.core.dom.ITypeBinding;
23 
24 
25 /**
26  * TTypes are lightweight fully-resolved type objects that stand for {@link ITypeBinding}s.
27  * TTypes can answer basic questions about the relationship between types.
28  *
29  * They do not hold references to their corresponding {@link ITypeBinding}s, and they
30  * don't carry any information about members of a type.
31  *
32  * @see TypeEnvironment
33  * @see TType#canAssignTo(TType)
34  * @see HierarchyType#isSubType(HierarchyType)
35  * @see TType#getSubTypes()
36  */
37 public abstract class TType {
38 
39 	public static final int NULL_TYPE= 1;
40 	public static final int VOID_TYPE= 2;
41 	public static final int PRIMITIVE_TYPE= 3;
42 
43 	public static final int ARRAY_TYPE= 4;
44 
45 	public static final int STANDARD_TYPE= 5;
46 	public static final int GENERIC_TYPE= 6;
47 	public static final int PARAMETERIZED_TYPE= 7;
48 	public static final int RAW_TYPE= 8;
49 
50 	public static final int UNBOUND_WILDCARD_TYPE= 9;
51 	public static final int SUPER_WILDCARD_TYPE= 10;
52 	public static final int EXTENDS_WILDCARD_TYPE= 11;
53 
54 	public static final int TYPE_VARIABLE= 12;
55 	public static final int CAPTURE_TYPE= 13;
56 
57 	protected static final int WILDCARD_TYPE_SHIFT= 3;
58 	protected static final int ARRAY_TYPE_SHIFT= 5;
59 
60 	private static final int F_IS_CLASS= 1 << 0;
61 	private static final int F_IS_INTERFACE= 1 << 1;
62 	private static final int F_IS_ENUM= 1 << 2;
63 	private static final int F_IS_ANNOTATION= 1 << 3;
64 
65 	private static final int F_IS_TOP_LEVEL= 1 << 4;
66 	private static final int F_IS_NESTED= 1 << 5;
67 	private static final int F_IS_MEMBER= 1 << 6;
68 	private static final int F_IS_LOCAL= 1 << 7;
69 	private static final int F_IS_ANONYMOUS= 1 << 8;
70 
71 	protected static final TType[] EMPTY_TYPE_ARRAY= new TType[0];
72 
73 	private TypeEnvironment fEnvironment;
74 	private String fBindingKey;
75 	private int fModifiers;
76 	private int fFlags;
77 
78 	/**
79 	 * Creates a new type with the given environment as an owner.
80 	 * The type environment <em>must</em> call {@link #initialize(ITypeBinding)} after using this constructor.
81 	 *
82 	 * @param environment owner
83 	 */
TType(TypeEnvironment environment)84 	protected TType(TypeEnvironment environment) {
85 		fEnvironment= environment;
86 	}
87 
88 	/**
89 	 * Creates a new type with the given environment as an owner.
90 	 * The type environment must <em>not</em> call {@link #initialize(ITypeBinding)} after using this constructor.
91 	 *
92 	 * @param environment owner
93 	 * @param key this type's binding key
94 	 */
TType(TypeEnvironment environment, String key)95 	protected TType(TypeEnvironment environment, String key) {
96 		this(environment);
97 		Assert.isNotNull(key);
98 		fBindingKey= key;
99 	}
100 
101 	/**
102 	 * Initialized the type from the given binding
103 	 *
104 	 * @param binding the binding to initialize from
105 	 */
initialize(ITypeBinding binding)106 	protected void initialize(ITypeBinding binding) {
107 		fBindingKey= binding.getKey();
108 		Assert.isNotNull(fBindingKey);
109 		fModifiers= binding.getModifiers();
110 		if (binding.isClass()) {
111 			fFlags= F_IS_CLASS;
112 		// the annotation test has to be done before test for interface
113 		// since annotations are interfaces as well.
114 		} else if (binding.isAnnotation()) {
115 			fFlags= F_IS_ANNOTATION | F_IS_INTERFACE;
116 		} else if (binding.isInterface()) {
117 			fFlags= F_IS_INTERFACE;
118 		} else if (binding.isEnum()) {
119 			fFlags= F_IS_ENUM;
120 		}
121 
122 		if (binding.isTopLevel()) {
123 			fFlags|= F_IS_TOP_LEVEL;
124 		} else if (binding.isNested()) {
125 			fFlags|= F_IS_NESTED;
126 			if (binding.isMember()) {
127 				fFlags|= F_IS_MEMBER;
128 			} else if (binding.isLocal()) {
129 				fFlags|= F_IS_LOCAL;
130 			} else if (binding.isAnonymous()) {
131 				fFlags|= F_IS_ANONYMOUS;
132 			}
133 		}
134 	}
135 
136 	/**
137 	 * Returns the type's environment
138 	 *
139 	 * @return the types's environment
140 	 */
getEnvironment()141 	public TypeEnvironment getEnvironment() {
142 		return fEnvironment;
143 	}
144 
145 	/**
146 	 * Returns the key of the binding from which this type
147 	 * got constructed.
148 	 *
149 	 * @return the binding key
150 	 */
getBindingKey()151 	public String getBindingKey() {
152 		return fBindingKey;
153 	}
154 
155 	/**
156 	 * Returns the modifiers for this type.
157 	 *
158 	 * @return the bit-wise or of <code>Modifier</code> constants
159 	 * @see org.eclipse.jdt.core.dom.IBinding#getModifiers()
160 	 * @see org.eclipse.jdt.core.dom.Modifier
161 	 */
getModifiers()162 	public int getModifiers() {
163 		return fModifiers;
164 	}
165 
166 	/**
167 	 * Returns the element kind
168 	 *
169 	 * @return the element kind.
170 	 */
getKind()171 	public abstract int getKind();
172 
173 	/**
174 	 * Returns whether this type represents <code>java.lang.Object</code> or
175 	 * not.
176 	 *
177 	 * @return whether this type is <code>java.lang.Object</code> or not
178 	 */
isJavaLangObject()179 	public boolean isJavaLangObject() {
180 		return false;
181 	}
182 
183 	/**
184 	 * Returns whether this type represents <code>java.lang.Cloneable</code>
185 	 * or not.
186 	 *
187 	 * @return whether this type is <code>java.lang.Cloneable</code> or not
188 	 */
isJavaLangCloneable()189 	public boolean isJavaLangCloneable() {
190 		return false;
191 	}
192 
193 	/**
194 	 * Returns whether this type represents <code>java.io.Serializable</code>
195 	 * or not.
196 	 *
197 	 * @return whether this type is <code>java.io.Serializable</code> or not
198 	 */
isJavaIoSerializable()199 	public boolean isJavaIoSerializable() {
200 		return false;
201 	}
202 
203 	/**
204 	 * Returns <code>true</code> if the given type represents the null type.
205 	 * Otherwise <code>false</code> is returned.
206 	 *
207 	 * @return whether this type is the null type or not
208 	 */
isNullType()209 	public final boolean isNullType() {
210 		return getKind() == NULL_TYPE;
211 	}
212 
213 	/**
214 	 * Returns <code>true</code> if the given type represents the void type.
215 	 * Otherwise <code>false</code> is returned.
216 	 *
217 	 * @return whether this type is the void type or not
218 	 */
isVoidType()219 	public final boolean isVoidType() {
220 		return getKind() == VOID_TYPE;
221 	}
222 
223 	/**
224 	 * Returns <code>true</code> if the given type represents a primitive type.
225 	 * Otherwise <code>false</code> is returned.
226 	 *
227 	 * @return whether this type is a primitive type or not
228 	 */
isPrimitiveType()229 	public final boolean isPrimitiveType() {
230 		return getKind() == PRIMITIVE_TYPE;
231 	}
232 
233 	/**
234 	 * Returns <code>true</code> if the given type represents an array type.
235 	 * Otherwise <code>false</code> is returned.
236 	 *
237 	 * @return whether this type is an array type or not
238 	 */
isArrayType()239 	public final boolean isArrayType() {
240 		return getKind() == ARRAY_TYPE;
241 	}
242 
243 	/**
244 	 * Returns <code>true</code> if the given type represents a hierarchy type.
245 	 * Otherwise <code>false</code> is returned.
246 	 *
247 	 * @return whether this type is a hierarchy type or not
248 	 */
isHierarchyType()249 	public final boolean isHierarchyType() {
250 		int elementType= getKind();
251 		return elementType == RAW_TYPE || elementType == PARAMETERIZED_TYPE
252 			|| elementType == GENERIC_TYPE || elementType == STANDARD_TYPE;
253 	}
254 
255 	/**
256 	 * Returns <code>true</code> if the given type represents a standard type.
257 	 * Otherwise <code>false</code> is returned.
258 	 *
259 	 * @return whether this type is a standard type or not
260 	 */
isStandardType()261 	public final boolean isStandardType() {
262 		return getKind() == STANDARD_TYPE;
263 	}
264 
265 	/**
266 	 * Returns <code>true</code> if the given type represents a raw type.
267 	 * Otherwise <code>false</code> is returned.
268 	 *
269 	 * @return whether this type is a raw type or not
270 	 */
isRawType()271 	public final boolean isRawType() {
272 		return getKind() == RAW_TYPE;
273 	}
274 
275 	/**
276 	 * Returns <code>true</code> if the given type represents a parameterized type.
277 	 * Otherwise <code>false</code> is returned.
278 	 *
279 	 * @return whether this type is a parameterized type or not
280 	 */
isParameterizedType()281 	public final boolean isParameterizedType() {
282 		return getKind() == PARAMETERIZED_TYPE;
283 	}
284 
285 	/**
286 	 * Returns <code>true</code> if the given type represents a generic type.
287 	 * Otherwise <code>false</code> is returned.
288 	 *
289 	 * @return whether this type is a generic type or not
290 	 */
isGenericType()291 	public final boolean isGenericType() {
292 		return getKind() == GENERIC_TYPE;
293 	}
294 
295 	/**
296 	 * Returns <code>true</code> if the given type represents a type variable.
297 	 * Otherwise <code>false</code> is returned.
298 	 *
299 	 * @return whether this type is a type variable or not
300 	 */
isTypeVariable()301 	public final boolean isTypeVariable() {
302 		return getKind() == TYPE_VARIABLE;
303 	}
304 
305 	/**
306 	 * Returns <code>true</code> if the given type represents a capture type.
307 	 * Otherwise <code>false</code> is returned.
308 	 *
309 	 * @return whether this type is a capture type or not
310 	 */
isCaptureType()311 	public final boolean isCaptureType() {
312 		return getKind() == CAPTURE_TYPE;
313 	}
314 
315 	/**
316 	 * Returns <code>true</code> if the given type represents a wildcard type.
317 	 * Otherwise <code>false</code> is returned.
318 	 *
319 	 * @return whether this type is a wildcard type or not
320 	 */
isWildcardType()321 	public final boolean isWildcardType() {
322 		int elementType= getKind();
323 		return elementType == EXTENDS_WILDCARD_TYPE || elementType == UNBOUND_WILDCARD_TYPE
324 			|| elementType == SUPER_WILDCARD_TYPE;
325 	}
326 
327 	/**
328 	 * Returns <code>true</code> if the given type represents a unbound wildcard type.
329 	 * Otherwise <code>false</code> is returned.
330 	 *
331 	 * @return whether this type is a unbound wildcard type or not
332 	 */
isUnboundWildcardType()333 	public final boolean isUnboundWildcardType() {
334 		return getKind() == UNBOUND_WILDCARD_TYPE;
335 	}
336 
337 	/**
338 	 * Returns <code>true</code> if the given type represents an extends wildcard type.
339 	 * Otherwise <code>false</code> is returned.
340 	 *
341 	 * @return whether this type is an extends wildcard type or not
342 	 */
isExtendsWildcardType()343 	public final boolean isExtendsWildcardType() {
344 		return getKind() == EXTENDS_WILDCARD_TYPE;
345 	}
346 
347 	/**
348 	 * Returns <code>true</code> if the given type represents a super wildcard type.
349 	 * Otherwise <code>false</code> is returned.
350 	 *
351 	 * @return whether this type is a super wildcard type or not
352 	 */
isSuperWildcardType()353 	public final boolean isSuperWildcardType() {
354 		return getKind() == SUPER_WILDCARD_TYPE;
355 	}
356 
357 	/**
358 	 * Returns whether this type represents a class.
359 	 *
360 	 * @return whether this type represents a class
361 	 * @see ITypeBinding#isClass()
362 	 */
isClass()363 	public final boolean isClass() {
364 		return (fFlags & F_IS_CLASS) != 0;
365 	}
366 
367 	/**
368 	 * Returns whether this type represents a interface.
369 	 *
370 	 * @return whether this type represents a interface
371 	 * @see ITypeBinding#isInterface()
372 	 */
isInterface()373 	public final boolean isInterface() {
374 		return (fFlags & F_IS_INTERFACE) != 0;
375 	}
376 
377 	/**
378 	 * Returns whether this type represents a enumeration.
379 	 *
380 	 * @return whether this type represents a enumeration
381 	 * @see ITypeBinding#isEnum()
382 	 */
isEnum()383 	public final boolean isEnum() {
384 		return (fFlags & F_IS_ENUM) != 0;
385 	}
386 
387 	/**
388 	 * Returns whether this type represents an annotation.
389 	 *
390 	 * @return whether this type represents an annotation
391 	 * @see ITypeBinding#isAnnotation()
392 	 */
isAnnotation()393 	public final boolean isAnnotation() {
394 		return (fFlags & F_IS_ANNOTATION) != 0;
395 	}
396 
397 	/**
398 	 * Returns whether this type represents a top level type.
399 	 *
400 	 * @return whether this type represents a top level type
401 	 * @see ITypeBinding#isTopLevel()
402 	 */
isTopLevel()403 	public final boolean isTopLevel() {
404 		return (fFlags & F_IS_TOP_LEVEL) != 0;
405 	}
406 
407 	/**
408 	 * Returns whether this type represents a nested type.
409 	 *
410 	 * @return whether this type represents a nested type
411 	 * @see ITypeBinding#isNested()
412 	 */
isNested()413 	public final boolean isNested() {
414 		return (fFlags & F_IS_NESTED) != 0;
415 	}
416 
417 	/**
418 	 * Returns whether this type represents a member type.
419 	 *
420 	 * @return whether this type represents a member type
421 	 * @see ITypeBinding#isMember()
422 	 */
isMember()423 	public final boolean isMember() {
424 		return (fFlags & F_IS_MEMBER) != 0;
425 	}
426 
427 	/**
428 	 * Returns whether this type represents a local type.
429 	 *
430 	 * @return whether this type represents a local type
431 	 * @see ITypeBinding#isLocal()
432 	 */
isLocal()433 	public final boolean isLocal() {
434 		return (fFlags & F_IS_LOCAL) != 0;
435 	}
436 
437 	/**
438 	 * Returns whether this type represents an anonymous type.
439 	 *
440 	 * @return whether this type represents an anonymous type
441 	 * @see ITypeBinding#isAnonymous()
442 	 */
isAnonymous()443 	public final boolean isAnonymous() {
444 		return (fFlags & F_IS_ANONYMOUS) != 0;
445 	}
446 
447 	/**
448 	 * Returns the super classes of this type or <code>null</code>.
449 	 *
450 	 * @return the super class of this type
451 	 */
getSuperclass()452 	public TType getSuperclass() {
453 		return null;
454 	}
455 
456 	/**
457 	 * Returns the interfaces this type implements or extends.
458 	 *
459 	 * @return the "super" interfaces or an empty array
460 	 */
getInterfaces()461 	public TType[] getInterfaces() {
462 		return EMPTY_TYPE_ARRAY;
463 	}
464 
isEqualTo(ITypeBinding binding)465 	public boolean isEqualTo(ITypeBinding binding) {
466 		if (binding == null)
467 			return false;
468 		return binding.getKey().equals(fBindingKey);
469 	}
470 
471 	@Override
equals(Object other)472 	public final boolean equals(Object other) {
473 		if (this == other)
474 			return true;
475 		if (!(other instanceof TType))
476 			return false;
477 		TType otherType= (TType)other;
478 		if (getKind() != otherType.getKind())
479 			return false;
480 		return doEquals(otherType);
481 	}
482 
483 	@Override
hashCode()484 	public abstract int hashCode();
485 
486 	/**
487 	 * Performs the actual equals check.
488 	 *
489 	 * @param type The right hand side of the equals operation. The dynamic type
490 	 *        of the actual argument must be the same as the receiver type.
491 	 * @return <code>true</code> iff this type is the same as the argument
492 	 */
doEquals(TType type)493 	protected abstract boolean doEquals(TType type);
494 
495 	/**
496 	 * Returns the erasure of this type as defined by ITypeBinding#getErasure().
497 	 *
498 	 * @return the erasure of this type
499 	 */
getErasure()500 	public TType getErasure() {
501 		return this;
502 	}
503 
504 	/**
505 	 * Returns the type for the type declaration corresponding to this type.
506 	 *
507 	 * @return the type representing the declaration of this type
508 	 * @see ITypeBinding#getTypeDeclaration()
509 	 */
getTypeDeclaration()510 	public TType getTypeDeclaration() {
511 		return this;
512 	}
513 
514 	/**
515 	 * @return direct subtypes of this type
516 	 * @throws IllegalStateException if this type's TypeEnvironment
517 	 * 		was not created with rememberSubtypes == true
518 	 */
getSubTypes()519 	public TType[] getSubTypes() throws IllegalStateException {
520 		Map<TType, ArrayList<TType>> subTypes= fEnvironment.getSubTypes();
521 		if (subTypes == null)
522 			throw new IllegalStateException("This TypeEnvironment does not remember subtypes"); //$NON-NLS-1$
523 		List<TType> subtypes= subTypes.get(this);
524 		if (subtypes == null)
525 			return EMPTY_TYPE_ARRAY;
526 		else
527 			return subtypes.toArray(new TType[subtypes.size()]);
528 	}
529 
530 	/**
531 	 * Answer <code>true</code> if the receiver of this method can be assigned
532 	 * to the argument lhs (e.g lhs= this is a valid assignment).
533 	 *
534 	 * @param lhs the left hand side of the assignment
535 	 * @return whether or not this type can be assigned to lhs
536 	 */
canAssignTo(TType lhs)537 	public final boolean canAssignTo(TType lhs) {
538 		if (this.isTypeEquivalentTo(lhs))
539 			return true;
540 		return doCanAssignTo(lhs);
541 	}
542 
543 	/**
544 	 * Returns whether the receiver type is type equivalent to the other type.
545 	 * This method considers the erasure for generic, raw and parameterized
546 	 * types.
547 	 *
548 	 * @param other the other type
549 	 * @return whether the receiver is type equivalent to other
550 	 */
isTypeEquivalentTo(TType other)551 	protected boolean isTypeEquivalentTo(TType other) {
552 		return this.equals(other);
553 	}
554 
555 	/**
556 	 * Checks whether the <code>this</code> left hand side type interpreted as
557 	 * a type argument of a parameterized type is compatible with the given type
558 	 * <code>rhs</code>. For example if
559 	 * <code>List&lt;this&gt;= List&lt;rhs&gt;</code> is a valid assignment.
560 	 *
561 	 * @param rhs the right-hand-side type
562 	 * @return <code>true</code> iff <code>this</code> contains <code>rhs</code> according to JLS3 4.5.1.1
563 	 */
checkTypeArgument(TType rhs)564 	protected boolean checkTypeArgument(TType rhs) {
565 		return this.equals(rhs);
566 	}
567 
568 	/**
569 	 * Hook method to perform the actual can assign test
570 	 *
571 	 * @param lhs the left hand side of the assignment
572 	 * @return whether or not this type can be assigned to lhs
573 	 */
doCanAssignTo(TType lhs)574 	protected abstract boolean doCanAssignTo(TType lhs);
575 
576 	/**
577 	 * Returns the name of this type as defined by {@link ITypeBinding#getName()}.
578 	 *
579 	 * @return the name of this type
580 	 * @see ITypeBinding#getName()
581 	 */
getName()582 	public abstract String getName();
583 
584 	/**
585 	 * Returns a signature of this type which can be presented to the user.
586 	 *
587 	 * @return a pretty signature for this type
588 	 */
getPrettySignature()589 	public String getPrettySignature() {
590 		return getPlainPrettySignature();
591 	}
592 
593 	/**
594 	 * Computes a plain pretty signature. For type with bounds (e.g
595 	 * type variables and wildcards) the plain signature is different
596 	 * than the full pretty signature.
597 	 *
598 	 * @return a plain pretty signature for this type
599 	 */
getPlainPrettySignature()600 	protected abstract String getPlainPrettySignature();
601 
602 	@Override
toString()603 	public String toString() {
604 		return getPrettySignature();
605 	}
606 }
607