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