• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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