blob: f6fcb69076c1e9f65abf5fec2ead8de5dd402fee [file] [log] [blame]
// Copyright (c) 2020, 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.tracereferences;
import static com.android.tools.r8.utils.FileUtils.isArchive;
import com.android.tools.r8.ArchiveClassFileProvider;
import com.android.tools.r8.ClassFileResourceProvider;
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.Keep;
import com.android.tools.r8.ProgramResourceProvider;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.tracereferences.TraceReferencesCommandParser.OutputFormat;
import com.android.tools.r8.utils.ArchiveResourceProvider;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@Keep
public class TraceReferencesCommand {
private final boolean printHelp;
private final boolean printVersion;
private final DiagnosticsHandler diagnosticsHandler;
private final ImmutableList<ClassFileResourceProvider> library;
private final ImmutableList<ClassFileResourceProvider> traceTarget;
private final ImmutableList<ProgramResourceProvider> traceSource;
private final StringConsumer output;
private final OutputFormat outputFormat;
TraceReferencesCommand(
boolean printHelp,
boolean printVersion,
DiagnosticsHandler diagnosticsHandler,
ImmutableList<ClassFileResourceProvider> library,
ImmutableList<ClassFileResourceProvider> traceTarget,
ImmutableList<ProgramResourceProvider> traceSource,
StringConsumer output,
OutputFormat outputFormat) {
this.printHelp = printHelp;
this.printVersion = printVersion;
this.diagnosticsHandler = diagnosticsHandler;
this.library = library;
this.traceTarget = traceTarget;
this.traceSource = traceSource;
this.output = output;
this.outputFormat = outputFormat;
}
/**
* Utility method for obtaining a <code>ReferenceTraceCommand.Builder</code>.
*
* @param diagnosticsHandler The diagnostics handler for consuming messages.
*/
public static Builder builder(DiagnosticsHandler diagnosticsHandler) {
return new Builder(diagnosticsHandler);
}
/**
* Utility method for obtaining a <code>ReferenceTraceCommand.Builder</code> with a default
* diagnostics handler.
*/
public static Builder builder() {
return new Builder(new DiagnosticsHandler() {});
}
public static Builder parse(String[] args, Origin origin) {
return TraceReferencesCommandParser.parse(args, origin);
}
public static Builder parse(String[] args, Origin origin, DiagnosticsHandler diagnosticsHandler) {
return TraceReferencesCommandParser.parse(args, origin, diagnosticsHandler);
}
public boolean isPrintHelp() {
return printHelp;
}
public boolean isPrintVersion() {
return printVersion;
}
public static class Builder {
private boolean printHelp = false;
private boolean printVersion = false;
private final DiagnosticsHandler diagnosticsHandler;
private final ImmutableList.Builder<ClassFileResourceProvider> libraryBuilder =
ImmutableList.builder();
private final ImmutableList.Builder<ClassFileResourceProvider> traceTargetBuilder =
ImmutableList.builder();
private final ImmutableList.Builder<ProgramResourceProvider> traceSourceBuilder =
ImmutableList.builder();
private StringConsumer output;
private OutputFormat outputFormat = TraceReferencesCommandParser.OutputFormat.PRINTUSAGE;
private Builder(DiagnosticsHandler diagnosticsHandler) {
this.diagnosticsHandler = diagnosticsHandler;
}
public Builder setPrintHelp(boolean printHelp) {
this.printHelp = printHelp;
return this;
}
/** True if the print-version flag is enabled. */
public boolean isPrintVersion() {
return printVersion;
}
/** Set the value of the print-version flag. */
public Builder setPrintVersion(boolean printVersion) {
this.printVersion = printVersion;
return this;
}
private void addLibraryOrTargetFile(
Path file, ImmutableList.Builder<ClassFileResourceProvider> builder) {
if (!Files.exists(file)) {
PathOrigin pathOrigin = new PathOrigin(file);
NoSuchFileException noSuchFileException = new NoSuchFileException(file.toString());
error(new ExceptionDiagnostic(noSuchFileException, pathOrigin));
}
if (isArchive(file)) {
try {
ArchiveClassFileProvider provider = new ArchiveClassFileProvider(file);
builder.add(provider);
} catch (IOException e) {
error(new ExceptionDiagnostic(e, new PathOrigin(file)));
}
} else {
error(new StringDiagnostic("Unsupported source file type", new PathOrigin(file)));
}
}
private void addSourceFile(Path file) {
if (!Files.exists(file)) {
PathOrigin pathOrigin = new PathOrigin(file);
NoSuchFileException noSuchFileException = new NoSuchFileException(file.toString());
error(new ExceptionDiagnostic(noSuchFileException, pathOrigin));
}
if (isArchive(file)) {
traceSourceBuilder.add(ArchiveResourceProvider.fromArchive(file, false));
} else {
error(new StringDiagnostic("Unsupported source file type", new PathOrigin(file)));
}
}
public Builder addLibraryResourceProvider(ClassFileResourceProvider provider) {
libraryBuilder.add(provider);
return this;
}
public Builder addLibraryFiles(Path... files) {
addLibraryFiles(Arrays.asList(files));
return this;
}
public Builder addLibraryFiles(Collection<Path> files) {
for (Path file : files) {
addLibraryOrTargetFile(file, libraryBuilder);
}
return this;
}
public Builder addTargetFiles(Path... files) {
addTargetFiles(Arrays.asList(files));
return this;
}
public Builder addTargetFiles(Collection<Path> files) {
for (Path file : files) {
addLibraryOrTargetFile(file, traceTargetBuilder);
}
return this;
}
public Builder addSourceFiles(Path... files) {
addSourceFiles(Arrays.asList(files));
return this;
}
public Builder addSourceFiles(Collection<Path> files) {
for (Path file : files) {
addSourceFile(file);
}
return this;
}
Builder setOutputPath(Path output) {
this.output = new StringConsumer.FileConsumer(output);
return this;
}
Builder setOutputFormat(OutputFormat outputFormat) {
this.outputFormat = outputFormat;
return this;
}
public final TraceReferencesCommand build() {
ImmutableList<ClassFileResourceProvider> traceTarget = traceTargetBuilder.build();
ImmutableList<ProgramResourceProvider> traceSource = traceSourceBuilder.build();
return new TraceReferencesCommand(
printHelp,
printVersion,
diagnosticsHandler,
libraryBuilder.build(),
traceTarget,
traceSource,
output,
outputFormat);
}
void error(Diagnostic diagnostic) {
diagnosticsHandler.error(diagnostic);
// For now all errors are fatal.
throw new TraceReferencesAbortException();
}
}
DiagnosticsHandler getDiagnosticsHandler() {
return diagnosticsHandler;
}
List<ClassFileResourceProvider> getLibrary() {
return library;
}
List<ClassFileResourceProvider> getTarget() {
return traceTarget;
}
List<ProgramResourceProvider> getSource() {
return traceSource;
}
StringConsumer getOutput() {
return output;
}
OutputFormat getOutputFormat() {
return outputFormat;
}
}