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