blob: 4eca4e10ebd988e60ea72c95d00d47bb43083ff3 [file] [log] [blame]
// Copyright (c) 2022, 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 static com.android.tools.r8.graph.ClassResolutionResult.NoResolutionResult.noResult;
import java.util.function.Consumer;
public interface ClassResolutionResult {
boolean hasClassResolutionResult();
DexClass toSingleClassWithProgramOverLibrary();
void forEachClassResolutionResult(Consumer<DexClass> consumer);
static Builder builder() {
return new Builder();
}
class Builder {
private ProgramOrClasspathClass programOrClasspathClass;
private DexLibraryClass libraryClass;
public Builder add(DexProgramClass programClass) {
assert this.programOrClasspathClass == null;
this.programOrClasspathClass = programClass;
return this;
}
public Builder add(DexClasspathClass classpathClass) {
assert this.programOrClasspathClass == null;
this.programOrClasspathClass = classpathClass;
return this;
}
public Builder add(DexLibraryClass libraryClass) {
assert this.libraryClass == null;
this.libraryClass = libraryClass;
return this;
}
public Builder add(ProgramOrClasspathClass programOrClasspathClass) {
assert this.programOrClasspathClass == null;
this.programOrClasspathClass = programOrClasspathClass;
return this;
}
public ClassResolutionResult build() {
if (programOrClasspathClass == null && libraryClass == null) {
return noResult();
} else if (programOrClasspathClass == null) {
return libraryClass;
} else if (libraryClass == null) {
return programOrClasspathClass;
} else if (programOrClasspathClass.isProgramClass()) {
return new ProgramAndLibraryClassResolutionResult(
programOrClasspathClass.asProgramClass(), libraryClass);
} else {
assert programOrClasspathClass.isClasspathClass();
return new ClasspathAndLibraryClassResolutionResult(
programOrClasspathClass.asClasspathClass(), libraryClass);
}
}
}
class NoResolutionResult implements ClassResolutionResult {
private static final NoResolutionResult NO_RESULT = new NoResolutionResult();
static ClassResolutionResult noResult() {
return NO_RESULT;
}
@Override
public boolean hasClassResolutionResult() {
return false;
}
@Override
public DexClass toSingleClassWithProgramOverLibrary() {
return null;
}
@Override
public void forEachClassResolutionResult(Consumer<DexClass> consumer) {
// Intentionally empty
}
}
abstract class MultipleClassResolutionResult<T extends DexClass>
implements ClassResolutionResult {
protected final T programOrClasspathClass;
protected final DexLibraryClass libraryClass;
public MultipleClassResolutionResult(T programOrClasspathClass, DexLibraryClass libraryClass) {
this.programOrClasspathClass = programOrClasspathClass;
this.libraryClass = libraryClass;
}
@Override
public boolean hasClassResolutionResult() {
return true;
}
@Override
public void forEachClassResolutionResult(Consumer<DexClass> consumer) {
consumer.accept(programOrClasspathClass);
consumer.accept(libraryClass);
}
}
class ProgramAndLibraryClassResolutionResult
extends MultipleClassResolutionResult<DexProgramClass> {
public ProgramAndLibraryClassResolutionResult(
DexProgramClass programClass, DexLibraryClass libraryClass) {
super(programClass, libraryClass);
}
@Override
public DexClass toSingleClassWithProgramOverLibrary() {
return programOrClasspathClass;
}
}
class ClasspathAndLibraryClassResolutionResult
extends MultipleClassResolutionResult<DexClasspathClass> {
public ClasspathAndLibraryClassResolutionResult(
DexClasspathClass classpathClass, DexLibraryClass libraryClass) {
super(classpathClass, libraryClass);
}
@Override
public DexClass toSingleClassWithProgramOverLibrary() {
return libraryClass;
}
}
}