1 /* 2 * Copyright 2016 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.lower; 18 19 import static com.google.turbine.binder.DisambiguateTypeAnnotations.groupRepeated; 20 21 import com.google.common.base.Function; 22 import com.google.common.collect.ImmutableList; 23 import com.google.common.collect.ImmutableList.Builder; 24 import com.google.common.collect.ImmutableMap; 25 import com.google.common.collect.ImmutableSet; 26 import com.google.turbine.binder.bound.AnnotationValue; 27 import com.google.turbine.binder.bound.ClassValue; 28 import com.google.turbine.binder.bound.EnumConstantValue; 29 import com.google.turbine.binder.bound.SourceTypeBoundClass; 30 import com.google.turbine.binder.bound.TypeBoundClass; 31 import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; 32 import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; 33 import com.google.turbine.binder.bound.TypeBoundClass.ParamInfo; 34 import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo; 35 import com.google.turbine.binder.bytecode.BytecodeBoundClass; 36 import com.google.turbine.binder.env.CompoundEnv; 37 import com.google.turbine.binder.env.Env; 38 import com.google.turbine.binder.env.SimpleEnv; 39 import com.google.turbine.binder.sym.ClassSymbol; 40 import com.google.turbine.binder.sym.Symbol; 41 import com.google.turbine.binder.sym.TyVarSymbol; 42 import com.google.turbine.bytecode.ClassFile; 43 import com.google.turbine.bytecode.ClassFile.AnnotationInfo; 44 import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue; 45 import com.google.turbine.bytecode.ClassFile.MethodInfo.ParameterInfo; 46 import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo; 47 import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo.Target; 48 import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo.TargetType; 49 import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo.ThrowsTarget; 50 import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo.TypePath; 51 import com.google.turbine.bytecode.ClassWriter; 52 import com.google.turbine.bytecode.sig.Sig; 53 import com.google.turbine.bytecode.sig.Sig.MethodSig; 54 import com.google.turbine.bytecode.sig.Sig.TySig; 55 import com.google.turbine.bytecode.sig.SigWriter; 56 import com.google.turbine.model.Const; 57 import com.google.turbine.model.TurbineFlag; 58 import com.google.turbine.model.TurbineVisibility; 59 import com.google.turbine.type.AnnoInfo; 60 import com.google.turbine.type.Type; 61 import com.google.turbine.type.Type.ArrayTy; 62 import com.google.turbine.type.Type.ClassTy; 63 import com.google.turbine.type.Type.ClassTy.SimpleClassTy; 64 import com.google.turbine.type.Type.TyVar; 65 import com.google.turbine.type.Type.WildTy; 66 import com.google.turbine.types.Erasure; 67 import java.lang.annotation.RetentionPolicy; 68 import java.util.ArrayDeque; 69 import java.util.ArrayList; 70 import java.util.Collections; 71 import java.util.Deque; 72 import java.util.LinkedHashSet; 73 import java.util.List; 74 import java.util.Map; 75 import java.util.Set; 76 import javax.annotation.Nullable; 77 78 /** Lowering from bound classes to bytecode. */ 79 public class Lower { 80 81 /** The lowered compilation output. */ 82 public static class Lowered { 83 private final ImmutableMap<String, byte[]> bytes; 84 private final ImmutableSet<ClassSymbol> symbols; 85 86 public Lowered(ImmutableMap<String, byte[]> bytes, ImmutableSet<ClassSymbol> symbols) { 87 this.bytes = bytes; 88 this.symbols = symbols; 89 } 90 91 /** Returns the bytecode for classes in the compilation. */ 92 public ImmutableMap<String, byte[]> bytes() { 93 return bytes; 94 } 95 96 /** Returns the set of all referenced symbols in the compilation. */ 97 public ImmutableSet<ClassSymbol> symbols() { 98 return symbols; 99 } 100 } 101 102 /** Lowers all given classes to bytecode. */ 103 public static Lowered lowerAll( 104 ImmutableMap<ClassSymbol, SourceTypeBoundClass> units, 105 CompoundEnv<ClassSymbol, BytecodeBoundClass> classpath) { 106 CompoundEnv<ClassSymbol, TypeBoundClass> env = 107 CompoundEnv.<ClassSymbol, TypeBoundClass>of(classpath).append(new SimpleEnv<>(units)); 108 ImmutableMap.Builder<String, byte[]> result = ImmutableMap.builder(); 109 Set<ClassSymbol> symbols = new LinkedHashSet<>(); 110 for (ClassSymbol sym : units.keySet()) { 111 result.put(sym.binaryName(), lower(units.get(sym), env, sym, symbols)); 112 } 113 return new Lowered(result.build(), ImmutableSet.copyOf(symbols)); 114 } 115 116 /** Lowers a class to bytecode. */ 117 public static byte[] lower( 118 SourceTypeBoundClass info, 119 Env<ClassSymbol, TypeBoundClass> env, 120 ClassSymbol sym, 121 Set<ClassSymbol> symbols) { 122 return new Lower(env).lower(info, sym, symbols); 123 } 124 125 private final LowerSignature sig = new LowerSignature(); 126 private final Env<ClassSymbol, TypeBoundClass> env; 127 128 public Lower(Env<ClassSymbol, TypeBoundClass> env) { 129 this.env = env; 130 } 131 132 private byte[] lower(SourceTypeBoundClass info, ClassSymbol sym, Set<ClassSymbol> symbols) { 133 int access = classAccess(info); 134 String name = sig.descriptor(sym); 135 String signature = sig.classSignature(info); 136 String superName = info.superclass() != null ? sig.descriptor(info.superclass()) : null; 137 List<String> interfaces = new ArrayList<>(); 138 for (ClassSymbol i : info.interfaces()) { 139 interfaces.add(sig.descriptor(i)); 140 } 141 142 List<ClassFile.MethodInfo> methods = new ArrayList<>(); 143 for (MethodInfo m : info.methods()) { 144 if (TurbineVisibility.fromAccess(m.access()) == TurbineVisibility.PRIVATE) { 145 // TODO(cushon): drop private members earlier? 146 continue; 147 } 148 methods.add(lowerMethod(m, sym)); 149 } 150 151 ImmutableList.Builder<ClassFile.FieldInfo> fields = ImmutableList.builder(); 152 for (FieldInfo f : info.fields()) { 153 if ((f.access() & TurbineFlag.ACC_PRIVATE) == TurbineFlag.ACC_PRIVATE) { 154 // TODO(cushon): drop private members earlier? 155 continue; 156 } 157 fields.add(lowerField(f)); 158 } 159 160 ImmutableList<AnnotationInfo> annotations = lowerAnnotations(info.annotations()); 161 162 ImmutableList<ClassFile.InnerClass> inners = collectInnerClasses(sym, info); 163 164 ImmutableList<TypeAnnotationInfo> typeAnnotations = classTypeAnnotations(info); 165 166 ClassFile classfile = 167 new ClassFile( 168 access, 169 name, 170 signature, 171 superName, 172 interfaces, 173 methods, 174 fields.build(), 175 annotations, 176 inners, 177 typeAnnotations); 178 179 symbols.addAll(sig.classes); 180 181 return ClassWriter.writeClass(classfile); 182 } 183 184 private ClassFile.MethodInfo lowerMethod(final MethodInfo m, final ClassSymbol sym) { 185 int access = m.access(); 186 Function<TyVarSymbol, TyVarInfo> tenv = new TyVarEnv(m.tyParams()); 187 String name = m.name(); 188 String desc = methodDescriptor(m, tenv); 189 String signature = sig.methodSignature(env, m, sym); 190 ImmutableList.Builder<String> exceptions = ImmutableList.builder(); 191 if (!m.exceptions().isEmpty()) { 192 for (Type e : m.exceptions()) { 193 exceptions.add(sig.descriptor(((ClassTy) Erasure.erase(e, tenv)).sym())); 194 } 195 } 196 197 ElementValue defaultValue = m.defaultValue() != null ? annotationValue(m.defaultValue()) : null; 198 199 ImmutableList<AnnotationInfo> annotations = lowerAnnotations(m.annotations()); 200 201 ImmutableList<ImmutableList<AnnotationInfo>> paramAnnotations = parameterAnnotations(m); 202 203 ImmutableList<TypeAnnotationInfo> typeAnnotations = methodTypeAnnotations(m); 204 205 ImmutableList<ClassFile.MethodInfo.ParameterInfo> parameters = methodParameters(m); 206 207 return new ClassFile.MethodInfo( 208 access, 209 name, 210 desc, 211 signature, 212 exceptions.build(), 213 defaultValue, 214 annotations, 215 paramAnnotations, 216 typeAnnotations, 217 parameters); 218 } 219 220 private ImmutableList<ParameterInfo> methodParameters(MethodInfo m) { 221 ImmutableList.Builder<ParameterInfo> result = ImmutableList.builder(); 222 for (ParamInfo p : m.parameters()) { 223 result.add(new ParameterInfo(p.name(), p.access() & PARAMETER_ACCESS_MASK)); 224 } 225 return result.build(); 226 } 227 228 private static final int PARAMETER_ACCESS_MASK = 229 TurbineFlag.ACC_MANDATED | TurbineFlag.ACC_FINAL | TurbineFlag.ACC_SYNTHETIC; 230 231 private ImmutableList<ImmutableList<AnnotationInfo>> parameterAnnotations(MethodInfo m) { 232 ImmutableList.Builder<ImmutableList<AnnotationInfo>> annotations = ImmutableList.builder(); 233 for (ParamInfo parameter : m.parameters()) { 234 if (parameter.synthetic()) { 235 continue; 236 } 237 if (parameter.annotations().isEmpty()) { 238 annotations.add(ImmutableList.of()); 239 continue; 240 } 241 ImmutableList.Builder<AnnotationInfo> parameterAnnotations = ImmutableList.builder(); 242 for (AnnoInfo annotation : parameter.annotations()) { 243 Boolean visible = isVisible(annotation.sym()); 244 if (visible == null) { 245 continue; 246 } 247 String desc = sig.objectType(annotation.sym()); 248 parameterAnnotations.add( 249 new AnnotationInfo(desc, visible, annotationValues(annotation.values()))); 250 } 251 annotations.add(parameterAnnotations.build()); 252 } 253 return annotations.build(); 254 } 255 256 private String methodDescriptor(MethodInfo m, Function<TyVarSymbol, TyVarInfo> tenv) { 257 ImmutableList<Sig.TyParamSig> typarams = ImmutableList.of(); 258 ImmutableList.Builder<TySig> fparams = ImmutableList.builder(); 259 for (ParamInfo t : m.parameters()) { 260 fparams.add(sig.signature(Erasure.erase(t.type(), tenv))); 261 } 262 TySig result = sig.signature(Erasure.erase(m.returnType(), tenv)); 263 ImmutableList<TySig> excns = ImmutableList.of(); 264 return SigWriter.method(new MethodSig(typarams, fparams.build(), result, excns)); 265 } 266 267 private ClassFile.FieldInfo lowerField(FieldInfo f) { 268 final String name = f.name(); 269 Function<TyVarSymbol, TyVarInfo> tenv = new TyVarEnv(Collections.emptyMap()); 270 String desc = SigWriter.type(sig.signature(Erasure.erase(f.type(), tenv))); 271 String signature = sig.fieldSignature(f.type()); 272 273 ImmutableList<AnnotationInfo> annotations = lowerAnnotations(f.annotations()); 274 275 ImmutableList.Builder<TypeAnnotationInfo> typeAnnotations = ImmutableList.builder(); 276 lowerTypeAnnotations( 277 typeAnnotations, f.type(), TargetType.FIELD, TypeAnnotationInfo.EMPTY_TARGET); 278 279 return new ClassFile.FieldInfo( 280 f.access(), name, desc, signature, f.value(), annotations, typeAnnotations.build()); 281 } 282 283 /** Creates inner class attributes for all referenced inner classes. */ 284 private ImmutableList<ClassFile.InnerClass> collectInnerClasses( 285 ClassSymbol origin, SourceTypeBoundClass info) { 286 Set<ClassSymbol> all = new LinkedHashSet<>(); 287 addEnclosing(env, all, origin); 288 for (ClassSymbol sym : info.children().values()) { 289 addEnclosing(env, all, sym); 290 } 291 for (ClassSymbol sym : sig.classes) { 292 addEnclosing(env, all, sym); 293 } 294 ImmutableList.Builder<ClassFile.InnerClass> inners = ImmutableList.builder(); 295 for (ClassSymbol innerSym : all) { 296 inners.add(innerClass(env, innerSym)); 297 } 298 return inners.build(); 299 } 300 301 /** 302 * Record all enclosing declarations of a symbol, to make sure the necessary InnerClass attributes 303 * are added. 304 * 305 * <p>javac expects InnerClass attributes for enclosing classes to appear before their member 306 * classes' entries. 307 */ 308 private void addEnclosing( 309 Env<ClassSymbol, TypeBoundClass> env, Set<ClassSymbol> all, ClassSymbol sym) { 310 ClassSymbol owner = env.get(sym).owner(); 311 if (owner != null) { 312 addEnclosing(env, all, owner); 313 all.add(sym); 314 } 315 } 316 317 /** 318 * Creates an inner class attribute, given an inner class that was referenced somewhere in the 319 * class. 320 */ 321 private ClassFile.InnerClass innerClass( 322 Env<ClassSymbol, TypeBoundClass> env, ClassSymbol innerSym) { 323 TypeBoundClass inner = env.get(innerSym); 324 325 String innerName = innerSym.binaryName().substring(inner.owner().binaryName().length() + 1); 326 327 int access = inner.access(); 328 access &= ~(TurbineFlag.ACC_SUPER | TurbineFlag.ACC_STRICT); 329 330 return new ClassFile.InnerClass( 331 innerSym.binaryName(), inner.owner().binaryName(), innerName, access); 332 } 333 334 /** Updates visibility, and unsets access bits that can only be set in InnerClass. */ 335 private int classAccess(SourceTypeBoundClass info) { 336 int access = info.access(); 337 access &= ~(TurbineFlag.ACC_STATIC | TurbineFlag.ACC_PRIVATE | TurbineFlag.ACC_STRICT); 338 if ((access & TurbineFlag.ACC_PROTECTED) != 0) { 339 access &= ~TurbineFlag.ACC_PROTECTED; 340 access |= TurbineFlag.ACC_PUBLIC; 341 } 342 return access; 343 } 344 345 /** 346 * Looks up {@link TyVarInfo}s. 347 * 348 * <p>We could generalize {@link com.google.turbine.binder.lookup.Scope} instead, but this isn't 349 * needed anywhere else. 350 */ 351 class TyVarEnv implements Function<TyVarSymbol, TyVarInfo> { 352 353 private final Map<TyVarSymbol, TyVarInfo> tyParams; 354 355 /** @param tyParams the initial lookup scope, e.g. a method's formal type parameters. */ 356 public TyVarEnv(Map<TyVarSymbol, TyVarInfo> tyParams) { 357 this.tyParams = tyParams; 358 } 359 360 @Override 361 public TyVarInfo apply(TyVarSymbol sym) { 362 TyVarInfo result = tyParams.get(sym); 363 if (result != null) { 364 return result; 365 } 366 // type variables can only be declared by methods and classes, 367 // and we've already handled methods 368 Symbol ownerSym = sym.owner(); 369 if (ownerSym.symKind() != Symbol.Kind.CLASS) { 370 throw new AssertionError(sym); 371 } 372 // anything that lexically encloses the class being lowered 373 // must be in the same compilation unit, so we have source 374 // information for it 375 TypeBoundClass owner = env.get((ClassSymbol) ownerSym); 376 return owner.typeParameterTypes().get(sym); 377 } 378 } 379 380 private ImmutableList<AnnotationInfo> lowerAnnotations(ImmutableList<AnnoInfo> annotations) { 381 ImmutableList.Builder<AnnotationInfo> lowered = ImmutableList.builder(); 382 for (AnnoInfo annotation : annotations) { 383 AnnotationInfo anno = lowerAnnotation(annotation); 384 if (anno == null) { 385 continue; 386 } 387 lowered.add(anno); 388 } 389 return lowered.build(); 390 } 391 392 private AnnotationInfo lowerAnnotation(AnnoInfo annotation) { 393 Boolean visible = isVisible(annotation.sym()); 394 if (visible == null) { 395 return null; 396 } 397 return new AnnotationInfo( 398 sig.objectType(annotation.sym()), visible, annotationValues(annotation.values())); 399 } 400 401 /** 402 * Returns true if the annotation is visible at runtime, false if it is not visible at runtime, 403 * and {@code null} if it should not be retained in bytecode. 404 */ 405 @Nullable 406 private Boolean isVisible(ClassSymbol sym) { 407 RetentionPolicy retention = env.get(sym).annotationMetadata().retention(); 408 switch (retention) { 409 case CLASS: 410 return false; 411 case RUNTIME: 412 return true; 413 case SOURCE: 414 return null; 415 default: 416 throw new AssertionError(retention); 417 } 418 } 419 420 private ImmutableMap<String, ElementValue> annotationValues(ImmutableMap<String, Const> values) { 421 ImmutableMap.Builder<String, ElementValue> result = ImmutableMap.builder(); 422 for (Map.Entry<String, Const> entry : values.entrySet()) { 423 result.put(entry.getKey(), annotationValue(entry.getValue())); 424 } 425 return result.build(); 426 } 427 428 private ElementValue annotationValue(Const value) { 429 switch (value.kind()) { 430 case CLASS_LITERAL: 431 { 432 ClassValue classValue = (ClassValue) value; 433 return new ElementValue.ConstClassValue(SigWriter.type(sig.signature(classValue.type()))); 434 } 435 case ENUM_CONSTANT: 436 { 437 EnumConstantValue enumValue = (EnumConstantValue) value; 438 return new ElementValue.EnumConstValue( 439 sig.objectType(enumValue.sym().owner()), enumValue.sym().name()); 440 } 441 case ARRAY: 442 { 443 Const.ArrayInitValue arrayValue = (Const.ArrayInitValue) value; 444 List<ElementValue> values = new ArrayList<>(); 445 for (Const element : arrayValue.elements()) { 446 values.add(annotationValue(element)); 447 } 448 return new ElementValue.ArrayValue(values); 449 } 450 case ANNOTATION: 451 { 452 AnnotationValue annotationValue = (AnnotationValue) value; 453 Boolean visible = isVisible(annotationValue.sym()); 454 if (visible == null) { 455 visible = true; 456 } 457 return new ElementValue.AnnotationValue( 458 new AnnotationInfo( 459 sig.objectType(annotationValue.sym()), 460 visible, 461 annotationValues(annotationValue.values()))); 462 } 463 case PRIMITIVE: 464 return new ElementValue.ConstValue((Const.Value) value); 465 default: 466 throw new AssertionError(value.kind()); 467 } 468 } 469 470 /** Lower type annotations in a class declaration's signature. */ 471 private ImmutableList<TypeAnnotationInfo> classTypeAnnotations(SourceTypeBoundClass info) { 472 ImmutableList.Builder<TypeAnnotationInfo> result = ImmutableList.builder(); 473 { 474 if (info.superClassType() != null) { 475 lowerTypeAnnotations( 476 result, 477 info.superClassType(), 478 TargetType.SUPERTYPE, 479 new TypeAnnotationInfo.SuperTypeTarget(-1)); 480 } 481 int idx = 0; 482 for (Type i : info.interfaceTypes()) { 483 lowerTypeAnnotations( 484 result, i, TargetType.SUPERTYPE, new TypeAnnotationInfo.SuperTypeTarget(idx++)); 485 } 486 } 487 typeParameterAnnotations( 488 result, 489 info.typeParameterTypes().values(), 490 TargetType.CLASS_TYPE_PARAMETER, 491 TargetType.CLASS_TYPE_PARAMETER_BOUND); 492 return result.build(); 493 } 494 495 /** Lower type annotations in a method declaration's signature. */ 496 private ImmutableList<TypeAnnotationInfo> methodTypeAnnotations(MethodInfo m) { 497 ImmutableList.Builder<TypeAnnotationInfo> result = ImmutableList.builder(); 498 499 typeParameterAnnotations( 500 result, 501 m.tyParams().values(), 502 TargetType.METHOD_TYPE_PARAMETER, 503 TargetType.METHOD_TYPE_PARAMETER_BOUND); 504 505 { 506 int idx = 0; 507 for (Type e : m.exceptions()) { 508 lowerTypeAnnotations(result, e, TargetType.METHOD_THROWS, new ThrowsTarget(idx++)); 509 } 510 } 511 512 if (m.receiver() != null) { 513 lowerTypeAnnotations( 514 result, 515 m.receiver().type(), 516 TargetType.METHOD_RECEIVER_PARAMETER, 517 TypeAnnotationInfo.EMPTY_TARGET); 518 } 519 520 lowerTypeAnnotations( 521 result, m.returnType(), TargetType.METHOD_RETURN, TypeAnnotationInfo.EMPTY_TARGET); 522 523 { 524 int idx = 0; 525 for (ParamInfo p : m.parameters()) { 526 if (p.synthetic()) { 527 continue; 528 } 529 lowerTypeAnnotations( 530 result, 531 p.type(), 532 TargetType.METHOD_FORMAL_PARAMETER, 533 new TypeAnnotationInfo.FormalParameterTarget(idx++)); 534 } 535 } 536 537 return result.build(); 538 } 539 540 /** 541 * Lower type annotations on class or method type parameters, either on the parameters themselves 542 * or on bounds. 543 */ 544 private void typeParameterAnnotations( 545 Builder<TypeAnnotationInfo> result, 546 Iterable<TyVarInfo> typeParameters, 547 TargetType targetType, 548 TargetType boundTargetType) { 549 int typeParameterIndex = 0; 550 for (TyVarInfo p : typeParameters) { 551 for (AnnoInfo anno : groupRepeated(env, p.annotations())) { 552 AnnotationInfo info = lowerAnnotation(anno); 553 if (info == null) { 554 continue; 555 } 556 result.add( 557 new TypeAnnotationInfo( 558 targetType, 559 new TypeAnnotationInfo.TypeParameterTarget(typeParameterIndex), 560 TypePath.root(), 561 info)); 562 } 563 if (p.superClassBound() != null) { 564 lowerTypeAnnotations( 565 result, 566 p.superClassBound(), 567 boundTargetType, 568 new TypeAnnotationInfo.TypeParameterBoundTarget(typeParameterIndex, 0)); 569 } 570 int boundIndex = 1; // super class bound index is always 0; interface bounds start at 1 571 for (Type i : p.interfaceBounds()) { 572 lowerTypeAnnotations( 573 result, 574 i, 575 boundTargetType, 576 new TypeAnnotationInfo.TypeParameterBoundTarget(typeParameterIndex, boundIndex++)); 577 } 578 typeParameterIndex++; 579 } 580 } 581 582 private void lowerTypeAnnotations( 583 Builder<TypeAnnotationInfo> result, Type type, TargetType targetType, Target target) { 584 new LowerTypeAnnotations(result, targetType, target) 585 .lowerTypeAnnotations(type, TypePath.root()); 586 } 587 588 class LowerTypeAnnotations { 589 private final ImmutableList.Builder<TypeAnnotationInfo> result; 590 private final TargetType targetType; 591 private final Target target; 592 593 public LowerTypeAnnotations( 594 Builder<TypeAnnotationInfo> result, TargetType targetType, Target target) { 595 this.result = result; 596 this.targetType = targetType; 597 this.target = target; 598 } 599 600 /** 601 * Lower all type annotations present in a type. 602 * 603 * <p>Recursively descends into nested types, and accumulates a type path structure to locate 604 * the annotation in the signature. 605 */ 606 private void lowerTypeAnnotations(Type type, TypePath path) { 607 switch (type.tyKind()) { 608 case TY_VAR: 609 lowerTypeAnnotations(((TyVar) type).annos(), path); 610 break; 611 case CLASS_TY: 612 lowerClassTypeTypeAnnotations((ClassTy) type, path); 613 break; 614 case ARRAY_TY: 615 lowerArrayTypeAnnotations(type, path); 616 break; 617 case WILD_TY: 618 lowerWildTyTypeAnnotations((WildTy) type, path); 619 break; 620 case PRIM_TY: 621 lowerTypeAnnotations(((Type.PrimTy) type).annos(), path); 622 break; 623 case VOID_TY: 624 break; 625 default: 626 throw new AssertionError(type.tyKind()); 627 } 628 } 629 630 /** Lower a list of type annotations. */ 631 private void lowerTypeAnnotations(ImmutableList<AnnoInfo> annos, TypePath path) { 632 for (AnnoInfo anno : groupRepeated(env, annos)) { 633 AnnotationInfo info = lowerAnnotation(anno); 634 if (info == null) { 635 continue; 636 } 637 result.add(new TypeAnnotationInfo(targetType, target, path, info)); 638 } 639 } 640 641 private void lowerWildTyTypeAnnotations(WildTy type, TypePath path) { 642 switch (type.boundKind()) { 643 case NONE: 644 lowerTypeAnnotations(type.annotations(), path); 645 break; 646 case UPPER: 647 case LOWER: 648 lowerTypeAnnotations(type.annotations(), path); 649 lowerTypeAnnotations(type.bound(), path.wild()); 650 break; 651 default: 652 throw new AssertionError(type.boundKind()); 653 } 654 } 655 656 private void lowerArrayTypeAnnotations(Type type, TypePath path) { 657 Type base = type; 658 Deque<ArrayTy> flat = new ArrayDeque<>(); 659 while (base instanceof ArrayTy) { 660 ArrayTy arrayTy = (ArrayTy) base; 661 flat.addFirst(arrayTy); 662 base = arrayTy.elementType(); 663 } 664 for (ArrayTy arrayTy : flat) { 665 lowerTypeAnnotations(arrayTy.annos(), path); 666 path = path.array(); 667 } 668 lowerTypeAnnotations(base, path); 669 } 670 671 private void lowerClassTypeTypeAnnotations(ClassTy type, TypePath path) { 672 for (SimpleClassTy simple : type.classes) { 673 lowerTypeAnnotations(simple.annos(), path); 674 int idx = 0; 675 for (Type a : simple.targs()) { 676 lowerTypeAnnotations(a, path.typeArgument(idx++)); 677 } 678 path = path.nested(); 679 } 680 } 681 } 682 } 683