1 /* 2 * Copyright 2019 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.turbine.processing; 18 19 import static com.google.common.collect.Iterables.getLast; 20 import static java.util.Objects.requireNonNull; 21 22 import com.google.common.base.Ascii; 23 import com.google.common.base.Joiner; 24 import com.google.common.base.Supplier; 25 import com.google.common.collect.ImmutableList; 26 import com.google.turbine.binder.bound.TypeBoundClass; 27 import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo; 28 import com.google.turbine.binder.sym.PackageSymbol; 29 import com.google.turbine.binder.sym.TyVarSymbol; 30 import com.google.turbine.model.TurbineConstantTypeKind; 31 import com.google.turbine.model.TurbineFlag; 32 import com.google.turbine.model.TurbineTyKind; 33 import com.google.turbine.type.AnnoInfo; 34 import com.google.turbine.type.Type; 35 import com.google.turbine.type.Type.ArrayTy; 36 import com.google.turbine.type.Type.ClassTy; 37 import com.google.turbine.type.Type.ErrorTy; 38 import com.google.turbine.type.Type.IntersectionTy; 39 import com.google.turbine.type.Type.MethodTy; 40 import com.google.turbine.type.Type.PrimTy; 41 import com.google.turbine.type.Type.TyVar; 42 import com.google.turbine.type.Type.WildTy; 43 import com.google.turbine.type.Type.WildTy.BoundKind; 44 import java.lang.annotation.Annotation; 45 import java.util.List; 46 import javax.lang.model.element.AnnotationMirror; 47 import javax.lang.model.element.Element; 48 import javax.lang.model.type.ArrayType; 49 import javax.lang.model.type.DeclaredType; 50 import javax.lang.model.type.ErrorType; 51 import javax.lang.model.type.ExecutableType; 52 import javax.lang.model.type.IntersectionType; 53 import javax.lang.model.type.NoType; 54 import javax.lang.model.type.NullType; 55 import javax.lang.model.type.PrimitiveType; 56 import javax.lang.model.type.TypeKind; 57 import javax.lang.model.type.TypeMirror; 58 import javax.lang.model.type.TypeVariable; 59 import javax.lang.model.type.TypeVisitor; 60 import javax.lang.model.type.WildcardType; 61 import org.jspecify.nullness.Nullable; 62 63 /** A {@link TypeMirror} implementation backed by a {@link Type}. */ 64 public abstract class TurbineTypeMirror implements TypeMirror { 65 66 protected final ModelFactory factory; 67 TurbineTypeMirror(ModelFactory factory)68 protected TurbineTypeMirror(ModelFactory factory) { 69 this.factory = requireNonNull(factory); 70 } 71 annos()72 protected abstract ImmutableList<AnnoInfo> annos(); 73 74 @Override getAnnotationMirrors()75 public final List<? extends AnnotationMirror> getAnnotationMirrors() { 76 ImmutableList.Builder<AnnotationMirror> result = ImmutableList.builder(); 77 for (AnnoInfo anno : annos()) { 78 result.add(TurbineAnnotationMirror.create(factory, anno)); 79 } 80 return result.build(); 81 } 82 83 @Override getAnnotation(Class<A> annotationType)84 public final <A extends Annotation> A getAnnotation(Class<A> annotationType) { 85 throw new AssertionError(); 86 } 87 88 @Override getAnnotationsByType(Class<A> annotationType)89 public final <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) { 90 throw new AssertionError(); 91 } 92 asTurbineType()93 public abstract Type asTurbineType(); 94 95 @Override toString()96 public String toString() { 97 return asTurbineType().toString(); 98 } 99 100 /** A {@link PrimitiveType} implementation backed by a {@link PrimTy}. */ 101 static class TurbinePrimitiveType extends TurbineTypeMirror implements PrimitiveType { 102 103 @Override toString()104 public String toString() { 105 return Ascii.toLowerCase(type.primkind().toString()); 106 } 107 108 @Override asTurbineType()109 public Type asTurbineType() { 110 return type; 111 } 112 113 public final PrimTy type; 114 TurbinePrimitiveType(ModelFactory factory, PrimTy type)115 TurbinePrimitiveType(ModelFactory factory, PrimTy type) { 116 super(factory); 117 if (type.primkind() == TurbineConstantTypeKind.STRING) { 118 throw new AssertionError(type); 119 } 120 this.type = type; 121 } 122 123 @Override getKind()124 public TypeKind getKind() { 125 switch (type.primkind()) { 126 case CHAR: 127 return TypeKind.CHAR; 128 case SHORT: 129 return TypeKind.SHORT; 130 case INT: 131 return TypeKind.INT; 132 case LONG: 133 return TypeKind.LONG; 134 case FLOAT: 135 return TypeKind.FLOAT; 136 case DOUBLE: 137 return TypeKind.DOUBLE; 138 case BOOLEAN: 139 return TypeKind.BOOLEAN; 140 case BYTE: 141 return TypeKind.BYTE; 142 case NULL: 143 return TypeKind.NULL; 144 case STRING: 145 } 146 throw new AssertionError(type.primkind()); 147 } 148 149 @Override accept(TypeVisitor<R, P> v, P p)150 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 151 return v.visitPrimitive(this, p); 152 } 153 154 @Override annos()155 protected ImmutableList<AnnoInfo> annos() { 156 return type.annos(); 157 } 158 } 159 160 /** A {@link DeclaredType} implementation backed by a {@link ClassTy}. */ 161 static class TurbineDeclaredType extends TurbineTypeMirror implements DeclaredType { 162 163 @Override hashCode()164 public int hashCode() { 165 return type.sym().hashCode(); 166 } 167 168 @Override equals(@ullable Object obj)169 public boolean equals(@Nullable Object obj) { 170 return obj instanceof TurbineDeclaredType && type.equals(((TurbineDeclaredType) obj).type); 171 } 172 173 @Override asTurbineType()174 public ClassTy asTurbineType() { 175 return type; 176 } 177 178 private final ClassTy type; 179 TurbineDeclaredType(ModelFactory factory, ClassTy type)180 TurbineDeclaredType(ModelFactory factory, ClassTy type) { 181 super(factory); 182 this.type = type; 183 } 184 185 @Override toString()186 public String toString() { 187 return type.toString(); 188 } 189 190 final Supplier<Element> element = 191 factory.memoize( 192 new Supplier<Element>() { 193 @Override 194 public Element get() { 195 return factory.typeElement(type.sym()); 196 } 197 }); 198 199 @Override asElement()200 public Element asElement() { 201 return element.get(); 202 } 203 204 final Supplier<TypeMirror> enclosing = 205 factory.memoize( 206 new Supplier<TypeMirror>() { 207 @Override 208 public TypeMirror get() { 209 TypeBoundClass info = factory.getSymbol(type.sym()); 210 if (info != null 211 && info.owner() != null 212 && ((info.access() & TurbineFlag.ACC_STATIC) == 0) 213 && info.kind() == TurbineTyKind.CLASS) { 214 if (type.classes().size() > 1) { 215 return factory.asTypeMirror( 216 ClassTy.create(type.classes().subList(0, type.classes().size() - 1))); 217 } 218 return factory.asTypeMirror(ClassTy.asNonParametricClassTy(info.owner())); 219 } 220 return factory.noType(); 221 } 222 }); 223 224 @Override getEnclosingType()225 public TypeMirror getEnclosingType() { 226 return enclosing.get(); 227 } 228 229 final Supplier<ImmutableList<TypeMirror>> typeArguments = 230 factory.memoize( 231 new Supplier<ImmutableList<TypeMirror>>() { 232 @Override 233 public ImmutableList<TypeMirror> get() { 234 return factory.asTypeMirrors(getLast(type.classes()).targs()); 235 } 236 }); 237 238 @Override getTypeArguments()239 public List<? extends TypeMirror> getTypeArguments() { 240 return typeArguments.get(); 241 } 242 243 @Override getKind()244 public TypeKind getKind() { 245 return TypeKind.DECLARED; 246 } 247 248 @Override accept(TypeVisitor<R, P> v, P p)249 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 250 return v.visitDeclared(this, p); 251 } 252 type()253 public ClassTy type() { 254 return type; 255 } 256 257 @Override annos()258 protected ImmutableList<AnnoInfo> annos() { 259 return getLast(type.classes()).annos(); 260 } 261 } 262 263 /** An {@link ArrayType} implementation backed by a {@link ArrayTy}. */ 264 static class TurbineArrayType extends TurbineTypeMirror implements ArrayType { 265 266 @Override asTurbineType()267 public Type asTurbineType() { 268 return type; 269 } 270 271 private final ArrayTy type; 272 TurbineArrayType(ModelFactory factory, ArrayTy type)273 TurbineArrayType(ModelFactory factory, ArrayTy type) { 274 super(factory); 275 this.type = type; 276 } 277 278 @Override getComponentType()279 public TypeMirror getComponentType() { 280 return factory.asTypeMirror(type.elementType()); 281 } 282 283 @Override getKind()284 public TypeKind getKind() { 285 return TypeKind.ARRAY; 286 } 287 288 @Override accept(TypeVisitor<R, P> v, P p)289 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 290 return v.visitArray(this, p); 291 } 292 293 @Override annos()294 protected ImmutableList<AnnoInfo> annos() { 295 return type.annos(); 296 } 297 } 298 299 /** An {@link ErrorType} implementation backed by a {@link ErrorTy}. */ 300 static class TurbineErrorType extends TurbineTypeMirror implements ErrorType { 301 302 private final ErrorTy type; 303 TurbineErrorType(ModelFactory factory, ErrorTy type)304 public TurbineErrorType(ModelFactory factory, ErrorTy type) { 305 super(factory); 306 this.type = type; 307 } 308 309 @Override getKind()310 public TypeKind getKind() { 311 return TypeKind.ERROR; 312 } 313 314 @Override accept(TypeVisitor<R, P> v, P p)315 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 316 return v.visitError(this, p); 317 } 318 319 @Override annos()320 protected ImmutableList<AnnoInfo> annos() { 321 return ImmutableList.of(); 322 } 323 324 @Override asTurbineType()325 public Type asTurbineType() { 326 return type; 327 } 328 329 @Override asElement()330 public Element asElement() { 331 return factory.noElement(type.name()); 332 } 333 334 @Override getEnclosingType()335 public TypeMirror getEnclosingType() { 336 return factory.noType(); 337 } 338 339 @Override getTypeArguments()340 public List<? extends TypeMirror> getTypeArguments() { 341 return ImmutableList.of(); 342 } 343 344 @Override toString()345 public String toString() { 346 return type.toString(); 347 } 348 } 349 350 /** A 'package type' implementation backed by a {@link PackageSymbol}. */ 351 static class TurbinePackageType extends TurbineTypeMirror implements NoType { 352 353 @Override asTurbineType()354 public Type asTurbineType() { 355 throw new UnsupportedOperationException(); 356 } 357 358 final PackageSymbol symbol; 359 TurbinePackageType(ModelFactory factory, PackageSymbol symbol)360 TurbinePackageType(ModelFactory factory, PackageSymbol symbol) { 361 super(factory); 362 this.symbol = symbol; 363 } 364 365 @Override getKind()366 public TypeKind getKind() { 367 return TypeKind.PACKAGE; 368 } 369 370 @Override accept(TypeVisitor<R, P> v, P p)371 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 372 return v.visitNoType(this, p); 373 } 374 375 @Override toString()376 public String toString() { 377 return symbol.toString(); 378 } 379 380 @Override equals(@ullable Object other)381 public boolean equals(@Nullable Object other) { 382 return other instanceof TurbinePackageType 383 && symbol.equals(((TurbinePackageType) other).symbol); 384 } 385 386 @Override hashCode()387 public int hashCode() { 388 return symbol.hashCode(); 389 } 390 391 @Override annos()392 protected ImmutableList<AnnoInfo> annos() { 393 return ImmutableList.of(); 394 } 395 } 396 397 /** The absence of a type, {@see javax.lang.model.util.Types#getNoType}. */ 398 static class TurbineNoType extends TurbineTypeMirror implements NoType { 399 400 @Override asTurbineType()401 public Type asTurbineType() { 402 return Type.NONE; 403 } 404 TurbineNoType(ModelFactory factory)405 TurbineNoType(ModelFactory factory) { 406 super(factory); 407 } 408 409 @Override getKind()410 public TypeKind getKind() { 411 return TypeKind.NONE; 412 } 413 414 @Override accept(TypeVisitor<R, P> v, P p)415 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 416 return v.visitNoType(this, p); 417 } 418 419 @Override toString()420 public String toString() { 421 return "none"; 422 } 423 424 @Override equals(@ullable Object other)425 public boolean equals(@Nullable Object other) { 426 return other instanceof TurbineNoType; 427 } 428 429 @Override hashCode()430 public int hashCode() { 431 return getKind().hashCode(); 432 } 433 434 @Override annos()435 protected ImmutableList<AnnoInfo> annos() { 436 return ImmutableList.of(); 437 } 438 } 439 440 /** A void type, {@see javax.lang.model.util.Types#getNoType}. */ 441 static class TurbineVoidType extends TurbineTypeMirror implements NoType { 442 443 @Override asTurbineType()444 public Type asTurbineType() { 445 return Type.VOID; 446 } 447 TurbineVoidType(ModelFactory factory)448 TurbineVoidType(ModelFactory factory) { 449 super(factory); 450 } 451 452 @Override getKind()453 public TypeKind getKind() { 454 return TypeKind.VOID; 455 } 456 457 @Override accept(TypeVisitor<R, P> v, P p)458 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 459 return v.visitNoType(this, p); 460 } 461 462 @Override annos()463 protected ImmutableList<AnnoInfo> annos() { 464 return ImmutableList.of(); 465 } 466 } 467 468 /** A {@link TypeVariable} implementation backed by a {@link TyVar}. */ 469 static class TurbineTypeVariable extends TurbineTypeMirror implements TypeVariable { 470 471 @Override hashCode()472 public int hashCode() { 473 return type.hashCode(); 474 } 475 476 @Override equals(@ullable Object obj)477 public boolean equals(@Nullable Object obj) { 478 return obj instanceof TurbineTypeVariable && type.equals(((TurbineTypeVariable) obj).type); 479 } 480 481 @Override asTurbineType()482 public Type asTurbineType() { 483 return type; 484 } 485 486 private final TyVar type; 487 488 private final Supplier<TyVarInfo> info = 489 factory.memoize( 490 new Supplier<TyVarInfo>() { 491 @Override 492 public TyVarInfo get() { 493 return factory.getTyVarInfo(type.sym()); 494 } 495 }); 496 info()497 private TyVarInfo info() { 498 return info.get(); 499 } 500 TurbineTypeVariable(ModelFactory factory, Type.TyVar type)501 TurbineTypeVariable(ModelFactory factory, Type.TyVar type) { 502 super(factory); 503 this.type = type; 504 } 505 506 @Override getKind()507 public TypeKind getKind() { 508 return TypeKind.TYPEVAR; 509 } 510 511 @Override accept(TypeVisitor<R, P> v, P p)512 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 513 return v.visitTypeVariable(this, p); 514 } 515 516 @Override asElement()517 public Element asElement() { 518 return factory.typeParameterElement(type.sym()); 519 } 520 521 @Override getUpperBound()522 public TypeMirror getUpperBound() { 523 return factory.asTypeMirror(info().upperBound()); 524 } 525 526 @Override getLowerBound()527 public TypeMirror getLowerBound() { 528 return info().lowerBound() != null 529 ? factory.asTypeMirror(info().lowerBound()) 530 : factory.noType(); 531 } 532 533 @Override toString()534 public String toString() { 535 return type.toString(); 536 } 537 538 @Override annos()539 protected ImmutableList<AnnoInfo> annos() { 540 return type.annos(); 541 } 542 } 543 544 /** A {@link WildcardType} implementation backed by a {@link WildTy}. */ 545 static class TurbineWildcardType extends TurbineTypeMirror implements WildcardType { 546 547 @Override asTurbineType()548 public Type asTurbineType() { 549 return type; 550 } 551 552 private final WildTy type; 553 TurbineWildcardType(ModelFactory factory, WildTy type)554 public TurbineWildcardType(ModelFactory factory, WildTy type) { 555 super(factory); 556 this.type = type; 557 } 558 559 @Override getKind()560 public TypeKind getKind() { 561 return TypeKind.WILDCARD; 562 } 563 564 @Override accept(TypeVisitor<R, P> v, P p)565 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 566 return v.visitWildcard(this, p); 567 } 568 569 @Override equals(@ullable Object obj)570 public boolean equals(@Nullable Object obj) { 571 return obj instanceof TurbineWildcardType && type.equals(((TurbineWildcardType) obj).type); 572 } 573 574 @Override hashCode()575 public int hashCode() { 576 return type.hashCode(); 577 } 578 579 @Override getExtendsBound()580 public TypeMirror getExtendsBound() { 581 return type.boundKind() == BoundKind.UPPER ? factory.asTypeMirror(type.bound()) : null; 582 } 583 584 @Override getSuperBound()585 public TypeMirror getSuperBound() { 586 return type.boundKind() == BoundKind.LOWER ? factory.asTypeMirror(type.bound()) : null; 587 } 588 589 @Override annos()590 protected ImmutableList<AnnoInfo> annos() { 591 return type.annotations(); 592 } 593 } 594 595 /** A {@link IntersectionType} implementation backed by a {@link IntersectionTy}. */ 596 static class TurbineIntersectionType extends TurbineTypeMirror implements IntersectionType { 597 598 @Override asTurbineType()599 public Type asTurbineType() { 600 return type; 601 } 602 603 private final IntersectionTy type; 604 TurbineIntersectionType(ModelFactory factory, IntersectionTy type)605 TurbineIntersectionType(ModelFactory factory, IntersectionTy type) { 606 super(factory); 607 this.type = type; 608 } 609 610 @Override equals(@ullable Object obj)611 public boolean equals(@Nullable Object obj) { 612 return obj instanceof TurbineIntersectionType 613 && type.equals(((TurbineIntersectionType) obj).type); 614 } 615 616 @Override hashCode()617 public int hashCode() { 618 return type.hashCode(); 619 } 620 621 @Override getKind()622 public TypeKind getKind() { 623 return TypeKind.INTERSECTION; 624 } 625 626 @Override accept(TypeVisitor<R, P> v, P p)627 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 628 return v.visitIntersection(this, p); 629 } 630 631 final Supplier<ImmutableList<TypeMirror>> bounds = 632 factory.memoize( 633 new Supplier<ImmutableList<TypeMirror>>() { 634 @Override 635 public ImmutableList<TypeMirror> get() { 636 return factory.asTypeMirrors(TurbineTypes.getBounds(factory, type)); 637 } 638 }); 639 640 @Override getBounds()641 public List<? extends TypeMirror> getBounds() { 642 return bounds.get(); 643 } 644 645 @Override toString()646 public String toString() { 647 return Joiner.on('&').join(getBounds()); 648 } 649 650 @Override annos()651 protected ImmutableList<AnnoInfo> annos() { 652 return ImmutableList.of(); 653 } 654 } 655 656 /** A {@link NullType} implementation. */ 657 public static class TurbineNullType extends TurbineTypeMirror implements NullType { 658 659 @Override asTurbineType()660 public Type asTurbineType() { 661 return Type.PrimTy.create(TurbineConstantTypeKind.NULL, ImmutableList.of()); 662 } 663 TurbineNullType(ModelFactory factory)664 public TurbineNullType(ModelFactory factory) { 665 super(factory); 666 } 667 668 @Override annos()669 protected ImmutableList<AnnoInfo> annos() { 670 return ImmutableList.of(); 671 } 672 673 @Override equals(@ullable Object obj)674 public boolean equals(@Nullable Object obj) { 675 return obj instanceof NullType; 676 } 677 678 @Override hashCode()679 public int hashCode() { 680 return super.hashCode(); 681 } 682 683 @Override getKind()684 public TypeKind getKind() { 685 return TypeKind.NULL; 686 } 687 688 @Override accept(TypeVisitor<R, P> v, P p)689 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 690 return v.visitNull(this, p); 691 } 692 } 693 694 /** An {@link ExecutableType} implementation backed by a {@link MethodTy}. */ 695 public static class TurbineExecutableType extends TurbineTypeMirror implements ExecutableType { 696 697 @Override toString()698 public String toString() { 699 return type.toString(); 700 } 701 702 @Override asTurbineType()703 public MethodTy asTurbineType() { 704 return type; 705 } 706 707 public final MethodTy type; 708 TurbineExecutableType(ModelFactory factory, MethodTy type)709 TurbineExecutableType(ModelFactory factory, MethodTy type) { 710 super(factory); 711 this.type = type; 712 } 713 714 @Override equals(@ullable Object obj)715 public boolean equals(@Nullable Object obj) { 716 return obj instanceof TurbineExecutableType 717 && type.equals(((TurbineExecutableType) obj).type); 718 } 719 720 @Override hashCode()721 public int hashCode() { 722 return type.hashCode(); 723 } 724 725 @Override getTypeVariables()726 public List<? extends TypeVariable> getTypeVariables() { 727 ImmutableList.Builder<TypeVariable> result = ImmutableList.builder(); 728 for (TyVarSymbol tyVar : type.tyParams()) { 729 result.add((TypeVariable) factory.asTypeMirror(TyVar.create(tyVar, ImmutableList.of()))); 730 } 731 return result.build(); 732 } 733 734 @Override getReturnType()735 public TypeMirror getReturnType() { 736 return factory.asTypeMirror(type.returnType()); 737 } 738 739 @Override getParameterTypes()740 public List<? extends TypeMirror> getParameterTypes() { 741 return factory.asTypeMirrors(type.parameters()); 742 } 743 744 @Override getReceiverType()745 public TypeMirror getReceiverType() { 746 return type.receiverType() != null 747 ? factory.asTypeMirror(type.receiverType()) 748 : factory.noType(); 749 } 750 751 @Override getThrownTypes()752 public List<? extends TypeMirror> getThrownTypes() { 753 return factory.asTypeMirrors(type.thrown()); 754 } 755 756 @Override getKind()757 public TypeKind getKind() { 758 return TypeKind.EXECUTABLE; 759 } 760 761 @Override accept(TypeVisitor<R, P> v, P p)762 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 763 return v.visitExecutable(this, p); 764 } 765 766 @Override annos()767 protected ImmutableList<AnnoInfo> annos() { 768 return ImmutableList.of(); 769 } 770 } 771 } 772