make desugar resilient to unrelated lambdas being dumped while it runs
RELNOTES: None.
PiperOrigin-RevId: 178952440
diff --git a/src/test/java/com/google/devtools/build/android/desugar/BUILD b/src/test/java/com/google/devtools/build/android/desugar/BUILD
index c1e011a..69b30c2 100644
--- a/src/test/java/com/google/devtools/build/android/desugar/BUILD
+++ b/src/test/java/com/google/devtools/build/android/desugar/BUILD
@@ -1913,6 +1913,24 @@
],
)
+# Regression test for b/70415451
+genrule(
+ name = "desugar_guava_at_head",
+ srcs = [
+ "//third_party:guava-jars",
+ # Depend on Jacoco runtime in case testdata was built with coverage
+ # instrumentation
+ "//third_party/java/jacoco:blaze-agent",
+ "//tools/defaults:android_jar",
+ ],
+ outs = ["guava_at_head_desugared.jar"],
+ cmd = "$(location //src/tools/android/java/com/google/devtools/build/android/desugar:Desugar) " +
+ "-i $(location //third_party:guava-jars) -o $@ " +
+ "--bootclasspath_entry $(location //tools/defaults:android_jar)",
+ tags = ["no_windows"],
+ tools = ["//src/tools/android/java/com/google/devtools/build/android/desugar:Desugar"],
+)
+
java_binary(
name = "generate_lambda_with_constant_arguments",
srcs = ["Bug62060793TestDataGenerator.java"],
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassMaker.java b/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassMaker.java
index beaeb03..1f240ef 100644
--- a/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassMaker.java
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassMaker.java
@@ -14,18 +14,19 @@
package com.google.devtools.build.android.desugar;
import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterators;
import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.function.Predicate;
-import java.util.stream.Stream;
+import java.util.Set;
class LambdaClassMaker {
@@ -33,6 +34,7 @@
private final Path rootDirectory;
private final Map<Path, LambdaInfo> generatedClasses = new LinkedHashMap<>();
+ private final Set<Path> existingPaths = new HashSet<>();
public LambdaClassMaker(Path rootDirectory) {
checkArgument(
@@ -42,7 +44,9 @@
public void generateLambdaClass(String invokerInternalName, LambdaInfo lambdaInfo,
MethodHandle bootstrapMethod, ArrayList<Object> bsmArgs) throws IOException {
- // Invoking the bootstrap method will dump the generated class
+ // Invoking the bootstrap method will dump the generated class. Ignore any pre-existing
+ // matching files, which can come from desugar's implementation using classes being desugared.
+ existingPaths.addAll(findUnprocessed(invokerInternalName + "$$Lambda$"));
try {
bootstrapMethod.invokeWithArguments(bsmArgs);
} catch (Throwable e) {
@@ -50,8 +54,9 @@
+ invokerInternalName + " using " + bootstrapMethod + " with arguments " + bsmArgs, e);
}
- Path generatedClassFile = findOnlyUnprocessed(invokerInternalName + "$$Lambda$");
+ Path generatedClassFile = getOnlyElement(findUnprocessed(invokerInternalName + "$$Lambda$"));
generatedClasses.put(generatedClassFile, lambdaInfo);
+ existingPaths.add(generatedClassFile);
}
/**
@@ -64,7 +69,7 @@
return result;
}
- private Path findOnlyUnprocessed(String pathPrefix) throws IOException {
+ private ImmutableList<Path> findUnprocessed(String pathPrefix) throws IOException {
// pathPrefix is an internal class name prefix containing '/', but paths obtained on Windows
// will not contain '/' and searches will fail. So, construct an absolute path from the given
// string and use its string representation to find the file we need regardless of host
@@ -72,18 +77,14 @@
Path rootPathPrefix = rootDirectory.resolve(pathPrefix);
final String rootPathPrefixStr = rootPathPrefix.toString();
- // TODO(bazel-team): This could be much nicer with lambdas
- try (Stream<Path> paths =
- Files.list(rootPathPrefix.getParent())
- .filter(
- new Predicate<Path>() {
- @Override
- public boolean test(Path path) {
- return path.toString().startsWith(rootPathPrefixStr)
- && !generatedClasses.containsKey(path);
- }
- })) {
- return Iterators.getOnlyElement(paths.iterator());
+ if (!Files.exists(rootPathPrefix.getParent())) {
+ return ImmutableList.of();
}
+ return Files.list(rootPathPrefix.getParent())
+ .filter(
+ path ->
+ path.toString().startsWith(rootPathPrefixStr)
+ && !existingPaths.contains(path))
+ .collect(ImmutableList.toImmutableList());
}
}