aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar kmb <kmb@google.com>2017-12-13 13:52:35 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2017-12-13 13:55:15 -0800
commit817b535d92ee7fdb4740e2a99505ab10d4b54a0d (patch)
tree449b1a158bd05e2ea9f566b04a39cc25e4adcf75
parent0cb96d1e3db39cb3054d2bcedc8e959ec60b0d45 (diff)
make desugar resilient to unrelated lambdas being dumped while it runs
RELNOTES: None. PiperOrigin-RevId: 178952440
-rw-r--r--src/test/java/com/google/devtools/build/android/desugar/BUILD18
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassMaker.java37
2 files changed, 37 insertions, 18 deletions
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 c1e011a3bc..69b30c2287 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 @@ genrule(
],
)
+# 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 beaeb0356f..1f240ef507 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 @@ class LambdaClassMaker {
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 @@ class LambdaClassMaker {
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 @@ class LambdaClassMaker {
+ 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 @@ class LambdaClassMaker {
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 @@ class LambdaClassMaker {
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());
}
}