| // 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 com.google.common.collect.Sets; |
| 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. |
| * |
| * <p>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 AppView<?> appView; |
| |
| private final Set<DexProgramClass> visited = Sets.newIdentityHashSet(); |
| |
| protected ProgramClassVisitor(AppView<?> appView) { |
| this.appView = appView; |
| } |
| |
| private void accept(DexType type) { |
| DexProgramClass clazz = appView.app().programDefinitionFor(type); |
| if (clazz != null) { |
| accept(clazz); |
| } |
| } |
| |
| private void accept(DexTypeList types) { |
| for (DexType type : types.values) { |
| accept(type); |
| } |
| } |
| |
| private void accept(DexProgramClass clazz) { |
| if (visited.add(clazz)) { |
| if (clazz.hasSuperType()) { |
| accept(clazz.getSuperType()); |
| } |
| accept(clazz.getInterfaces()); |
| visit(clazz); |
| } |
| } |
| |
| public void run(DexProgramClass[] classes) { |
| for (DexProgramClass clazz : classes) { |
| accept(clazz); |
| } |
| } |
| |
| /** Called for each class defined in the application. */ |
| public abstract void visit(DexProgramClass clazz); |
| } |