• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 allowFromJar: Boolean = true,
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         if (!allowFromJar && member.isFromClassPath()) {
57             return false
58         }
59 
60         var visible = member.isPublic || member.isProtected // TODO: Should this use checkLevel instead?
61         var hidden = member.hidden
62         if (!visible || hidden) {
63             return false
64         }
65 
66         var hasShowAnnotation = ignoreShown || member.hasShowAnnotation()
67         var docOnly = member.docOnly
68         var removed = member.removed
69 
70         var clazz: ClassItem? = when (member) {
71             is MemberItem -> member.containingClass()
72             is ClassItem -> member
73             else -> null
74         }
75 
76         if (clazz != null) {
77             var pkg: PackageItem? = clazz.containingPackage()
78             while (pkg != null) {
79                 hidden = hidden or pkg.hidden
80                 docOnly = docOnly or pkg.docOnly
81                 removed = removed or pkg.removed
82                 pkg = pkg.containingPackage()
83             }
84         }
85         while (clazz != null) {
86             visible = visible and (clazz.isPublic || clazz.isProtected)
87             hasShowAnnotation = hasShowAnnotation or (ignoreShown || clazz.hasShowAnnotation())
88             hidden = hidden or clazz.hidden
89             docOnly = docOnly or clazz.docOnly
90             removed = removed or clazz.removed
91             clazz = clazz.containingClass()
92         }
93 
94         if (ignoreRemoved) {
95             removed = matchRemoved
96         }
97 
98         if (docOnly && includeDocOnly) {
99             docOnly = false
100         }
101 
102         return visible && hasShowAnnotation && !hidden && !docOnly && removed == matchRemoved
103     }
104 }
105