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