| // 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); |
| } |
| } |
| } |
| } |