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