Merge "Improve configuration parser error"
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 47d3743..1b74e3b 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -401,13 +401,22 @@
&& (unknownOption.equals("forceinline") || unknownOption.equals("neverinline"))) {
devMessage = ", this option needs to be turned on explicitly if used for tests.";
}
- reporter.error(new StringDiagnostic(
- "Unknown option \"-" + unknownOption + "\"" + devMessage,
- origin, getPosition(optionStart)));
+ unknownOption(unknownOption, optionStart, devMessage);
}
return true;
}
+ private void unknownOption(String unknownOption, TextPosition optionStart) {
+ unknownOption(unknownOption, optionStart, "");
+ }
+
+ private void unknownOption(
+ String unknownOption, TextPosition optionStart, String additionalMessage) {
+ throw reporter.fatalError((new StringDiagnostic(
+ "Unknown option \"-" + unknownOption + "\"" + additionalMessage,
+ origin, getPosition(optionStart))));
+ }
+
private boolean parseUnsupportedOptionAndErr(TextPosition optionStart) {
String option = Iterables.find(UNSUPPORTED_FLAG_OPTIONS, this::skipFlag, null);
if (option != null) {
@@ -768,14 +777,19 @@
TextPosition start = getPosition();
acceptString("-");
String unknownOption = acceptString();
- throw reporter.fatalError(new StringDiagnostic(
- "Unknown option \"-" + unknownOption + "\"",
- origin,
- start));
+ unknownOption(unknownOption, start);
}
} else {
builder.setType(ProguardKeepRuleType.KEEP);
}
+ if (!eof() && !Character.isWhitespace(peekChar()) && peekChar() != ',') {
+ // The only path to here is through "-keep" with an unsupported suffix.
+ unacceptString("-keep");
+ TextPosition start = getPosition();
+ acceptString("-");
+ String unknownOption = acceptString();
+ unknownOption(unknownOption, start);
+ }
parseRuleModifiers(builder);
}
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index e0baab1..c24ed3b 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -163,6 +163,8 @@
/**
* Write lines of text to a temporary file.
+ *
+ * The file will include a line separator after the last line.
*/
protected Path writeTextToTempFile(String... lines) throws IOException {
return writeTextToTempFile(System.lineSeparator(), Arrays.asList(lines));
@@ -170,11 +172,28 @@
/**
* Write lines of text to a temporary file, along with the specified line separator.
+ *
+ * The file will include a line separator after the last line.
*/
protected Path writeTextToTempFile(String lineSeparator, List<String> lines)
throws IOException {
+ return writeTextToTempFile(lineSeparator, lines, true);
+ }
+
+ /**
+ * Write lines of text to a temporary file, along with the specified line separator.
+ *
+ * The argument <code>includeTerminatingLineSeparator</code> control if the file will include
+ * a line separator after the last line.
+ */
+ protected Path writeTextToTempFile(
+ String lineSeparator, List<String> lines, boolean includeTerminatingLineSeparator)
+ throws IOException {
Path file = temp.newFile().toPath();
- String contents = String.join(lineSeparator, lines) + lineSeparator;
+ String contents = String.join(lineSeparator, lines);
+ if (includeTerminatingLineSeparator) {
+ contents += lineSeparator;
+ }
Files.write(file, contents.getBytes(StandardCharsets.UTF_8));
return file;
}
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index ff84486..db5f631 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -1113,6 +1113,39 @@
}
@Test
+ public void parseInvalidKeepOption() throws Exception {
+ Path proguardConfig = writeTextToTempFile(
+ "-keepx public class * { ",
+ " native <methods>; ",
+ "} "
+ );
+ try {
+ ProguardConfigurationParser parser =
+ new ProguardConfigurationParser(new DexItemFactory(), reporter);
+ parser.parse(proguardConfig);
+ fail();
+ } catch (AbortException e) {
+ checkDiagnostics(handler.errors, proguardConfig, 1, 1,
+ "Unknown option", "-keepx");
+ }
+ }
+
+ @Test
+ public void parseKeepOptionEOF() throws Exception {
+ Path proguardConfig = writeTextToTempFile(
+ System.lineSeparator(), ImmutableList.of("-keep"), false);
+ try {
+ ProguardConfigurationParser parser =
+ new ProguardConfigurationParser(new DexItemFactory(), reporter);
+ parser.parse(proguardConfig);
+ fail();
+ } catch (AbortException e) {
+ checkDiagnostics(handler.errors, proguardConfig, 1, 6,
+ "Expected [!]interface|@interface|class|enum");
+ }
+ }
+
+ @Test
public void parseInvalidKeepClassOption() throws Exception {
Path proguardConfig = writeTextToTempFile(
"-keepclassx public class * { ",
@@ -1493,7 +1526,7 @@
parser.parse(createConfigurationForTesting(ImmutableList.of(option + " class A { *; }")));
fail("Expect to fail due to testing option being turned off.");
} catch (AbortException e) {
- assertEquals(2, handler.errors.size());
+ assertEquals(1, handler.errors.size());
checkDiagnostics(handler.errors, 0, null, 1, 1, "Unknown option \"" + option + "\"");
}
}