Version 1.4.98
Cherry-pick: Issue warning if -injars or -libraryjars are given non-archive arguments.
CL: https://r8-review.googlesource.com/c/r8/+/38549
Cherry-pick: Extend testing utilities for diagnostic inspection.
CL: https://r8-review.googlesource.com/c/r8/+/38557
Bug: 133122577
Change-Id: I075fd6488f3800ca4d255d12d133197f680b2a50
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 6fa660a..3b51d48 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "1.4.97";
+ public static final String LABEL = "1.4.98";
private Version() {
}
diff --git a/src/main/java/com/android/tools/r8/shaking/FilteredClassPath.java b/src/main/java/com/android/tools/r8/shaking/FilteredClassPath.java
index 9badf35..9bef056 100644
--- a/src/main/java/com/android/tools/r8/shaking/FilteredClassPath.java
+++ b/src/main/java/com/android/tools/r8/shaking/FilteredClassPath.java
@@ -3,10 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
import com.google.common.collect.ImmutableList;
-import java.io.File;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.List;
/**
@@ -21,32 +21,36 @@
private final Path path;
private final ImmutableList<String> pattern;
+ private final Origin origin;
+ private final Position position;
- public FilteredClassPath(Path path, List<String> pattern) {
+ public FilteredClassPath(Path path, List<String> pattern, Origin origin, Position position) {
this.path = path;
this.pattern = ImmutableList.copyOf(pattern);
+ this.origin = origin;
+ this.position = position;
}
private FilteredClassPath(Path path) {
- this(path, ImmutableList.of());
- }
-
- public static FilteredClassPath unfiltered(File file) {
- return new FilteredClassPath(file.toPath());
+ this(path, ImmutableList.of(), Origin.unknown(), Position.UNKNOWN);
}
public static FilteredClassPath unfiltered(Path path) {
return new FilteredClassPath(path);
}
- public static FilteredClassPath unfiltered(String path) {
- return new FilteredClassPath(Paths.get(path));
- }
-
public Path getPath() {
return path;
}
+ public Origin getOrigin() {
+ return origin;
+ }
+
+ public Position getPosition() {
+ return position;
+ }
+
public boolean matchesFile(String name) {
if (isUnfiltered()) {
return true;
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index 4a4a182..7ab8dd5 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -1226,13 +1226,14 @@
private List<FilteredClassPath> parseClassPath() throws ProguardRuleParserException {
List<FilteredClassPath> classPath = new ArrayList<>();
skipWhitespace();
+ TextPosition position = getPosition();
Path file = parseFileName(true);
ImmutableList<String> filters = parseClassPathFilters();
- classPath.add(new FilteredClassPath(file, filters));
+ classPath.add(new FilteredClassPath(file, filters, origin, position));
while (acceptChar(File.pathSeparatorChar)) {
file = parseFileName(true);
filters = parseClassPathFilters();
- classPath.add(new FilteredClassPath(file, filters));
+ classPath.add(new FilteredClassPath(file, filters, origin, position));
}
return classPath;
}
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index 4c15524..ad09465 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -439,10 +439,17 @@
/** Add filtered archives of program resources. */
public Builder addFilteredProgramArchives(Collection<FilteredClassPath> filteredArchives) {
for (FilteredClassPath archive : filteredArchives) {
- assert isArchive(archive.getPath());
- ArchiveResourceProvider archiveResourceProvider =
- new ArchiveResourceProvider(archive, ignoreDexInArchive);
- addProgramResourceProvider(archiveResourceProvider);
+ if (isArchive(archive.getPath())) {
+ ArchiveResourceProvider archiveResourceProvider =
+ new ArchiveResourceProvider(archive, ignoreDexInArchive);
+ addProgramResourceProvider(archiveResourceProvider);
+ } else {
+ reporter.error(
+ new StringDiagnostic(
+ "Unexpected input type. Only archive types are supported, e.g., .jar, .zip, etc.",
+ archive.getOrigin(),
+ archive.getPosition()));
+ }
}
return this;
}
@@ -502,13 +509,21 @@
/** Add library file resources. */
public Builder addFilteredLibraryArchives(Collection<FilteredClassPath> filteredArchives) {
for (FilteredClassPath archive : filteredArchives) {
- assert isArchive(archive.getPath());
- try {
- FilteredArchiveClassFileProvider provider = new FilteredArchiveClassFileProvider(archive);
- archiveProvidersToClose.add(provider);
- libraryResourceProviders.add(provider);
- } catch (IOException e) {
- reporter.error(new ExceptionDiagnostic(e, new PathOrigin(archive.getPath())));
+ if (isArchive(archive.getPath())) {
+ try {
+ FilteredArchiveClassFileProvider provider =
+ new FilteredArchiveClassFileProvider(archive);
+ archiveProvidersToClose.add(provider);
+ libraryResourceProviders.add(provider);
+ } catch (IOException e) {
+ reporter.error(new ExceptionDiagnostic(e, new PathOrigin(archive.getPath())));
+ }
+ } else {
+ reporter.error(
+ new StringDiagnostic(
+ "Unexpected input type. Only archive types are supported, e.g., .jar, .zip, etc.",
+ archive.getOrigin(),
+ archive.getPosition()));
}
}
return this;
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index 5900399c..74ba7d6 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -110,6 +110,10 @@
graphConsumer);
}
+ public Builder getBuilder() {
+ return builder;
+ }
+
public R8TestBuilder addDataResources(List<DataEntryResource> resources) {
resources.forEach(builder.getAppBuilder()::addDataResource);
return self();
diff --git a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
index a6afe52..1560cab 100644
--- a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -85,6 +85,19 @@
}
}
+ public CR compileWithExpectedDiagnostics(
+ Consumer<TestDiagnosticMessages> diagnosticsConsumer) throws CompilationFailedException {
+ TestDiagnosticMessages diagnosticsHandler = getState().getDiagnosticsMessages();
+ try {
+ CR result = compile();
+ diagnosticsConsumer.accept(diagnosticsHandler);
+ return result;
+ } catch (CompilationFailedException e) {
+ diagnosticsConsumer.accept(diagnosticsHandler);
+ throw e;
+ }
+ }
+
@Override
public RR run(String mainClass)
throws CompilationFailedException, ExecutionException, IOException {
diff --git a/src/test/java/com/android/tools/r8/TestDiagnosticMessages.java b/src/test/java/com/android/tools/r8/TestDiagnosticMessages.java
index d1e55f4..cfa647a 100644
--- a/src/test/java/com/android/tools/r8/TestDiagnosticMessages.java
+++ b/src/test/java/com/android/tools/r8/TestDiagnosticMessages.java
@@ -22,6 +22,8 @@
public TestDiagnosticMessages assertOnlyWarnings();
+ public TestDiagnosticMessages assertOnlyErrors();
+
public TestDiagnosticMessages assertInfosCount(int count);
public TestDiagnosticMessages assertWarningsCount(int count);
diff --git a/src/test/java/com/android/tools/r8/TestDiagnosticMessagesImpl.java b/src/test/java/com/android/tools/r8/TestDiagnosticMessagesImpl.java
index a0ed928..ccffe02 100644
--- a/src/test/java/com/android/tools/r8/TestDiagnosticMessagesImpl.java
+++ b/src/test/java/com/android/tools/r8/TestDiagnosticMessagesImpl.java
@@ -76,6 +76,13 @@
return this;
}
+ public TestDiagnosticMessages assertOnlyErrors() {
+ assertEmpty("info", getInfos());
+ assertEmpty("warning", getWarnings());
+ assertNotEquals(0, getErrors().size());
+ return this;
+ }
+
public TestDiagnosticMessages assertInfosCount(int count) {
assertEquals(count, getInfos().size());
return this;
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index ea774b8..0835f70 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -18,6 +18,8 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
import com.android.tools.r8.shaking.FilteredClassPath;
import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardConfigurationParser;
@@ -1008,9 +1010,13 @@
}
public static void addFilteredAndroidJar(AndroidApp.Builder builder, AndroidApiLevel apiLevel) {
- builder.addFilteredLibraryArchives(Collections.singletonList(
- new FilteredClassPath(getAndroidJar(apiLevel),
- ImmutableList.of("!junit/**", "!android/test/**"))));
+ builder.addFilteredLibraryArchives(
+ Collections.singletonList(
+ new FilteredClassPath(
+ getAndroidJar(apiLevel),
+ ImmutableList.of("!junit/**", "!android/test/**"),
+ Origin.unknown(),
+ Position.UNKNOWN)));
}
public static AndroidApp runD8(AndroidApp app) throws CompilationFailedException {
diff --git a/src/test/java/com/android/tools/r8/shaking/FilteredClassPathTest.java b/src/test/java/com/android/tools/r8/shaking/FilteredClassPathTest.java
index 7c243ae..31838fc 100644
--- a/src/test/java/com/android/tools/r8/shaking/FilteredClassPathTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/FilteredClassPathTest.java
@@ -8,6 +8,8 @@
import com.android.tools.r8.ProgramResourceProvider;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.AndroidApp.Builder;
import com.android.tools.r8.utils.ListUtils;
@@ -43,7 +45,8 @@
}
private static FilteredClassPath makeFilteredClassPath(Path path, List<String> filters) {
- return new FilteredClassPath(path, ImmutableList.copyOf(filters));
+ return new FilteredClassPath(
+ path, ImmutableList.copyOf(filters), Origin.unknown(), Position.UNKNOWN);
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardDirectoryInputsTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardDirectoryInputsTest.java
new file mode 100644
index 0000000..67ed661
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardDirectoryInputsTest.java
@@ -0,0 +1,113 @@
+// Copyright (c) 2019, 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.shaking;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.ByteDataView;
+import com.android.tools.r8.ClassFileConsumer.DirectoryConsumer;
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.Diagnostic;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.TextPosition;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
+import java.nio.file.Path;
+import java.util.Collections;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ProguardDirectoryInputsTest extends TestBase {
+
+ static final String EXPECTED = StringUtils.lines("Hello, world");
+
+ private final Backend backend;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Backend[] data() {
+ return Backend.values();
+ }
+
+ public ProguardDirectoryInputsTest(Backend backend) {
+ this.backend = backend;
+ }
+
+ @Test(expected = CompilationFailedException.class)
+ public void testInJars() throws Exception {
+ test("injars");
+ }
+
+ @Test(expected = CompilationFailedException.class)
+ public void testLibraryJars() throws Exception {
+ test("libraryjars");
+ }
+
+ private void test(String option) throws Exception {
+ Path directory = temp.newFolder().toPath();
+ {
+ DirectoryConsumer consumer = new DirectoryConsumer(directory);
+ consumer.accept(
+ ByteDataView.of(ToolHelper.getClassAsBytes(OtherClass.class)),
+ DescriptorUtils.javaTypeToDescriptor(OtherClass.class.getTypeName()),
+ null);
+ consumer.finished(null);
+ }
+ if (backend == Backend.CF) {
+ testForJvm()
+ .addProgramClasses(TestClass.class)
+ .addClasspath(directory)
+ .run(TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ Origin origin =
+ new Origin(Origin.root()) {
+ @Override
+ public String part() {
+ return "pg-test-input";
+ }
+ };
+
+ String prefix = "-" + option + " ";
+ testForR8(backend)
+ .addProgramClasses(TestClass.class)
+ .apply(
+ b -> {
+ b.getBuilder()
+ .addProguardConfiguration(
+ Collections.singletonList(prefix + directory.toAbsolutePath()), origin);
+ })
+ .addKeepMainRule(TestClass.class)
+ .compileWithExpectedDiagnostics(diagnostics -> {
+ diagnostics.assertOnlyErrors();
+ diagnostics.assertErrorsCount(1);
+ Diagnostic diagnostic = diagnostics.getErrors().get(0);
+ assertThat(diagnostic.getDiagnosticMessage(), containsString("Unexpected input type"));
+ assertEquals(origin, diagnostic.getOrigin());
+ TextPosition position = (TextPosition) diagnostic.getPosition();
+ assertEquals(1, position.getLine());
+ assertEquals(prefix.length() + 1, position.getColumn());
+ });
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ System.out.println("Hello, world");
+ }
+ }
+
+ static class OtherClass {
+
+ public void foo() {
+ System.out.println("foo");
+ }
+ }
+}