blob: 341403774f908251e03c49bff12f1a289ddf4951 [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 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);
}