summaryrefslogtreecommitdiff
path: root/java/com/google/devtools/build/android/desugar/Desugar.java
diff options
context:
space:
mode:
authorkmb <kmb@google.com>2017-10-03 02:14:25 +0200
committerColin Cross <ccross@android.com>2017-10-24 12:20:33 -0700
commit59adc3acdd6a3dd50fa2ffae0cba2370209c86d6 (patch)
tree1e827642a3d559eca344a4a237625d708a2dda13 /java/com/google/devtools/build/android/desugar/Desugar.java
parent5846f33fd5435036751ecf36331386cf6fe655b5 (diff)
downloaddesugar-59adc3acdd6a3dd50fa2ffae0cba2370209c86d6.tar.gz
add flags to desugar to emit metadata that can be used for double-checking correctness of default and static interface desugaring.
RELNOTES: none PiperOrigin-RevId: 170779637 GitOrigin-RevId: bdb12ceeb7c23d7d2293e8006d0aa7127a91b973 Change-Id: I6969cc42323b5299a90af9e8084658e9f654825f
Diffstat (limited to 'java/com/google/devtools/build/android/desugar/Desugar.java')
-rw-r--r--java/com/google/devtools/build/android/desugar/Desugar.java76
1 files changed, 72 insertions, 4 deletions
diff --git a/java/com/google/devtools/build/android/desugar/Desugar.java b/java/com/google/devtools/build/android/desugar/Desugar.java
index 31c362e..07702fe 100644
--- a/java/com/google/devtools/build/android/desugar/Desugar.java
+++ b/java/com/google/devtools/build/android/desugar/Desugar.java
@@ -176,6 +176,26 @@ class Desugar {
public int minSdkVersion;
@Option(
+ name = "emit_dependency_metadata_as_needed",
+ defaultValue = "false",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.UNKNOWN},
+ help = "Whether to emit META-INF/desugar_deps as needed for later consistency checking."
+ )
+ public boolean emitDependencyMetadata;
+
+ @Option(
+ name = "best_effort_tolerate_missing_deps",
+ defaultValue = "true",
+ category = "misc",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.UNKNOWN},
+ help = "Whether to tolerate missing dependencies on the classpath in some cases. You should "
+ + "strive to set this flag to false."
+ )
+ public boolean tolerateMissingDependencies;
+
+ @Option(
name = "desugar_interface_method_bodies_if_needed",
defaultValue = "true",
category = "misc",
@@ -316,6 +336,7 @@ class Desugar {
try (OutputFileProvider outputFileProvider = toOutputFileProvider(outputPath);
InputFileProvider inputFiles = toInputFileProvider(inputPath)) {
+ DependencyCollector depsCollector = createDepsCollector();
IndexedInputs indexedInputFiles = new IndexedInputs(ImmutableList.of(inputFiles));
// Prepend classpath with input file itself so LambdaDesugaring can load classes with
// lambdas.
@@ -344,6 +365,7 @@ class Desugar {
outputFileProvider,
loader,
classpathReader,
+ depsCollector,
bootclasspathReader,
interfaceLambdaMethodCollector);
@@ -351,12 +373,18 @@ class Desugar {
outputFileProvider,
loader,
classpathReader,
+ depsCollector,
bootclasspathReader,
interfaceLambdaMethodCollector.build(),
bridgeMethodReader);
desugarAndWriteGeneratedClasses(outputFileProvider);
copyThrowableExtensionClass(outputFileProvider);
+
+ byte[] depsInfo = depsCollector.toByteArray();
+ if (depsInfo != null) {
+ outputFileProvider.write(OutputFileProvider.DESUGAR_DEPS_FILENAME, depsInfo);
+ }
}
ImmutableMap<Path, LambdaInfo> lambdasLeftBehind = lambdas.drain();
@@ -365,6 +393,32 @@ class Desugar {
checkState(generatedLeftBehind.isEmpty(), "Didn't process %s", generatedLeftBehind.keySet());
}
+ /**
+ * Returns a dependency collector for use with a single input Jar. If
+ * {@link DesugarOptions#emitDependencyMetadata} is set, this method instantiates the collector
+ * reflectively to allow compiling and using the desugar tool without this mechanism.
+ */
+ private DependencyCollector createDepsCollector() {
+ if (options.emitDependencyMetadata) {
+ try {
+ return (DependencyCollector)
+ Thread.currentThread()
+ .getContextClassLoader()
+ .loadClass(
+ "com.google.devtools.build.android.desugar.dependencies.MetadataCollector")
+ .getConstructor(Boolean.TYPE)
+ .newInstance(options.tolerateMissingDependencies);
+ } catch (ReflectiveOperationException
+ | SecurityException e) {
+ throw new IllegalStateException("Can't emit desugaring metadata as requested");
+ }
+ } else if (options.tolerateMissingDependencies) {
+ return DependencyCollector.NoWriteCollectors.NOOP;
+ } else {
+ return DependencyCollector.NoWriteCollectors.FAIL_ON_MISSING;
+ }
+ }
+
private void copyThrowableExtensionClass(OutputFileProvider outputFileProvider) {
if (allowTryWithResources || options.desugarTryWithResourcesOmitRuntimeClasses) {
// try-with-resources statements are okay in the output jar.
@@ -390,10 +444,15 @@ class Desugar {
OutputFileProvider outputFileProvider,
ClassLoader loader,
@Nullable ClassReaderFactory classpathReader,
+ DependencyCollector depsCollector,
ClassReaderFactory bootclasspathReader,
Builder<String> interfaceLambdaMethodCollector)
throws IOException {
for (String filename : inputFiles) {
+ if (OutputFileProvider.DESUGAR_DEPS_FILENAME.equals(filename)) {
+ // TODO(kmb): rule out that this happens or merge input file with what's in depsCollector
+ continue; // skip as we're writing a new file like this at the end or don't want it
+ }
try (InputStream content = inputFiles.getInputStream(filename)) {
// We can write classes uncompressed since they need to be converted to .dex format
// for Android anyways. Resources are written as they were in the input jar to avoid
@@ -405,6 +464,7 @@ class Desugar {
createClassVisitorsForClassesInInputs(
loader,
classpathReader,
+ depsCollector,
bootclasspathReader,
interfaceLambdaMethodCollector,
writer,
@@ -431,6 +491,7 @@ class Desugar {
OutputFileProvider outputFileProvider,
ClassLoader loader,
@Nullable ClassReaderFactory classpathReader,
+ DependencyCollector depsCollector,
ClassReaderFactory bootclasspathReader,
ImmutableSet<String> interfaceLambdaMethods,
@Nullable ClassReaderFactory bridgeMethodReader)
@@ -460,6 +521,7 @@ class Desugar {
createClassVisitorsForDumpedLambdaClasses(
loader,
classpathReader,
+ depsCollector,
bootclasspathReader,
interfaceLambdaMethods,
bridgeMethodReader,
@@ -499,6 +561,7 @@ class Desugar {
private ClassVisitor createClassVisitorsForDumpedLambdaClasses(
ClassLoader loader,
@Nullable ClassReaderFactory classpathReader,
+ DependencyCollector depsCollector,
ClassReaderFactory bootclasspathReader,
ImmutableSet<String> interfaceLambdaMethods,
@Nullable ClassReaderFactory bridgeMethodReader,
@@ -523,9 +586,11 @@ class Desugar {
visitor = new Java7Compatibility(visitor, (ClassReaderFactory) null);
if (options.desugarInterfaceMethodBodiesIfNeeded) {
visitor =
- new DefaultMethodClassFixer(visitor, classpathReader, bootclasspathReader, loader);
+ new DefaultMethodClassFixer(
+ visitor, classpathReader, depsCollector, bootclasspathReader, loader);
visitor =
- new InterfaceDesugaring(visitor, bootclasspathReader, store, options.legacyJacocoFix);
+ new InterfaceDesugaring(
+ visitor, depsCollector, bootclasspathReader, store, options.legacyJacocoFix);
}
}
visitor =
@@ -553,6 +618,7 @@ class Desugar {
private ClassVisitor createClassVisitorsForClassesInInputs(
ClassLoader loader,
@Nullable ClassReaderFactory classpathReader,
+ DependencyCollector depsCollector,
ClassReaderFactory bootclasspathReader,
Builder<String> interfaceLambdaMethodCollector,
UnprefixingClassWriter writer,
@@ -574,9 +640,11 @@ class Desugar {
visitor = new Java7Compatibility(visitor, classpathReader);
if (options.desugarInterfaceMethodBodiesIfNeeded) {
visitor =
- new DefaultMethodClassFixer(visitor, classpathReader, bootclasspathReader, loader);
+ new DefaultMethodClassFixer(
+ visitor, classpathReader, depsCollector, bootclasspathReader, loader);
visitor =
- new InterfaceDesugaring(visitor, bootclasspathReader, store, options.legacyJacocoFix);
+ new InterfaceDesugaring(
+ visitor, depsCollector, bootclasspathReader, store, options.legacyJacocoFix);
}
}
// LambdaDesugaring is relatively expensive, so check first whether we need it. Additionally,