1 package com.android.tools.metalava.doclava1
2 
3 import com.android.tools.metalava.Options
4 import com.android.tools.metalava.model.ClassItem
5 import com.android.tools.metalava.model.Item
6 import com.android.tools.metalava.model.MemberItem
7 import com.android.tools.metalava.model.PackageItem
8 import com.android.tools.metalava.options
9 import java.util.function.Predicate
10 
11 // Ported from doclava1
12 
13 /**
14  * Predicate that decides if the given member should be considered part of an
15  * API surface area. To make the most accurate decision, it searches for
16  * signals on the member, all containing classes, and all containing packages.
17  */
18 class ApiPredicate(
19     /**
20      * Set if the value of [MemberItem.hasShowAnnotation] should be
21      * ignored. That is, this predicate will assume that all encountered members
22      * match the "shown" requirement.
23      *
24      * This is typically useful when generating "current.txt", when no
25      * [Options.showAnnotations] have been defined.
26      */
27     val ignoreShown: Boolean = options.showUnannotated,
28 
29     /**
30      * Set if the value of [MemberItem.removed] should be ignored.
31      * That is, this predicate will assume that all encountered members match
32      * the "removed" requirement.
33      *
34      * This is typically useful when generating "removed.txt", when it's okay to
35      * reference both current and removed APIs.
36      */
37     private val ignoreRemoved: Boolean = false,
38 
39     /**
40      * Set what the value of [MemberItem.removed] must be equal to in
41      * order for a member to match.
42      *
43      * This is typically useful when generating "removed.txt", when you only
44      * want to match members that have actually been removed.
45      */
46     private val matchRemoved: Boolean = false,
47 
48     /** Whether we allow matching items loaded from jar files instead of sources */
49     private val allowClassesFromClasspath: Boolean = options.allowClassesFromClasspath,
50 
51     /** Whether we should include doc-only items */
52     private val includeDocOnly: Boolean = false
53 ) : Predicate<Item> {
54 
testnull55     override fun test(member: Item): Boolean {
56         // Type Parameter references (e.g. T) aren't actual types, skip all visibility checks
57         if (member is ClassItem && member.isTypeParameter) {
58             return true
59         }
60 
61         if (!allowClassesFromClasspath && member.isFromClassPath()) {
62             return false
63         }
64 
65         var visible = member.isPublic || member.isProtected // TODO: Should this use checkLevel instead?
66         var hidden = member.hidden
67         if (!visible || hidden) {
68             return false
69         }
70 
71         var hasShowAnnotation = ignoreShown || member.hasShowAnnotation()
72         var docOnly = member.docOnly
73         var removed = member.removed
74 
75         var clazz: ClassItem? = when (member) {
76             is MemberItem -> member.containingClass()
77             is ClassItem -> member
78             else -> null
79         }
80 
81         if (clazz != null) {
82             var pkg: PackageItem? = clazz.containingPackage()
83             while (pkg != null) {
84                 hidden = hidden or pkg.hidden
85                 docOnly = docOnly or pkg.docOnly
86                 removed = removed or pkg.removed
87                 pkg = pkg.containingPackage()
88             }
89         }
90         while (clazz != null) {
91             visible = visible and (clazz.isPublic || clazz.isProtected)
92             hasShowAnnotation = hasShowAnnotation or (ignoreShown || clazz.hasShowAnnotation())
93             hidden = hidden or clazz.hidden
94             docOnly = docOnly or clazz.docOnly
95             removed = removed or clazz.removed
96             clazz = clazz.containingClass()
97         }
98 
99         if (ignoreRemoved) {
100             removed = matchRemoved
101         }
102 
103         if (docOnly && includeDocOnly) {
104             docOnly = false
105         }
106 
107         return visible && hasShowAnnotation && !hidden && !docOnly && removed == matchRemoved
108     }
109 }
110