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<this>= List<rhs></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