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 /** Finds a given method in this class matching the VM name signature */ 421 fun findMethodByDesc( 422 name: String, 423 desc: String, 424 includeSuperClasses: Boolean = false, 425 includeInterfaces: Boolean = false 426 ): MethodItem? { 427 if (desc.startsWith("<init>")) { 428 constructors().asSequence() 429 .filter { it.internalDesc() == desc } 430 .forEach { return it } 431 return null 432 } else { 433 methods().asSequence() 434 .filter { it.name() == name && it.internalDesc() == desc } 435 .forEach { return it } 436 } 437 438 if (includeSuperClasses) { 439 superClass()?.findMethodByDesc(name, desc, true, includeInterfaces)?.let { return it } 440 } 441 442 if (includeInterfaces) { 443 for (itf in interfaceTypes()) { 444 val cls = itf.asClass() ?: continue 445 cls.findMethodByDesc(name, desc, includeSuperClasses, true)?.let { return it } 446 } 447 } 448 return null 449 } 450 451 fun findConstructor(template: ConstructorItem): ConstructorItem? { 452 constructors().asSequence() 453 .filter { it.matches(template) } 454 .forEach { return it } 455 return null 456 } 457 458 fun findField( 459 fieldName: String, 460 includeSuperClasses: Boolean = false, 461 includeInterfaces: Boolean = false 462 ): FieldItem? { 463 val field = fields().firstOrNull { it.name() == fieldName } 464 if (field != null) { 465 return field 466 } 467 468 if (includeSuperClasses) { 469 superClass()?.findField(fieldName, true, includeInterfaces)?.let { return it } 470 } 471 472 if (includeInterfaces) { 473 for (itf in interfaceTypes()) { 474 val cls = itf.asClass() ?: continue 475 cls.findField(fieldName, includeSuperClasses, true)?.let { return it } 476 } 477 } 478 return null 479 } 480 481 fun findMethod(methodName: String, parameters: String): MethodItem? { 482 if (methodName == simpleName()) { 483 // Constructor 484 constructors() 485 .filter { parametersMatch(it, parameters) } 486 .forEach { return it } 487 } else { 488 methods() 489 .filter { it.name() == methodName && parametersMatch(it, parameters) } 490 .forEach { return it } 491 } 492 493 return null 494 } 495 496 private fun parametersMatch(method: MethodItem, description: String): Boolean { 497 val parameterStrings = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(description) 498 val parameters = method.parameters() 499 if (parameters.size != parameterStrings.size) { 500 return false 501 } 502 for (i in parameters.indices) { 503 var parameterString = parameterStrings[i] 504 val index = parameterString.indexOf('<') 505 if (index != -1) { 506 parameterString = parameterString.substring(0, index) 507 } 508 val parameter = parameters[i].type().toErasedTypeString(method) 509 if (parameter != parameterString) { 510 return false 511 } 512 } 513 514 return true 515 } 516 517 /** Returns the corresponding compilation unit, if any */ 518 fun getCompilationUnit(): CompilationUnit? = null 519 520 /** If this class is an annotation type, returns the retention of this class */ 521 fun getRetention(): AnnotationRetention 522 523 /** 524 * Return superclass matching the given predicate. When a superclass doesn't 525 * match, we'll keep crawling up the tree until we find someone who matches. 526 */ 527 fun filteredSuperclass(predicate: Predicate<Item>): ClassItem? { 528 val superClass = superClass() ?: return null 529 return if (predicate.test(superClass)) { 530 superClass 531 } else { 532 superClass.filteredSuperclass(predicate) 533 } 534 } 535 536 fun filteredSuperClassType(predicate: Predicate<Item>): TypeItem? { 537 var superClassType: TypeItem? = superClassType() ?: return null 538 var prev: ClassItem? = null 539 while (superClassType != null) { 540 val superClass = superClassType.asClass() ?: return null 541 if (predicate.test(superClass)) { 542 if (prev == null || superClass == superClass()) { 543 // Direct reference; no need to map type variables 544 return superClassType 545 } 546 if (!superClassType.hasTypeArguments()) { 547 // No type variables - also no need for mapping 548 return superClassType 549 } 550 551 return superClassType.convertType(this, prev) 552 } 553 554 prev = superClass 555 superClassType = superClass.superClassType() 556 } 557 558 return null 559 } 560 561 /** 562 * Return methods matching the given predicate. Forcibly includes local 563 * methods that override a matching method in an ancestor class. 564 */ 565 fun filteredMethods(predicate: Predicate<Item>): Collection<MethodItem> { 566 val methods = LinkedHashSet<MethodItem>() 567 for (method in methods()) { 568 if (predicate.test(method) || method.findPredicateSuperMethod(predicate) != null) { 569 // val duplicated = method.duplicate(this) 570 // methods.add(duplicated) 571 methods.remove(method) 572 methods.add(method) 573 } 574 } 575 return methods 576 } 577 578 /** Returns the constructors that match the given predicate */ 579 fun filteredConstructors(predicate: Predicate<Item>): Sequence<ConstructorItem> { 580 return constructors().asSequence().filter { predicate.test(it) } 581 } 582 583 /** 584 * Return fields matching the given predicate. Also clones fields from 585 * ancestors that would match had they been defined in this class. 586 */ 587 fun filteredFields(predicate: Predicate<Item>, showUnannotated: Boolean): List<FieldItem> { 588 val fields = LinkedHashSet<FieldItem>() 589 if (showUnannotated) { 590 for (clazz in allInterfaces()) { 591 if (!clazz.isInterface()) { 592 continue 593 } 594 for (field in clazz.fields()) { 595 if (!predicate.test(field)) { 596 val duplicated = field.duplicate(this) 597 if (predicate.test(duplicated)) { 598 fields.remove(duplicated) 599 fields.add(duplicated) 600 } 601 } 602 } 603 } 604 605 val superClass = superClass() 606 if (superClass != null && !predicate.test(superClass) && predicate.test(this)) { 607 // Include constants from hidden super classes. 608 for (field in superClass.fields()) { 609 val fieldModifiers = field.modifiers 610 if (!fieldModifiers.isStatic() || !fieldModifiers.isFinal() || !fieldModifiers.isPublic()) { 611 continue 612 } 613 if (!field.originallyHidden) { 614 val duplicated = field.duplicate(this) 615 if (predicate.test(duplicated)) { 616 duplicated.inheritedField = true 617 fields.remove(duplicated) 618 fields.add(duplicated) 619 } 620 } 621 } 622 } 623 } 624 for (field in fields()) { 625 if (predicate.test(field)) { 626 fields.remove(field) 627 fields.add(field) 628 } 629 } 630 if (fields.isEmpty()) { 631 return emptyList() 632 } 633 val list = fields.toMutableList() 634 list.sortWith(FieldItem.comparator) 635 return list 636 } 637 638 fun filteredInterfaceTypes(predicate: Predicate<Item>): Collection<TypeItem> { 639 val interfaceTypes = filteredInterfaceTypes( 640 predicate, LinkedHashSet(), 641 includeSelf = false, includeParents = false, target = this 642 ) 643 if (interfaceTypes.isEmpty()) { 644 return interfaceTypes 645 } 646 647 return interfaceTypes 648 } 649 650 fun allInterfaceTypes(predicate: Predicate<Item>): Collection<TypeItem> { 651 val interfaceTypes = filteredInterfaceTypes( 652 predicate, LinkedHashSet(), 653 includeSelf = false, includeParents = true, target = this 654 ) 655 if (interfaceTypes.isEmpty()) { 656 return interfaceTypes 657 } 658 659 return interfaceTypes 660 } 661 662 private fun filteredInterfaceTypes( 663 predicate: Predicate<Item>, 664 types: LinkedHashSet<TypeItem>, 665 includeSelf: Boolean, 666 includeParents: Boolean, 667 target: ClassItem 668 ): LinkedHashSet<TypeItem> { 669 val superClassType = superClassType() 670 if (superClassType != null) { 671 val superClass = superClassType.asClass() 672 if (superClass != null) { 673 if (!predicate.test(superClass)) { 674 superClass.filteredInterfaceTypes(predicate, types, true, includeParents, target) 675 } else if (includeSelf && superClass.isInterface()) { 676 types.add(superClassType) 677 if (includeParents) { 678 superClass.filteredInterfaceTypes(predicate, types, true, includeParents, target) 679 } 680 } 681 } 682 } 683 for (type in interfaceTypes()) { 684 val cls = type.asClass() ?: continue 685 if (predicate.test(cls)) { 686 if (hasTypeVariables() && type.hasTypeArguments()) { 687 val replacementMap = target.mapTypeVariables(this) 688 if (replacementMap.isNotEmpty()) { 689 val mapped = type.convertType(replacementMap) 690 types.add(mapped) 691 continue 692 } 693 } 694 types.add(type) 695 if (includeParents) { 696 cls.filteredInterfaceTypes(predicate, types, true, includeParents, target) 697 } 698 } else { 699 cls.filteredInterfaceTypes(predicate, types, true, includeParents, target) 700 } 701 } 702 return types 703 } 704 705 fun allInnerClasses(includeSelf: Boolean = false): Sequence<ClassItem> { 706 if (!includeSelf && innerClasses().isEmpty()) { 707 return emptySequence() 708 } 709 710 val list = ArrayList<ClassItem>() 711 if (includeSelf) { 712 list.add(this) 713 } 714 addInnerClasses(list, this) 715 return list.asSequence() 716 } 717 718 private fun addInnerClasses(list: MutableList<ClassItem>, cls: ClassItem) { 719 for (innerClass in cls.innerClasses()) { 720 list.add(innerClass) 721 addInnerClasses(list, innerClass) 722 } 723 } 724 725 /** 726 * The default constructor to invoke on this class from subclasses; initially null 727 * but populated by [ApiAnalyzer.addConstructors]. (Note that in some cases 728 * [stubConstructor] may not be in [constructors], e.g. when we need to 729 * create a constructor to match a public parent class with a non-default constructor 730 * and the one in the code is not a match, e.g. is marked @hide etc.) 731 */ 732 var stubConstructor: ConstructorItem? 733 734 /** 735 * Creates a map of type variables from this class to the given target class. 736 * If class A<X,Y> extends B<X,Y>, and B is declared as class B<M,N>, 737 * this returns the map {"X"->"M", "Y"->"N"}. There could be multiple intermediate 738 * classes between this class and the target class, and in some cases we could 739 * be substituting in a concrete class, e.g. class MyClass extends B<String,Number> 740 * would return the map {"java.lang.String"->"M", "java.lang.Number"->"N"}. 741 * 742 * If [reverse] is true, compute the reverse map: keys are the variables in 743 * the target and the values are the variables in the source. 744 */ 745 fun mapTypeVariables(target: ClassItem): Map<String, String> = codebase.unsupported() 746 747 /** 748 * Creates a constructor in this class 749 */ 750 fun createDefaultConstructor(): ConstructorItem = codebase.unsupported() 751 752 /** 753 * Creates a method corresponding to the given method signature in this class 754 */ 755 fun createMethod(template: MethodItem): MethodItem = codebase.unsupported() 756 757 fun addMethod(method: MethodItem): Unit = codebase.unsupported() 758 } 759 760 class VisitCandidate(val cls: ClassItem, private val visitor: ApiVisitor) { 761 val innerClasses: Sequence<VisitCandidate> 762 private val constructors: Sequence<MethodItem> 763 private val methods: Sequence<MethodItem> 764 private val fields: Sequence<FieldItem> 765 private val enums: Sequence<FieldItem> 766 private val properties: Sequence<PropertyItem> 767 768 init { 769 val filterEmit = visitor.filterEmit 770 771 constructors = cls.constructors().asSequence() <lambda>null772 .filter { filterEmit.test(it) } 773 .sortedWith(MethodItem.comparator) 774 775 methods = cls.methods().asSequence() <lambda>null776 .filter { filterEmit.test(it) } 777 .sortedWith(MethodItem.comparator) 778 779 val fieldSequence = 780 if (visitor.inlineInheritedFields) { 781 cls.filteredFields(filterEmit, visitor.showUnannotated).asSequence() 782 } else { 783 cls.fields().asSequence() <lambda>null784 .filter { filterEmit.test(it) } 785 } 786 if (cls.isEnum()) { 787 fields = fieldSequence <lambda>null788 .filter { !it.isEnumConstant() } 789 .sortedWith(FieldItem.comparator) 790 enums = fieldSequence <lambda>null791 .filter { it.isEnumConstant() } <lambda>null792 .filter { filterEmit.test(it) } 793 .sortedWith(FieldItem.comparator) 794 } else { 795 fields = fieldSequence.sortedWith(FieldItem.comparator) 796 enums = emptySequence() 797 } 798 799 properties = if (cls.properties().isEmpty()) { 800 emptySequence() 801 } else { 802 cls.properties().asSequence() <lambda>null803 .filter { filterEmit.test(it) } 804 .sortedWith(PropertyItem.comparator) 805 } 806 807 innerClasses = cls.innerClasses() 808 .asSequence() 809 .sortedWith(ClassItem.classNameSorter()) <lambda>null810 .map { VisitCandidate(it, visitor) } 811 } 812 813 /** Whether the class body contains any Item's (other than inner Classes) */ nonEmptynull814 fun nonEmpty(): Boolean { 815 return !(constructors.none() && methods.none() && enums.none() && fields.none() && properties.none()) 816 } 817 acceptnull818 fun accept() { 819 if (!visitor.include(this)) { 820 return 821 } 822 823 val emitThis = visitor.shouldEmitClass(this) 824 if (emitThis) { 825 if (!visitor.visitingPackage) { 826 visitor.visitingPackage = true 827 val pkg = cls.containingPackage() 828 visitor.visitItem(pkg) 829 visitor.visitPackage(pkg) 830 } 831 832 visitor.visitItem(cls) 833 visitor.visitClass(cls) 834 835 val sortedConstructors = if (visitor.methodComparator != null) { 836 constructors.sortedWith(visitor.methodComparator) 837 } else { 838 constructors 839 } 840 val sortedMethods = if (visitor.methodComparator != null) { 841 methods.sortedWith(visitor.methodComparator) 842 } else { 843 methods 844 } 845 val sortedFields = if (visitor.fieldComparator != null) { 846 fields.sortedWith(visitor.fieldComparator) 847 } else { 848 fields 849 } 850 851 for (constructor in sortedConstructors) { 852 constructor.accept(visitor) 853 } 854 855 for (method in sortedMethods) { 856 method.accept(visitor) 857 } 858 859 for (property in properties) { 860 property.accept(visitor) 861 } 862 for (enumConstant in enums) { 863 enumConstant.accept(visitor) 864 } 865 for (field in sortedFields) { 866 field.accept(visitor) 867 } 868 } 869 870 if (visitor.nestInnerClasses) { // otherwise done below 871 innerClasses.forEach { it.accept() } 872 } 873 874 if (emitThis) { 875 visitor.afterVisitClass(cls) 876 visitor.afterVisitItem(cls) 877 } 878 879 if (!visitor.nestInnerClasses) { 880 innerClasses.forEach { it.accept() } 881 } 882 } 883 } 884