|  | // Copyright (c) 2019, 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.graph; | 
|  |  | 
|  | import com.google.common.collect.Iterables; | 
|  | import java.util.Objects; | 
|  | import java.util.function.Function; | 
|  |  | 
|  | public class BottomUpClassHierarchyTraversal<T extends DexClass> | 
|  | extends ClassHierarchyTraversal<T, BottomUpClassHierarchyTraversal<T>> { | 
|  |  | 
|  | private final Function<T, Iterable<T>> immediateSubtypesProvider; | 
|  |  | 
|  | private BottomUpClassHierarchyTraversal( | 
|  | AppView<? extends AppInfoWithClassHierarchy> appView, | 
|  | Function<T, Iterable<T>> immediateSubtypesProvider, | 
|  | Scope scope) { | 
|  | super(appView, scope); | 
|  | this.immediateSubtypesProvider = immediateSubtypesProvider; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns a visitor that can be used to visit all the classes (including class path and library | 
|  | * classes) that are reachable from a given set of sources. | 
|  | */ | 
|  | public static BottomUpClassHierarchyTraversal<DexClass> forAllClasses( | 
|  | AppView<? extends AppInfoWithClassHierarchy> appView, SubtypingInfo subtypingInfo) { | 
|  | return new BottomUpClassHierarchyTraversal<>( | 
|  | appView, | 
|  | clazz -> | 
|  | Iterables.filter( | 
|  | Iterables.transform( | 
|  | subtypingInfo.allImmediateSubtypes(clazz.getType()), | 
|  | appView::contextIndependentDefinitionFor), | 
|  | Objects::nonNull), | 
|  | Scope.ALL_CLASSES); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns a visitor that can be used to visit all the program classes that are reachable from a | 
|  | * given set of sources. | 
|  | */ | 
|  | public static BottomUpClassHierarchyTraversal<DexProgramClass> forProgramClasses( | 
|  | AppView<? extends AppInfoWithClassHierarchy> appView, | 
|  | ImmediateProgramSubtypingInfo immediateSubtypingInfo) { | 
|  | return forProgramClasses(appView, immediateSubtypingInfo::getSubclasses); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns a visitor that can be used to visit all the program classes that are reachable from a | 
|  | * given set of sources. | 
|  | */ | 
|  | public static BottomUpClassHierarchyTraversal<DexProgramClass> forProgramClasses( | 
|  | AppView<? extends AppInfoWithClassHierarchy> appView, | 
|  | Function<DexProgramClass, Iterable<DexProgramClass>> immediateSubtypesProvider) { | 
|  | return new BottomUpClassHierarchyTraversal<>( | 
|  | appView, immediateSubtypesProvider, Scope.ONLY_PROGRAM_CLASSES); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | BottomUpClassHierarchyTraversal<T> self() { | 
|  | return this; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | void addDependentsToWorklist(DexClass clazz) { | 
|  | @SuppressWarnings("unchecked") | 
|  | T clazzWithTypeT = (T) clazz; | 
|  |  | 
|  | if (excludeInterfaces && clazzWithTypeT.isInterface()) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (visited.contains(clazzWithTypeT)) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | worklist.addFirst(clazzWithTypeT); | 
|  |  | 
|  | // Add subtypes to worklist. | 
|  | for (DexClass subclass : immediateSubtypesProvider.apply(clazzWithTypeT)) { | 
|  | if (scope != Scope.ONLY_PROGRAM_CLASSES || subclass.isProgramClass()) { | 
|  | addDependentsToWorklist(subclass); | 
|  | } | 
|  | } | 
|  | } | 
|  | } |