1 /* <lambda>null2 * Copyright (C) 2017 The Android Open Source Project 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.android.tools.metalava.model 18 19 import com.android.SdkConstants 20 import com.android.tools.metalava.ApiAnalyzer 21 import com.android.tools.metalava.JAVA_LANG_ANNOTATION 22 import com.android.tools.metalava.JAVA_LANG_ENUM 23 import com.android.tools.metalava.JAVA_LANG_OBJECT 24 import com.android.tools.metalava.model.visitors.ApiVisitor 25 import com.android.tools.metalava.model.visitors.ItemVisitor 26 import com.android.tools.metalava.model.visitors.TypeVisitor 27 import com.google.common.base.Splitter 28 import java.util.ArrayList 29 import java.util.LinkedHashSet 30 import java.util.function.Predicate 31 32 /** 33 * Represents a {@link https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html Class} 34 * 35 * If you need to model array dimensions or resolved type parameters, see {@link com.android.tools.metalava.model.TypeItem} instead 36 */ 37 interface ClassItem : Item { 38 /** The simple name of a class. In class foo.bar.Outer.Inner, the simple name is "Inner" */ 39 fun simpleName(): String 40 41 /** The full name of a class. In class foo.bar.Outer.Inner, the full name is "Outer.Inner" */ 42 fun fullName(): String 43 44 /** The qualified name of a class. In class foo.bar.Outer.Inner, the qualified name is the whole thing. */ 45 fun qualifiedName(): String 46 47 /** Is the class explicitly defined in the source file? */ 48 fun isDefined(): Boolean 49 50 /** Is this an innerclass? */ 51 fun isInnerClass(): Boolean = containingClass() != null 52 53 /** Is this a top level class? */ 54 fun isTopLevelClass(): Boolean = containingClass() == null 55 56 /** This [ClassItem] and all of its inner classes, recursively */ 57 fun allClasses(): Sequence<ClassItem> { 58 return sequenceOf(this).plus(innerClasses().asSequence().flatMap { it.allClasses() }) 59 } 60 61 override fun parent(): Item? = containingClass() ?: containingPackage() 62 63 /** 64 * The qualified name where inner classes use $ as a separator. 65 * In class foo.bar.Outer.Inner, this method will return foo.bar.Outer$Inner. 66 * (This is the name format used in ProGuard keep files for example.) 67 */ 68 fun qualifiedNameWithDollarInnerClasses(): String { 69 var curr: ClassItem? = this 70 while (curr?.containingClass() != null) { 71 curr = curr.containingClass() 72 } 73 74 if (curr == null) { 75 return fullName().replace('.', '$') 76 } 77 78 return curr.containingPackage().qualifiedName() + "." + fullName().replace('.', '$') 79 } 80 81 /** Returns the internal name of the class, as seen in bytecode */ 82 fun internalName(): String { 83 var curr: ClassItem? = this 84 while (curr?.containingClass() != null) { 85 curr = curr.containingClass() 86 } 87 88 if (curr == null) { 89 return fullName().replace('.', '$') 90 } 91 92 return curr.containingPackage().qualifiedName().replace('.', '/') + "/" + 93 fullName().replace('.', '$') 94 } 95 96 /** The super class of this class, if any */ 97 fun superClass(): ClassItem? 98 99 /** The super class type of this class, if any. The difference between this and [superClass] is 100 * that the type reference can include type arguments; e.g. in "class MyList extends List<String>" 101 * the super class is java.util.List and the super class type is java.util.List<java.lang.String>. 102 * */ 103 fun superClassType(): TypeItem? 104 105 /** Finds the public super class of this class, if any */ 106 fun publicSuperClass(): ClassItem? { 107 var superClass = superClass() 108 while (superClass != null && !superClass.checkLevel()) { 109 superClass = superClass.superClass() 110 } 111 112 return superClass 113 } 114 115 /** Returns true if this class extends the given class (includes self) */ 116 fun extends(qualifiedName: String): Boolean { 117 if (qualifiedName() == qualifiedName) { 118 return true 119 } 120 121 val superClass = superClass() 122 return superClass?.extends(qualifiedName) ?: when { 123 isEnum() -> qualifiedName == JAVA_LANG_ENUM 124 isAnnotationType() -> qualifiedName == JAVA_LANG_ANNOTATION 125 else -> qualifiedName == JAVA_LANG_OBJECT 126 } 127 } 128 129 /** Returns true if this class implements the given interface (includes self) */ 130 fun implements(qualifiedName: String): Boolean { 131 if (qualifiedName() == qualifiedName) { 132 return true 133 } 134 135 interfaceTypes().forEach { 136 val cls = it.asClass() 137 if (cls != null && cls.implements(qualifiedName)) { 138 return true 139 } 140 } 141 142 // Might be implementing via superclass 143 if (superClass()?.implements(qualifiedName) == true) { 144 return true 145 } 146 147 return false 148 } 149 150 /** Returns true if this class extends or implements the given class or interface */ 151 fun extendsOrImplements(qualifiedName: String): Boolean = extends(qualifiedName) || implements(qualifiedName) 152 153 /** Any interfaces implemented by this class */ 154 fun interfaceTypes(): List<TypeItem> 155 156 /** All classes and interfaces implemented (by this class and its super classes and the interfaces themselves) */ 157 fun allInterfaces(): Sequence<ClassItem> 158 159 /** Any inner classes of this class */ 160 fun innerClasses(): List<ClassItem> 161 162 /** The constructors in this class */ 163 fun constructors(): List<ConstructorItem> 164 165 /** Whether this class has an implicit default constructor */ 166 fun hasImplicitDefaultConstructor(): Boolean 167 168 /** The non-constructor methods in this class */ 169 fun methods(): List<MethodItem> 170 171 /** The properties in this class */ 172 fun properties(): List<PropertyItem> 173 174 /** The fields in this class */ 175 fun fields(): List<FieldItem> 176 177 /** The members in this class: constructors, methods, fields/enum constants */ 178 fun members(): Sequence<MemberItem> { 179 return fields().asSequence().plus(constructors().asSequence()).plus(methods().asSequence()) 180 } 181 182 /** Whether this class is an interface */ 183 fun isInterface(): Boolean 184 185 /** Whether this class is an annotation type */ 186 fun isAnnotationType(): Boolean 187 188 /** Whether this class is an enum */ 189 fun isEnum(): Boolean 190 191 /** Whether this class is a regular class (not an interface, not an enum, etc) */ 192 fun isClass(): Boolean = !isInterface() && !isAnnotationType() && !isEnum() 193 194 /** The containing class, for inner classes */ 195 fun containingClass(): ClassItem? 196 197 /** The containing package */ 198 fun containingPackage(): PackageItem 199 200 override fun containingPackage(strict: Boolean): PackageItem = containingPackage() 201 202 override fun containingClass(strict: Boolean): ClassItem? { 203 return if (strict) containingClass() else this 204 } 205 206 /** Gets the type for this class */ 207 fun toType(): TypeItem 208 209 override fun type(): TypeItem? = null 210 211 /** Returns true if this class has type parameters */ 212 fun hasTypeVariables(): Boolean 213 214 /** Any type parameters for the class, if any, as a source string (with fully qualified class names) */ 215 fun typeParameterList(): TypeParameterList 216 217 /** Returns the classes that are part of the type parameters of this method, if any */ 218 fun typeArgumentClasses(): List<ClassItem> = codebase.unsupported() 219 220 fun isJavaLangObject(): Boolean { 221 return qualifiedName() == JAVA_LANG_OBJECT 222 } 223 224 // Mutation APIs: Used to "fix up" the API hierarchy (in [ApiAnalyzer]) to only expose 225 // visible parts of the API) 226 227 // This replaces the "real" super class 228 fun setSuperClass(superClass: ClassItem?, superClassType: TypeItem? = superClass?.toType()) 229 230 // This replaces the interface types implemented by this class 231 fun setInterfaceTypes(interfaceTypes: List<TypeItem>) 232 233 // Whether this class is a generic type parameter, such as T, rather than a non-generic type, like String 234 val isTypeParameter: Boolean 235 236 var hasPrivateConstructor: Boolean 237 238 /** 239 * Maven artifact of this class, if any. (Not used for the Android SDK, but used in 240 * for example support libraries. 241 */ 242 var artifact: String? 243 244 override fun accept(visitor: ItemVisitor) { 245 if (visitor is ApiVisitor) { 246 accept(visitor) 247 return 248 } 249 250 if (visitor.skip(this)) { 251 return 252 } 253 254 visitor.visitItem(this) 255 visitor.visitClass(this) 256 257 for (constructor in constructors()) { 258 constructor.accept(visitor) 259 } 260 261 for (method in methods()) { 262 method.accept(visitor) 263 } 264 265 for (property in properties()) { 266 property.accept(visitor) 267 } 268 269 if (isEnum()) { 270 // In enums, visit the enum constants first, then the fields 271 for (field in fields()) { 272 if (field.isEnumConstant()) { 273 field.accept(visitor) 274 } 275 } 276 for (field in fields()) { 277 if (!field.isEnumConstant()) { 278 field.accept(visitor) 279 } 280 } 281 } else { 282 for (field in fields()) { 283 field.accept(visitor) 284 } 285 } 286 287 if (visitor.nestInnerClasses) { 288 for (cls in innerClasses()) { 289 cls.accept(visitor) 290 } 291 } // otherwise done below 292 293 visitor.afterVisitClass(this) 294 visitor.afterVisitItem(this) 295 296 if (!visitor.nestInnerClasses) { 297 for (cls in innerClasses()) { 298 cls.accept(visitor) 299 } 300 } 301 } 302 303 fun accept(visitor: ApiVisitor) { 304 305 if (!visitor.include(this)) { 306 return 307 } 308 309 // We build up a separate data structure such that we can compute the 310 // sets of fields, methods, etc even for inner classes (recursively); that way 311 // we can easily and up front determine whether we have any matches for 312 // inner classes (which is vital for computing the removed-api for example, where 313 // only something like the appearance of a removed method inside an inner class 314 // results in the outer class being described in the signature file. 315 val candidate = VisitCandidate(this, visitor) 316 candidate.accept() 317 } 318 319 override fun acceptTypes(visitor: TypeVisitor) { 320 if (visitor.skip(this)) { 321 return 322 } 323 324 val type = toType() 325 visitor.visitType(type, this) 326 327 // TODO: Visit type parameter list (at least the bounds types, e.g. View in <T extends View> 328 superClass()?.let { 329 visitor.visitType(it.toType(), it) 330 } 331 332 if (visitor.includeInterfaces) { 333 for (itf in interfaceTypes()) { 334 val owner = itf.asClass() 335 owner?.let { visitor.visitType(itf, it) } 336 } 337 } 338 339 for (constructor in constructors()) { 340 constructor.acceptTypes(visitor) 341 } 342 for (field in fields()) { 343 field.acceptTypes(visitor) 344 } 345 for (method in methods()) { 346 method.acceptTypes(visitor) 347 } 348 for (cls in innerClasses()) { 349 cls.acceptTypes(visitor) 350 } 351 352 visitor.afterVisitType(type, this) 353 } 354 355 companion object { 356 /** Looks up the retention policy for the given class */ 357 fun findRetention(cls: ClassItem): AnnotationRetention { 358 val modifiers = cls.modifiers 359 val annotation = modifiers.findAnnotation("java.lang.annotation.Retention") 360 ?: modifiers.findAnnotation("kotlin.annotation.Retention") 361 val value = annotation?.findAttribute(SdkConstants.ATTR_VALUE) 362 val source = value?.value?.toSource() 363 return when { 364 source == null -> AnnotationRetention.CLASS // default 365 source.contains("RUNTIME") -> AnnotationRetention.RUNTIME 366 source.contains("SOURCE") -> AnnotationRetention.SOURCE 367 else -> AnnotationRetention.CLASS // default 368 } 369 } 370 371 // Same as doclava1 (modulo the new handling when class names match) 372 val comparator: Comparator<in ClassItem> = Comparator { o1, o2 -> 373 val delta = o1.fullName().compareTo(o2.fullName()) 374 if (delta == 0) { 375 o1.qualifiedName().compareTo(o2.qualifiedName()) 376 } else { 377 delta 378 } 379 } 380 381 val nameComparator: Comparator<ClassItem> = Comparator { a, b -> 382 a.simpleName().compareTo(b.simpleName()) 383 } 384 385 val fullNameComparator: Comparator<ClassItem> = Comparator { a, b -> a.fullName().compareTo(b.fullName()) } 386 387 val qualifiedComparator: Comparator<ClassItem> = Comparator { a, b -> 388 a.qualifiedName().compareTo(b.qualifiedName()) 389 } 390 391 fun classNameSorter(): Comparator<in ClassItem> = ClassItem.qualifiedComparator 392 } 393 394 fun findMethod( 395 template: MethodItem, 396 includeSuperClasses: Boolean = false, 397 includeInterfaces: Boolean = false 398 ): MethodItem? { 399 if (template.isConstructor()) { 400 return findConstructor(template as ConstructorItem) 401 } 402 403 methods().asSequence() 404 .filter { it.matches(template) } 405 .forEach { return it } 406 407 if (includeSuperClasses) { 408 superClass()?.findMethod(template, true, includeInterfaces)?.let { return it } 409 } 410 411 if (includeInterfaces) { 412 for (itf in interfaceTypes()) { 413 val cls = itf.asClass() ?: continue 414 cls.findMethod(template, includeSuperClasses, true)?.let { return it } 415 } 416 } 417 return null 418 } 419 420 /** 421 * Finds a method matching the given method that satisfies the given predicate, 422 * considering all methods defined on this class and its super classes 423 */ 424 fun findPredicateMethodWithSuper(template: MethodItem, filter: Predicate<Item>?): MethodItem? { 425 val method = findMethod(template, true, true) 426 if (method == null) { 427 return null 428 } 429 if (filter == null || filter.test(method)) { 430 return method 431 } 432 return method.findPredicateSuperMethod(filter) 433 } 434 435 /** Finds a given method in this class matching the VM name signature */ 436 fun findMethodByDesc( 437 name: String, 438 desc: String, 439 includeSuperClasses: Boolean = false, 440 includeInterfaces: Boolean = false 441 ): MethodItem? { 442 if (desc.startsWith("<init>")) { 443 constructors().asSequence() 444 .filter { it.internalDesc() == desc } 445 .forEach { return it } 446 return null 447 } else { 448 methods().asSequence() 449 .filter { it.name() == name && it.internalDesc() == desc } 450 .forEach { return it } 451 } 452 453 if (includeSuperClasses) { 454 superClass()?.findMethodByDesc(name, desc, true, includeInterfaces)?.let { return it } 455 } 456 457 if (includeInterfaces) { 458 for (itf in interfaceTypes()) { 459 val cls = itf.asClass() ?: continue 460 cls.findMethodByDesc(name, desc, includeSuperClasses, true)?.let { return it } 461 } 462 } 463 return null 464 } 465 466 fun findConstructor(template: ConstructorItem): ConstructorItem? { 467 constructors().asSequence() 468 .filter { it.matches(template) } 469 .forEach { return it } 470 return null 471 } 472 473 fun findField( 474 fieldName: String, 475 includeSuperClasses: Boolean = false, 476 includeInterfaces: Boolean = false 477 ): FieldItem? { 478 val field = fields().firstOrNull { it.name() == fieldName } 479 if (field != null) { 480 return field 481 } 482 483 if (includeSuperClasses) { 484 superClass()?.findField(fieldName, true, includeInterfaces)?.let { return it } 485 } 486 487 if (includeInterfaces) { 488 for (itf in interfaceTypes()) { 489 val cls = itf.asClass() ?: continue 490 cls.findField(fieldName, includeSuperClasses, true)?.let { return it } 491 } 492 } 493 return null 494 } 495 496 fun findMethod(methodName: String, parameters: String): MethodItem? { 497 if (methodName == simpleName()) { 498 // Constructor 499 constructors() 500 .filter { parametersMatch(it, parameters) } 501 .forEach { return it } 502 } else { 503 methods() 504 .filter { it.name() == methodName && parametersMatch(it, parameters) } 505 .forEach { return it } 506 } 507 508 return null 509 } 510 511 private fun parametersMatch(method: MethodItem, description: String): Boolean { 512 val parameterStrings = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(description) 513 val parameters = method.parameters() 514 if (parameters.size != parameterStrings.size) { 515 return false 516 } 517 for (i in parameters.indices) { 518 var parameterString = parameterStrings[i] 519 val index = parameterString.indexOf('<') 520 if (index != -1) { 521 parameterString = parameterString.substring(0, index) 522 } 523 val parameter = parameters[i].type().toErasedTypeString(method) 524 if (parameter != parameterString) { 525 return false 526 } 527 } 528 529 return true 530 } 531 532 /** Returns the corresponding compilation unit, if any */ 533 fun getCompilationUnit(): CompilationUnit? = null 534 535 /** If this class is an annotation type, returns the retention of this class */ 536 fun getRetention(): AnnotationRetention 537 538 /** 539 * Return superclass matching the given predicate. When a superclass doesn't 540 * match, we'll keep crawling up the tree until we find someone who matches. 541 */ 542 fun filteredSuperclass(predicate: Predicate<Item>): ClassItem? { 543 val superClass = superClass() ?: return null 544 return if (predicate.test(superClass)) { 545 superClass 546 } else { 547 superClass.filteredSuperclass(predicate) 548 } 549 } 550 551 fun filteredSuperClassType(predicate: Predicate<Item>): TypeItem? { 552 var superClassType: TypeItem? = superClassType() ?: return null 553 var prev: ClassItem? = null 554 while (superClassType != null) { 555 val superClass = superClassType.asClass() ?: return null 556 if (predicate.test(superClass)) { 557 if (prev == null || superClass == superClass()) { 558 // Direct reference; no need to map type variables 559 return superClassType 560 } 561 if (!superClassType.hasTypeArguments()) { 562 // No type variables - also no need for mapping 563 return superClassType 564 } 565 566 return superClassType.convertType(this, prev) 567 } 568 569 prev = superClass 570 superClassType = superClass.superClassType() 571 } 572 573 return null 574 } 575 576 /** 577 * Return methods matching the given predicate. Forcibly includes local 578 * methods that override a matching method in an ancestor class. 579 */ 580 fun filteredMethods( 581 predicate: Predicate<Item>, 582 includeSuperClassMethods: Boolean = false 583 ): Collection<MethodItem> { 584 val methods = LinkedHashSet<MethodItem>() 585 for (method in methods()) { 586 if (predicate.test(method) || method.findPredicateSuperMethod(predicate) != null) { 587 // val duplicated = method.duplicate(this) 588 // methods.add(duplicated) 589 methods.remove(method) 590 methods.add(method) 591 } 592 } 593 if (includeSuperClassMethods) { 594 superClass()?.filteredMethods(predicate, includeSuperClassMethods)?.let { methods += it } 595 } 596 return methods 597 } 598 599 /** Returns the constructors that match the given predicate */ 600 fun filteredConstructors(predicate: Predicate<Item>): Sequence<ConstructorItem> { 601 return constructors().asSequence().filter { predicate.test(it) } 602 } 603 604 /** 605 * Return fields matching the given predicate. Also clones fields from 606 * ancestors that would match had they been defined in this class. 607 */ 608 fun filteredFields(predicate: Predicate<Item>, showUnannotated: Boolean): List<FieldItem> { 609 val fields = LinkedHashSet<FieldItem>() 610 if (showUnannotated) { 611 for (clazz in allInterfaces()) { 612 if (!clazz.isInterface()) { 613 continue 614 } 615 for (field in clazz.fields()) { 616 if (!predicate.test(field)) { 617 val duplicated = field.duplicate(this) 618 if (predicate.test(duplicated)) { 619 fields.remove(duplicated) 620 fields.add(duplicated) 621 } 622 } 623 } 624 } 625 626 val superClass = superClass() 627 if (superClass != null && !predicate.test(superClass) && predicate.test(this)) { 628 // Include constants from hidden super classes. 629 for (field in superClass.fields()) { 630 val fieldModifiers = field.modifiers 631 if (!fieldModifiers.isStatic() || !fieldModifiers.isFinal() || !fieldModifiers.isPublic()) { 632 continue 633 } 634 if (!field.originallyHidden) { 635 val duplicated = field.duplicate(this) 636 if (predicate.test(duplicated)) { 637 duplicated.inheritedField = true 638 fields.remove(duplicated) 639 fields.add(duplicated) 640 } 641 } 642 } 643 } 644 } 645 for (field in fields()) { 646 if (predicate.test(field)) { 647 fields.remove(field) 648 fields.add(field) 649 } 650 } 651 if (fields.isEmpty()) { 652 return emptyList() 653 } 654 val list = fields.toMutableList() 655 list.sortWith(FieldItem.comparator) 656 return list 657 } 658 659 fun filteredInterfaceTypes(predicate: Predicate<Item>): Collection<TypeItem> { 660 val interfaceTypes = filteredInterfaceTypes( 661 predicate, LinkedHashSet(), 662 includeSelf = false, includeParents = false, target = this 663 ) 664 if (interfaceTypes.isEmpty()) { 665 return interfaceTypes 666 } 667 668 return interfaceTypes 669 } 670 671 fun allInterfaceTypes(predicate: Predicate<Item>): Collection<TypeItem> { 672 val interfaceTypes = filteredInterfaceTypes( 673 predicate, LinkedHashSet(), 674 includeSelf = false, includeParents = true, target = this 675 ) 676 if (interfaceTypes.isEmpty()) { 677 return interfaceTypes 678 } 679 680 return interfaceTypes 681 } 682 683 private fun filteredInterfaceTypes( 684 predicate: Predicate<Item>, 685 types: LinkedHashSet<TypeItem>, 686 includeSelf: Boolean, 687 includeParents: Boolean, 688 target: ClassItem 689 ): LinkedHashSet<TypeItem> { 690 val superClassType = superClassType() 691 if (superClassType != null) { 692 val superClass = superClassType.asClass() 693 if (superClass != null) { 694 if (!predicate.test(superClass)) { 695 superClass.filteredInterfaceTypes(predicate, types, true, includeParents, target) 696 } else if (includeSelf && superClass.isInterface()) { 697 types.add(superClassType) 698 if (includeParents) { 699 superClass.filteredInterfaceTypes(predicate, types, true, includeParents, target) 700 } 701 } 702 } 703 } 704 for (type in interfaceTypes()) { 705 val cls = type.asClass() ?: continue 706 if (predicate.test(cls)) { 707 if (hasTypeVariables() && type.hasTypeArguments()) { 708 val replacementMap = target.mapTypeVariables(this) 709 if (replacementMap.isNotEmpty()) { 710 val mapped = type.convertType(replacementMap) 711 types.add(mapped) 712 continue 713 } 714 } 715 types.add(type) 716 if (includeParents) { 717 cls.filteredInterfaceTypes(predicate, types, true, includeParents, target) 718 } 719 } else { 720 cls.filteredInterfaceTypes(predicate, types, true, includeParents, target) 721 } 722 } 723 return types 724 } 725 726 fun allInnerClasses(includeSelf: Boolean = false): Sequence<ClassItem> { 727 if (!includeSelf && innerClasses().isEmpty()) { 728 return emptySequence() 729 } 730 731 val list = ArrayList<ClassItem>() 732 if (includeSelf) { 733 list.add(this) 734 } 735 addInnerClasses(list, this) 736 return list.asSequence() 737 } 738 739 private fun addInnerClasses(list: MutableList<ClassItem>, cls: ClassItem) { 740 for (innerClass in cls.innerClasses()) { 741 list.add(innerClass) 742 addInnerClasses(list, innerClass) 743 } 744 } 745 746 /** 747 * The default constructor to invoke on this class from subclasses; initially null 748 * but populated by [ApiAnalyzer.addConstructors]. (Note that in some cases 749 * [stubConstructor] may not be in [constructors], e.g. when we need to 750 * create a constructor to match a public parent class with a non-default constructor 751 * and the one in the code is not a match, e.g. is marked @hide etc.) 752 */ 753 var stubConstructor: ConstructorItem? 754 755 /** 756 * Creates a map of type variables from this class to the given target class. 757 * If class A<X,Y> extends B<X,Y>, and B is declared as class B<M,N>, 758 * this returns the map {"X"->"M", "Y"->"N"}. There could be multiple intermediate 759 * classes between this class and the target class, and in some cases we could 760 * be substituting in a concrete class, e.g. class MyClass extends B<String,Number> 761 * would return the map {"java.lang.String"->"M", "java.lang.Number"->"N"}. 762 * 763 * If [reverse] is true, compute the reverse map: keys are the variables in 764 * the target and the values are the variables in the source. 765 */ 766 fun mapTypeVariables(target: ClassItem): Map<String, String> = codebase.unsupported() 767 768 /** 769 * Creates a constructor in this class 770 */ 771 fun createDefaultConstructor(): ConstructorItem = codebase.unsupported() 772 773 /** 774 * Creates a method corresponding to the given method signature in this class 775 */ 776 fun createMethod(template: MethodItem): MethodItem = codebase.unsupported() 777 778 fun addMethod(method: MethodItem): Unit = codebase.unsupported() 779 } 780 781 class VisitCandidate(val cls: ClassItem, private val visitor: ApiVisitor) { 782 val innerClasses: Sequence<VisitCandidate> 783 private val constructors: Sequence<MethodItem> 784 private val methods: Sequence<MethodItem> 785 private val fields: Sequence<FieldItem> 786 private val enums: Sequence<FieldItem> 787 private val properties: Sequence<PropertyItem> 788 789 init { 790 val filterEmit = visitor.filterEmit 791 792 constructors = cls.constructors().asSequence() <lambda>null793 .filter { filterEmit.test(it) } 794 .sortedWith(MethodItem.comparator) 795 796 methods = cls.methods().asSequence() <lambda>null797 .filter { filterEmit.test(it) } 798 .sortedWith(MethodItem.comparator) 799 800 val fieldSequence = 801 if (visitor.inlineInheritedFields) { 802 cls.filteredFields(filterEmit, visitor.showUnannotated).asSequence() 803 } else { 804 cls.fields().asSequence() <lambda>null805 .filter { filterEmit.test(it) } 806 } 807 if (cls.isEnum()) { 808 fields = fieldSequence <lambda>null809 .filter { !it.isEnumConstant() } 810 .sortedWith(FieldItem.comparator) 811 enums = fieldSequence <lambda>null812 .filter { it.isEnumConstant() } <lambda>null813 .filter { filterEmit.test(it) } 814 .sortedWith(FieldItem.comparator) 815 } else { 816 fields = fieldSequence.sortedWith(FieldItem.comparator) 817 enums = emptySequence() 818 } 819 820 properties = if (cls.properties().isEmpty()) { 821 emptySequence() 822 } else { 823 cls.properties().asSequence() <lambda>null824 .filter { filterEmit.test(it) } 825 .sortedWith(PropertyItem.comparator) 826 } 827 828 innerClasses = cls.innerClasses() 829 .asSequence() 830 .sortedWith(ClassItem.classNameSorter()) <lambda>null831 .map { VisitCandidate(it, visitor) } 832 } 833 834 /** Whether the class body contains any Item's (other than inner Classes) */ nonEmptynull835 fun nonEmpty(): Boolean { 836 return !(constructors.none() && methods.none() && enums.none() && fields.none() && properties.none()) 837 } 838 acceptnull839 fun accept() { 840 if (!visitor.include(this)) { 841 return 842 } 843 844 val emitThis = visitor.shouldEmitClass(this) 845 if (emitThis) { 846 if (!visitor.visitingPackage) { 847 visitor.visitingPackage = true 848 val pkg = cls.containingPackage() 849 visitor.visitItem(pkg) 850 visitor.visitPackage(pkg) 851 } 852 853 visitor.visitItem(cls) 854 visitor.visitClass(cls) 855 856 val sortedConstructors = if (visitor.methodComparator != null) { 857 constructors.sortedWith(visitor.methodComparator) 858 } else { 859 constructors 860 } 861 val sortedMethods = if (visitor.methodComparator != null) { 862 methods.sortedWith(visitor.methodComparator) 863 } else { 864 methods 865 } 866 val sortedFields = if (visitor.fieldComparator != null) { 867 fields.sortedWith(visitor.fieldComparator) 868 } else { 869 fields 870 } 871 872 for (constructor in sortedConstructors) { 873 constructor.accept(visitor) 874 } 875 876 for (method in sortedMethods) { 877 method.accept(visitor) 878 } 879 880 for (property in properties) { 881 property.accept(visitor) 882 } 883 for (enumConstant in enums) { 884 enumConstant.accept(visitor) 885 } 886 for (field in sortedFields) { 887 field.accept(visitor) 888 } 889 } 890 891 if (visitor.nestInnerClasses) { // otherwise done below 892 innerClasses.forEach { it.accept() } 893 } 894 895 if (emitThis) { 896 visitor.afterVisitClass(cls) 897 visitor.afterVisitItem(cls) 898 } 899 900 if (!visitor.nestInnerClasses) { 901 innerClasses.forEach { it.accept() } 902 } 903 } 904 } 905