|  | // Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | package com.android.tools.r8.optimize.utils; | 
|  |  | 
|  | import com.android.tools.r8.graph.AppInfoWithClassHierarchy; | 
|  | import com.android.tools.r8.graph.AppView; | 
|  | import com.android.tools.r8.graph.ClasspathOrLibraryClass; | 
|  | import com.android.tools.r8.graph.DexClass; | 
|  | import com.android.tools.r8.graph.DexClassAndMethod; | 
|  | import com.android.tools.r8.utils.collections.DexMethodSignatureSet; | 
|  | import java.util.Map; | 
|  |  | 
|  | public abstract class NonProgramMethodsCollection { | 
|  |  | 
|  | private final AppView<? extends AppInfoWithClassHierarchy> appView; | 
|  | private final Map<DexClass, DexMethodSignatureSet> nonProgramMethods; | 
|  |  | 
|  | NonProgramMethodsCollection( | 
|  | AppView<? extends AppInfoWithClassHierarchy> appView, | 
|  | Map<DexClass, DexMethodSignatureSet> nonProgramMethods) { | 
|  | this.appView = appView; | 
|  | this.nonProgramMethods = nonProgramMethods; | 
|  | } | 
|  |  | 
|  | public DexMethodSignatureSet getOrComputeNonProgramMethods(ClasspathOrLibraryClass clazz) { | 
|  | return getOrComputeNonProgramMethods(clazz.asDexClass()); | 
|  | } | 
|  |  | 
|  | // Parameter is typed as DexClass to account for program classes above classpath or library | 
|  | // classes. | 
|  | private DexMethodSignatureSet getOrComputeNonProgramMethods(DexClass clazz) { | 
|  | DexMethodSignatureSet nonProgramMethodsOnClass = nonProgramMethods.get(clazz); | 
|  | return nonProgramMethodsOnClass != null | 
|  | ? nonProgramMethodsOnClass | 
|  | : computeNonProgramMethods(clazz); | 
|  | } | 
|  |  | 
|  | private DexMethodSignatureSet computeNonProgramMethods(DexClass clazz) { | 
|  | DexMethodSignatureSet nonProgramMethodsOnClass = DexMethodSignatureSet.create(); | 
|  | clazz.forEachImmediateSuperClassMatching( | 
|  | appView, | 
|  | (supertype, superclass) -> superclass != null, | 
|  | (supertype, superclass) -> | 
|  | nonProgramMethodsOnClass.addAll(getOrComputeNonProgramMethods(superclass))); | 
|  | if (!clazz.isProgramClass()) { | 
|  | clazz.forEachClassMethod( | 
|  | method -> { | 
|  | if (test(method)) { | 
|  | nonProgramMethodsOnClass.add(method.getMethodSignature()); | 
|  | } | 
|  | }); | 
|  | } | 
|  | nonProgramMethods.put(clazz, nonProgramMethodsOnClass); | 
|  | return nonProgramMethodsOnClass; | 
|  | } | 
|  |  | 
|  | public abstract boolean test(DexClassAndMethod method); | 
|  | } |