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> = TODO("Not yet implemented") 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 /** If true, this is an invisible element that was referenced by a public API. */ 239 var notStrippable: Boolean 240 241 /** 242 * Maven artifact of this class, if any. (Not used for the Android SDK, but used in 243 * for example support libraries. 244 */ 245 var artifact: String? 246 247 override fun accept(visitor: ItemVisitor) { 248 if (visitor is ApiVisitor) { 249 accept(visitor) 250 return 251 } 252 253 if (visitor.skip(this)) { 254 return 255 } 256 257 visitor.visitItem(this) 258 visitor.visitClass(this) 259 260 for (constructor in constructors()) { 261 constructor.accept(visitor) 262 } 263 264 for (method in methods()) { 265 method.accept(visitor) 266 } 267 268 for (property in properties()) { 269 property.accept(visitor) 270 } 271 272 if (isEnum()) { 273 // In enums, visit the enum constants first, then the fields 274 for (field in fields()) { 275 if (field.isEnumConstant()) { 276 field.accept(visitor) 277 } 278 } 279 for (field in fields()) { 280 if (!field.isEnumConstant()) { 281 field.accept(visitor) 282 } 283 } 284 } else { 285 for (field in fields()) { 286 field.accept(visitor) 287 } 288 } 289 290 if (visitor.nestInnerClasses) { 291 for (cls in innerClasses()) { 292 cls.accept(visitor) 293 } 294 } // otherwise done below 295 296 visitor.afterVisitClass(this) 297 visitor.afterVisitItem(this) 298 299 if (!visitor.nestInnerClasses) { 300 for (cls in innerClasses()) { 301 cls.accept(visitor) 302 } 303 } 304 } 305 306 fun accept(visitor: ApiVisitor) { 307 308 if (!visitor.include(this)) { 309 return 310 } 311 312 // We build up a separate data structure such that we can compute the 313 // sets of fields, methods, etc even for inner classes (recursively); that way 314 // we can easily and up front determine whether we have any matches for 315 // inner classes (which is vital for computing the removed-api for example, where 316 // only something like the appearance of a removed method inside an inner class 317 // results in the outer class being described in the signature file. 318 val candidate = VisitCandidate(this, visitor) 319 candidate.accept() 320 } 321 322 override fun acceptTypes(visitor: TypeVisitor) { 323 if (visitor.skip(this)) { 324 return 325 } 326 327 val type = toType() 328 visitor.visitType(type, this) 329 330 // TODO: Visit type parameter list (at least the bounds types, e.g. View in <T extends View> 331 superClass()?.let { 332 visitor.visitType(it.toType(), it) 333 } 334 335 if (visitor.includeInterfaces) { 336 for (itf in interfaceTypes()) { 337 val owner = itf.asClass() 338 owner?.let { visitor.visitType(itf, it) } 339 } 340 } 341 342 for (constructor in constructors()) { 343 constructor.acceptTypes(visitor) 344 } 345 for (field in fields()) { 346 field.acceptTypes(visitor) 347 } 348 for (method in methods()) { 349 method.acceptTypes(visitor) 350 } 351 for (cls in innerClasses()) { 352 cls.acceptTypes(visitor) 353 } 354 355 visitor.afterVisitType(type, this) 356 } 357 358 companion object { 359 /** Looks up the retention policy for the given class */ 360 fun findRetention(cls: ClassItem): AnnotationRetention { 361 val modifiers = cls.modifiers 362 val annotation = modifiers.findAnnotation("java.lang.annotation.Retention") 363 ?: modifiers.findAnnotation("kotlin.annotation.Retention") 364 val value = annotation?.findAttribute(SdkConstants.ATTR_VALUE) 365 val source = value?.value?.toSource() 366 return when { 367 source == null -> AnnotationRetention.CLASS // default 368 source.contains("RUNTIME") -> AnnotationRetention.RUNTIME 369 source.contains("SOURCE") -> AnnotationRetention.SOURCE 370 else -> AnnotationRetention.CLASS // default 371 } 372 } 373 374 // Same as doclava1 (modulo the new handling when class names match) 375 val comparator: Comparator<in ClassItem> = Comparator { o1, o2 -> 376 val delta = o1.fullName().compareTo(o2.fullName()) 377 if (delta == 0) { 378 o1.qualifiedName().compareTo(o2.qualifiedName()) 379 } else { 380 delta 381 } 382 } 383 384 val nameComparator: Comparator<ClassItem> = Comparator { a, b -> 385 a.simpleName().compareTo(b.simpleName()) 386 } 387 388 val fullNameComparator: Comparator<ClassItem> = Comparator { a, b -> a.fullName().compareTo(b.fullName()) } 389 390 val qualifiedComparator: Comparator<ClassItem> = Comparator { a, b -> 391 a.qualifiedName().compareTo(b.qualifiedName()) 392 } 393 394 fun classNameSorter(): Comparator<in ClassItem> = ClassItem.qualifiedComparator 395 } 396 397 fun findMethod( 398 template: MethodItem, 399 includeSuperClasses: Boolean = false, 400 includeInterfaces: Boolean = false 401 ): MethodItem? { 402 if (template.isConstructor()) { 403 return findConstructor(template as ConstructorItem) 404 } 405 406 methods().asSequence() 407 .filter { it.matches(template) } 408 .forEach { return it } 409 410 if (includeSuperClasses) { 411 superClass()?.findMethod(template, true, includeInterfaces)?.let { return it } 412 } 413 414 if (includeInterfaces) { 415 for (itf in interfaceTypes()) { 416 val cls = itf.asClass() ?: continue 417 cls.findMethod(template, includeSuperClasses, true)?.let { return it } 418 } 419 } 420 return null 421 } 422 423 /** Finds a given method in this class matching the VM name signature */ 424 fun findMethodByDesc( 425 name: String, 426 desc: String, 427 includeSuperClasses: Boolean = false, 428 includeInterfaces: Boolean = false 429 ): MethodItem? { 430 if (desc.startsWith("<init>")) { 431 constructors().asSequence() 432 .filter { it.internalDesc() == desc } 433 .forEach { return it } 434 return null 435 } else { 436 methods().asSequence() 437 .filter { it.name() == name && it.internalDesc() == desc } 438 .forEach { return it } 439 } 440 441 if (includeSuperClasses) { 442 superClass()?.findMethodByDesc(name, desc, true, includeInterfaces)?.let { return it } 443 } 444 445 if (includeInterfaces) { 446 for (itf in interfaceTypes()) { 447 val cls = itf.asClass() ?: continue 448 cls.findMethodByDesc(name, desc, includeSuperClasses, true)?.let { return it } 449 } 450 } 451 return null 452 } 453 454 fun findConstructor(template: ConstructorItem): ConstructorItem? { 455 constructors().asSequence() 456 .filter { it.matches(template) } 457 .forEach { return it } 458 return null 459 } 460 461 fun findField( 462 fieldName: String, 463 includeSuperClasses: Boolean = false, 464 includeInterfaces: Boolean = false 465 ): FieldItem? { 466 val field = fields().firstOrNull { it.name() == fieldName } 467 if (field != null) { 468 return field 469 } 470 471 if (includeSuperClasses) { 472 superClass()?.findField(fieldName, true, includeInterfaces)?.let { return it } 473 } 474 475 if (includeInterfaces) { 476 for (itf in interfaceTypes()) { 477 val cls = itf.asClass() ?: continue 478 cls.findField(fieldName, includeSuperClasses, true)?.let { return it } 479 } 480 } 481 return null 482 } 483 484 fun findMethod(methodName: String, parameters: String): MethodItem? { 485 if (methodName == simpleName()) { 486 // Constructor 487 constructors() 488 .filter { parametersMatch(it, parameters) } 489 .forEach { return it } 490 } else { 491 methods() 492 .filter { it.name() == methodName && parametersMatch(it, parameters) } 493 .forEach { return it } 494 } 495 496 return null 497 } 498 499 private fun parametersMatch(method: MethodItem, description: String): Boolean { 500 val parameterStrings = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(description) 501 val parameters = method.parameters() 502 if (parameters.size != parameterStrings.size) { 503 return false 504 } 505 for (i in 0 until parameters.size) { 506 var parameterString = parameterStrings[i] 507 val index = parameterString.indexOf('<') 508 if (index != -1) { 509 parameterString = parameterString.substring(0, index) 510 } 511 val parameter = parameters[i].type().toErasedTypeString(method) 512 if (parameter != parameterString) { 513 return false 514 } 515 } 516 517 return true 518 } 519 520 /** Returns the corresponding compilation unit, if any */ 521 fun getCompilationUnit(): CompilationUnit? = null 522 523 /** If this class is an annotation type, returns the retention of this class */ 524 fun getRetention(): AnnotationRetention 525 526 /** 527 * Return superclass matching the given predicate. When a superclass doesn't 528 * match, we'll keep crawling up the tree until we find someone who matches. 529 */ 530 fun filteredSuperclass(predicate: Predicate<Item>): ClassItem? { 531 val superClass = superClass() ?: return null 532 return if (predicate.test(superClass)) { 533 superClass 534 } else { 535 superClass.filteredSuperclass(predicate) 536 } 537 } 538 539 fun filteredSuperClassType(predicate: Predicate<Item>): TypeItem? { 540 var superClassType: TypeItem? = superClassType() ?: return null 541 var prev: ClassItem? = null 542 while (superClassType != null) { 543 val superClass = superClassType.asClass() ?: return null 544 if (predicate.test(superClass)) { 545 if (prev == null || superClass == superClass()) { 546 // Direct reference; no need to map type variables 547 return superClassType 548 } 549 if (!superClassType.hasTypeArguments()) { 550 // No type variables - also no need for mapping 551 return superClassType 552 } 553 554 return superClassType.convertType(this, prev) 555 } 556 557 prev = superClass 558 superClassType = superClass.superClassType() 559 } 560 561 return null 562 } 563 564 /** 565 * Return methods matching the given predicate. Forcibly includes local 566 * methods that override a matching method in an ancestor class. 567 */ 568 fun filteredMethods(predicate: Predicate<Item>): Collection<MethodItem> { 569 val methods = LinkedHashSet<MethodItem>() 570 for (method in methods()) { 571 if (predicate.test(method) || method.findPredicateSuperMethod(predicate) != null) { 572 // val duplicated = method.duplicate(this) 573 // methods.add(duplicated) 574 methods.remove(method) 575 methods.add(method) 576 } 577 } 578 return methods 579 } 580 581 /** Returns the constructors that match the given predicate */ 582 fun filteredConstructors(predicate: Predicate<Item>): Sequence<ConstructorItem> { 583 return constructors().asSequence().filter { predicate.test(it) } 584 } 585 586 /** 587 * Return fields matching the given predicate. Also clones fields from 588 * ancestors that would match had they been defined in this class. 589 */ 590 fun filteredFields(predicate: Predicate<Item>, showUnannotated: Boolean): List<FieldItem> { 591 val fields = LinkedHashSet<FieldItem>() 592 if (showUnannotated) { 593 for (clazz in allInterfaces()) { 594 if (!clazz.isInterface()) { 595 continue 596 } 597 for (field in clazz.fields()) { 598 if (!predicate.test(field)) { 599 val duplicated = field.duplicate(this) 600 if (predicate.test(duplicated)) { 601 fields.remove(duplicated) 602 fields.add(duplicated) 603 } 604 } 605 } 606 } 607 608 val superClass = superClass() 609 if (superClass != null && !predicate.test(superClass) && predicate.test(this)) { 610 // Include constants from hidden super classes. 611 for (field in superClass.fields()) { 612 val fieldModifiers = field.modifiers 613 if (!fieldModifiers.isStatic() || !fieldModifiers.isFinal() || !fieldModifiers.isPublic()) { 614 continue 615 } 616 if (!field.originallyHidden) { 617 val duplicated = field.duplicate(this) 618 if (predicate.test(duplicated)) { 619 duplicated.inheritedField = true 620 fields.remove(duplicated) 621 fields.add(duplicated) 622 } 623 } 624 } 625 } 626 } 627 for (field in fields()) { 628 if (predicate.test(field)) { 629 fields.remove(field) 630 fields.add(field) 631 } 632 } 633 if (fields.isEmpty()) { 634 return emptyList() 635 } 636 val list = fields.toMutableList() 637 list.sortWith(FieldItem.comparator) 638 return list 639 } 640 641 fun filteredInterfaceTypes(predicate: Predicate<Item>): Collection<TypeItem> { 642 val interfaceTypes = filteredInterfaceTypes( 643 predicate, LinkedHashSet(), 644 includeSelf = false, includeParents = false, target = this 645 ) 646 if (interfaceTypes.isEmpty()) { 647 return interfaceTypes 648 } 649 650 return interfaceTypes 651 } 652 653 fun allInterfaceTypes(predicate: Predicate<Item>): Collection<TypeItem> { 654 val interfaceTypes = filteredInterfaceTypes( 655 predicate, LinkedHashSet(), 656 includeSelf = false, includeParents = true, target = this 657 ) 658 if (interfaceTypes.isEmpty()) { 659 return interfaceTypes 660 } 661 662 return interfaceTypes 663 } 664 665 private fun filteredInterfaceTypes( 666 predicate: Predicate<Item>, 667 types: LinkedHashSet<TypeItem>, 668 includeSelf: Boolean, 669 includeParents: Boolean, 670 target: ClassItem 671 ): LinkedHashSet<TypeItem> { 672 val superClassType = superClassType() 673 if (superClassType != null) { 674 val superClass = superClassType.asClass() 675 if (superClass != null) { 676 if (!predicate.test(superClass)) { 677 superClass.filteredInterfaceTypes(predicate, types, true, includeParents, target) 678 } else if (includeSelf && superClass.isInterface()) { 679 types.add(superClassType) 680 if (includeParents) { 681 superClass.filteredInterfaceTypes(predicate, types, true, includeParents, target) 682 } 683 } 684 } 685 } 686 for (type in interfaceTypes()) { 687 val cls = type.asClass() ?: continue 688 if (predicate.test(cls)) { 689 if (hasTypeVariables() && type.hasTypeArguments()) { 690 val replacementMap = target.mapTypeVariables(this) 691 if (replacementMap.isNotEmpty()) { 692 val mapped = type.convertType(replacementMap) 693 types.add(mapped) 694 continue 695 } 696 } 697 types.add(type) 698 if (includeParents) { 699 cls.filteredInterfaceTypes(predicate, types, true, includeParents, target) 700 } 701 } else { 702 cls.filteredInterfaceTypes(predicate, types, true, includeParents, target) 703 } 704 } 705 return types 706 } 707 708 fun allInnerClasses(includeSelf: Boolean = false): Sequence<ClassItem> { 709 if (!includeSelf && innerClasses().isEmpty()) { 710 return emptySequence() 711 } 712 713 val list = ArrayList<ClassItem>() 714 if (includeSelf) { 715 list.add(this) 716 } 717 addInnerClasses(list, this) 718 return list.asSequence() 719 } 720 721 private fun addInnerClasses(list: MutableList<ClassItem>, cls: ClassItem) { 722 for (innerClass in cls.innerClasses()) { 723 list.add(innerClass) 724 addInnerClasses(list, innerClass) 725 } 726 } 727 728 /** 729 * The default constructor to invoke on this class from subclasses; initially null 730 * but populated by [ApiAnalyzer.addConstructors]. (Note that in some cases 731 * [stubConstructor] may not be in [constructors], e.g. when we need to 732 * create a constructor to match a public parent class with a non-default constructor 733 * and the one in the code is not a match, e.g. is marked @hide etc.) 734 */ 735 var stubConstructor: ConstructorItem? 736 737 /** 738 * Creates a map of type variables from this class to the given target class. 739 * If class A<X,Y> extends B<X,Y>, and B is declared as class B<M,N>, 740 * this returns the map {"X"->"M", "Y"->"N"}. There could be multiple intermediate 741 * classes between this class and the target class, and in some cases we could 742 * be substituting in a concrete class, e.g. class MyClass extends B<String,Number> 743 * would return the map {"java.lang.String"->"M", "java.lang.Number"->"N"}. 744 * 745 * If [reverse] is true, compute the reverse map: keys are the variables in 746 * the target and the values are the variables in the source. 747 */ 748 fun mapTypeVariables(target: ClassItem): Map<String, String> = codebase.unsupported() 749 750 /** 751 * Creates a constructor in this class 752 */ 753 fun createDefaultConstructor(): ConstructorItem = codebase.unsupported() 754 755 /** 756 * Creates a method corresponding to the given method signature in this class 757 */ 758 fun createMethod(template: MethodItem): MethodItem = codebase.unsupported() 759 760 fun addMethod(method: MethodItem): Unit = codebase.unsupported() 761 } 762 763 class VisitCandidate(val cls: ClassItem, private val visitor: ApiVisitor) { 764 public val innerClasses: Sequence<VisitCandidate> 765 private val constructors: Sequence<MethodItem> 766 private val methods: Sequence<MethodItem> 767 private val fields: Sequence<FieldItem> 768 private val enums: Sequence<FieldItem> 769 private val properties: Sequence<PropertyItem> 770 771 init { 772 val filterEmit = visitor.filterEmit 773 774 constructors = cls.constructors().asSequence() <lambda>null775 .filter { filterEmit.test(it) } 776 .sortedWith(MethodItem.comparator) 777 778 methods = cls.methods().asSequence() <lambda>null779 .filter { filterEmit.test(it) } 780 .sortedWith(MethodItem.comparator) 781 782 val fieldSequence = 783 if (visitor.inlineInheritedFields) { 784 cls.filteredFields(filterEmit, visitor.showUnannotated).asSequence() 785 } else { 786 cls.fields().asSequence() <lambda>null787 .filter { filterEmit.test(it) } 788 } 789 if (cls.isEnum()) { 790 fields = fieldSequence <lambda>null791 .filter { !it.isEnumConstant() } 792 .sortedWith(FieldItem.comparator) 793 enums = fieldSequence <lambda>null794 .filter { it.isEnumConstant() } <lambda>null795 .filter { filterEmit.test(it) } 796 .sortedWith(FieldItem.comparator) 797 } else { 798 fields = fieldSequence.sortedWith(FieldItem.comparator) 799 enums = emptySequence() 800 } 801 802 properties = if (cls.properties().isEmpty()) { 803 emptySequence() 804 } else { 805 cls.properties().asSequence() <lambda>null806 .filter { filterEmit.test(it) } 807 .sortedWith(PropertyItem.comparator) 808 } 809 810 innerClasses = cls.innerClasses() 811 .asSequence() 812 .sortedWith(ClassItem.classNameSorter()) <lambda>null813 .map { VisitCandidate(it, visitor) } 814 } 815 816 /** Whether the class body contains any Item's (other than inner Classes) */ nonEmptynull817 public fun nonEmpty(): Boolean { 818 return !(constructors.none() && methods.none() && enums.none() && fields.none() && properties.none()) 819 } 820 acceptnull821 fun accept() { 822 if (!visitor.include(this)) { 823 return 824 } 825 826 val emitThis = visitor.shouldEmitClass(this) 827 if (emitThis) { 828 if (!visitor.visitingPackage) { 829 visitor.visitingPackage = true 830 val pkg = cls.containingPackage() 831 visitor.visitItem(pkg) 832 visitor.visitPackage(pkg) 833 } 834 835 visitor.visitItem(cls) 836 visitor.visitClass(cls) 837 838 val sortedConstructors = if (visitor.methodComparator != null) { 839 constructors.sortedWith(visitor.methodComparator) 840 } else { 841 constructors 842 } 843 val sortedMethods = if (visitor.methodComparator != null) { 844 methods.sortedWith(visitor.methodComparator) 845 } else { 846 methods 847 } 848 val sortedFields = if (visitor.fieldComparator != null) { 849 fields.sortedWith(visitor.fieldComparator) 850 } else { 851 fields 852 } 853 854 for (constructor in sortedConstructors) { 855 constructor.accept(visitor) 856 } 857 858 for (method in sortedMethods) { 859 method.accept(visitor) 860 } 861 862 for (property in properties) { 863 property.accept(visitor) 864 } 865 for (enumConstant in enums) { 866 enumConstant.accept(visitor) 867 } 868 for (field in sortedFields) { 869 field.accept(visitor) 870 } 871 } 872 873 if (visitor.nestInnerClasses) { // otherwise done below 874 innerClasses.forEach { it.accept() } 875 } 876 877 if (emitThis) { 878 visitor.afterVisitClass(cls) 879 visitor.afterVisitItem(cls) 880 } 881 882 if (!visitor.nestInnerClasses) { 883 innerClasses.forEach { it.accept() } 884 } 885 } 886 } 887