| // Copyright (c) 2016, 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 java.util.HashSet; |
| import java.util.Set; |
| |
| /** |
| * Implements traversal of the class hierarchy in topological order. A class is visited after its |
| * super class and its interfaces are visited. Only visits program classes and does NOT visit |
| * classpath, nor library classes. |
| * |
| * NOTE: The visiting is processed by traversing program classes only, which means that |
| * in presence of classpath it is NOT guaranteed that class C is visited before class D |
| * if there exists a classpath class X in class hierarchy between C and D, like: |
| * |
| * <pre> |
| * class ProgramClassS {} |
| * class ClasspathClassX extends ProgramClassS {} |
| * class ProgramClassD extends ClasspathClassX {} |
| * </pre> |
| * |
| * The above consideration does not apply to library classes, since we assume library |
| * classes never extend or implement program/classpath class. |
| */ |
| public abstract class ProgramClassVisitor { |
| |
| final DexApplication application; |
| private final Set<DexItem> visited = new HashSet<>(); |
| |
| protected ProgramClassVisitor(DexApplication application) { |
| this.application = application; |
| } |
| |
| private void accept(DexType type) { |
| if (type == null || visited.contains(type)) { |
| return; |
| } |
| DexClass clazz = application.programDefinitionFor(type); |
| if (clazz != null) { |
| accept(clazz); |
| return; |
| } |
| visit(type); |
| visited.add(type); |
| } |
| |
| private void accept(DexTypeList types) { |
| for (DexType type : types.values) { |
| accept(type); |
| } |
| } |
| |
| private void accept(DexClass clazz) { |
| if (visited.contains(clazz)) { |
| return; |
| } |
| accept(clazz.superType); |
| accept(clazz.interfaces); |
| visit(clazz); |
| visited.add(clazz); |
| } |
| |
| public void run(DexProgramClass[] classes) { |
| for (DexProgramClass clazz : classes) { |
| accept(clazz); |
| } |
| } |
| |
| public void run(Iterable<DexProgramClass> classes) { |
| for (DexProgramClass clazz : classes) { |
| accept(clazz); |
| } |
| } |
| |
| public void run() { |
| run(application.classes()); |
| } |
| |
| /** |
| * Called for each library class used in the class hierarchy. A library class is a class that is |
| * not present in the application. |
| */ |
| public abstract void visit(DexType type); |
| |
| /** |
| * Called for each class defined in the application. |
| */ |
| public abstract void visit(DexClass clazz); |
| } |