1 /*
<lambda>null2  * Copyright (C) 2023 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 package com.android.hoststubgen.filters
17 
18 import com.android.hoststubgen.asm.ClassNodes
19 import com.android.hoststubgen.asm.getDirectOuterClassName
20 
21 /**
22  * This is used as the second last fallback filter. This filter propagates the class-wide policy
23  * (obtained from [outermostFilter]) to the fields and methods.
24  */
25 class ClassWidePolicyPropagatingFilter(
26     private val classes: ClassNodes,
27     fallback: OutputFilter,
28     ) : DelegatingFilter(fallback) {
29 
30     private fun getClassWidePolicy(className: String, resolve: Boolean): FilterPolicyWithReason? {
31         var currentClass = className
32 
33 
34         // If the class name is `a.b.c.A$B$C`, then we try to get the class wide policy
35         // from a.b.c.A$B$C, then a.b.c.A$B, and then a.b.c.A.
36         while (true) {
37             // Sometimes a class name has a `$` in it but not as a nest class name separator --
38             // e.g. class name like "MyClass$$". In this case, `MyClass$` may not actually be
39             // a class name.
40             // So before getting the class policy on a nonexistent class, which may cause an
41             // incorrect result, we make sure if className actually exists.
42             if (classes.hasClass(className)) {
43                 outermostFilter.getPolicyForClass(className).let { policy ->
44                     if (policy.policy.isClassWidePolicy) {
45                         val p = if (resolve) {
46                             policy.policy.resolveClassWidePolicy()
47                         } else {
48                             policy.policy
49                         }
50 
51                         return p.withReason(policy.reason)
52                             .wrapReason("class-wide in $currentClass")
53                     }
54                     // If the class's policy is remove, then remove it.
55                     if (policy.policy == FilterPolicy.Remove) {
56                         return FilterPolicy.Remove.withReason("class-wide in $currentClass")
57                     }
58                 }
59             }
60 
61             // Next, look at the outer class...
62             val outer = getDirectOuterClassName(currentClass)
63             if (outer == null) {
64                 return null
65             }
66             currentClass = outer
67         }
68     }
69 
70     override fun getPolicyForClass(className: String): FilterPolicyWithReason {
71         // If it's a nested class, use the outer class's policy.
72         getDirectOuterClassName(className)?.let { outerName ->
73             getClassWidePolicy(outerName, resolve = false)?.let { policy ->
74                 return policy
75             }
76         }
77 
78         return super.getPolicyForClass(className)
79     }
80 
81     override fun getPolicyForField(
82             className: String,
83             fieldName: String
84     ): FilterPolicyWithReason {
85         return getClassWidePolicy(className, resolve = true)
86                 ?: super.getPolicyForField(className, fieldName)
87     }
88 
89     override fun getPolicyForMethod(
90             className: String,
91             methodName: String,
92             descriptor: String
93     ): FilterPolicyWithReason {
94         return getClassWidePolicy(className, resolve = true)
95                 ?: super.getPolicyForMethod(className, methodName, descriptor)
96     }
97 }