blob: 06d094352011a5adffa05fff98163fc8a384b46a [file] [log] [blame]
// 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);
}