Skip to content

Commit 598f248

Browse files
sormurascushon
authored andcommitted
Add support for javac-style @params files
Fixes #77 MOE_MIGRATED_REVID=172163309
1 parent 1d60175 commit 598f248

File tree

3 files changed

+67
-4
lines changed

3 files changed

+67
-4
lines changed

core/src/main/java/com/google/googlejavaformat/java/CommandLineOptionsParser.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,18 @@
1414

1515
package com.google.googlejavaformat.java;
1616

17+
import static java.nio.charset.StandardCharsets.UTF_8;
18+
19+
import com.google.common.base.CharMatcher;
1720
import com.google.common.base.Splitter;
1821
import com.google.common.collect.ImmutableRangeSet;
1922
import com.google.common.collect.Range;
23+
import java.io.IOException;
24+
import java.io.UncheckedIOException;
25+
import java.nio.file.Files;
26+
import java.nio.file.Path;
27+
import java.nio.file.Paths;
28+
import java.util.ArrayList;
2029
import java.util.Iterator;
2130
import java.util.List;
2231

@@ -25,11 +34,15 @@ final class CommandLineOptionsParser {
2534

2635
private static final Splitter COMMA_SPLITTER = Splitter.on(',');
2736
private static final Splitter COLON_SPLITTER = Splitter.on(':');
37+
private static final Splitter ARG_SPLITTER =
38+
Splitter.on(CharMatcher.breakingWhitespace()).omitEmptyStrings().trimResults();
2839

2940
/** Parses {@link CommandLineOptions}. */
3041
static CommandLineOptions parse(Iterable<String> options) {
3142
CommandLineOptions.Builder optionsBuilder = CommandLineOptions.builder();
32-
Iterator<String> it = options.iterator();
43+
List<String> expandedOptions = new ArrayList<>();
44+
expandParamsFiles(options, expandedOptions);
45+
Iterator<String> it = expandedOptions.iterator();
3346
while (it.hasNext()) {
3447
String option = it.next();
3548
if (!option.startsWith("-")) {
@@ -158,4 +171,29 @@ private static Range<Integer> parseRange(String arg) {
158171
throw new IllegalArgumentException(arg);
159172
}
160173
}
174+
175+
/**
176+
* Pre-processes an argument list, expanding arguments of the form {@code @filename} by reading
177+
* the content of the file and appending whitespace-delimited options to {@code arguments}.
178+
*/
179+
private static void expandParamsFiles(Iterable<String> args, List<String> expanded) {
180+
for (String arg : args) {
181+
if (arg.isEmpty()) {
182+
continue;
183+
}
184+
if (!arg.startsWith("@")) {
185+
expanded.add(arg);
186+
} else if (arg.startsWith("@@")) {
187+
expanded.add(arg.substring(1));
188+
} else {
189+
Path path = Paths.get(arg.substring(1));
190+
try {
191+
String sequence = new String(Files.readAllBytes(path), UTF_8);
192+
expandParamsFiles(ARG_SPLITTER.split(sequence), expanded);
193+
} catch (IOException e) {
194+
throw new UncheckedIOException(path + ": could not read file: " + e.getMessage(), e);
195+
}
196+
}
197+
}
198+
}
161199
}

core/src/main/java/com/google/googlejavaformat/java/UsageException.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import com.google.common.base.Joiner;
2020

2121
/** Checked exception class for formatter command-line usage errors. */
22-
public final class UsageException extends Exception {
22+
final class UsageException extends Exception {
2323

2424
private static final Joiner NEWLINE_JOINER = Joiner.on(System.lineSeparator());
2525

@@ -37,7 +37,7 @@ public final class UsageException extends Exception {
3737
" -",
3838
" Format stdin -> stdout",
3939
" --aosp, -aosp, -a",
40-
" Use AOSP style instead of Google Style (4-space indentation)",
40+
" Use AOSP style instead of Google Style (4-space indentation).",
4141
" --fix-imports-only",
4242
" Fix import order and remove any unused imports, but do no other formatting.",
4343
" --skip-sorting-imports",
@@ -56,9 +56,11 @@ public final class UsageException extends Exception {
5656
" --offset, -offset",
5757
" Character offset to format (0-based; default is all).",
5858
" --help, -help, -h",
59-
" Print this usage statement",
59+
" Print this usage statement.",
6060
" --version, -version, -v",
6161
" Print the version.",
62+
" @<filename>",
63+
" Read options and filenames from file.",
6264
"",
6365
};
6466

core/src/test/java/com/google/googlejavaformat/java/CommandLineOptionsParserTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,27 @@
1515
package com.google.googlejavaformat.java;
1616

1717
import static com.google.common.truth.Truth.assertThat;
18+
import static java.nio.charset.StandardCharsets.UTF_8;
1819
import static org.junit.Assert.fail;
1920

2021
import com.google.common.collect.Range;
22+
import java.io.IOException;
23+
import java.nio.file.Files;
24+
import java.nio.file.Path;
2125
import java.util.Arrays;
2226
import java.util.Collections;
27+
import org.junit.Rule;
2328
import org.junit.Test;
29+
import org.junit.rules.TemporaryFolder;
2430
import org.junit.runner.RunWith;
2531
import org.junit.runners.JUnit4;
2632

2733
/** {@link CommandLineOptionsParser}Test */
2834
@RunWith(JUnit4.class)
2935
public class CommandLineOptionsParserTest {
3036

37+
@Rule public TemporaryFolder testFolder = new TemporaryFolder();
38+
3139
@Test
3240
public void defaults() {
3341
CommandLineOptions options = CommandLineOptionsParser.parse(Collections.<String>emptyList());
@@ -152,4 +160,19 @@ public void illegalLines() {
152160
}
153161
}
154162

163+
@Test
164+
public void paramsFile() throws IOException {
165+
Path outer = testFolder.newFile("outer").toPath();
166+
Path exit = testFolder.newFile("exit").toPath();
167+
Path nested = testFolder.newFile("nested").toPath();
168+
169+
String[] args = {"--dry-run", "@" + exit, "L", "@" + outer, "Q"};
170+
171+
Files.write(exit, "--set-exit-if-changed".getBytes(UTF_8));
172+
Files.write(outer, ("M\n@" + nested.toAbsolutePath() + "\nP").getBytes(UTF_8));
173+
Files.write(nested, "ℕ\n\n \n@@O\n".getBytes(UTF_8));
174+
175+
CommandLineOptions options = CommandLineOptionsParser.parse(Arrays.asList(args));
176+
assertThat(options.files()).containsExactly("L", "M", "ℕ", "@O", "P", "Q");
177+
}
155178
}

0 commit comments

Comments
 (0)