|
14 | 14 |
|
15 | 15 | package com.google.googlejavaformat.java;
|
16 | 16 |
|
17 |
| -import static java.nio.charset.StandardCharsets.UTF_8; |
18 |
| - |
19 |
| -import com.google.common.base.CharMatcher; |
20 | 17 | import com.google.common.base.Preconditions;
|
21 | 18 | import com.google.common.base.Splitter;
|
22 | 19 | import com.google.common.collect.ImmutableRangeSet;
|
|
25 | 22 | import java.io.UncheckedIOException;
|
26 | 23 | import java.nio.file.Files;
|
27 | 24 | import java.nio.file.Path;
|
28 |
| -import java.nio.file.Paths; |
29 | 25 | import java.util.ArrayDeque;
|
30 | 26 | import java.util.ArrayList;
|
31 | 27 | import java.util.Deque;
|
32 | 28 | import java.util.Iterator;
|
33 | 29 | import java.util.List;
|
| 30 | +import java.util.regex.Matcher; |
| 31 | +import java.util.regex.Pattern; |
34 | 32 |
|
35 | 33 | /** A parser for {@link CommandLineOptions}. */
|
36 | 34 | final class CommandLineOptionsParser {
|
37 | 35 |
|
38 | 36 | private static final Splitter COMMA_SPLITTER = Splitter.on(',');
|
39 | 37 | private static final Splitter COLON_SPLITTER = Splitter.on(':');
|
40 |
| - private static final Splitter ARG_SPLITTER = |
41 |
| - Splitter.on(CharMatcher.breakingWhitespace()).omitEmptyStrings().trimResults(); |
| 38 | + |
| 39 | + /** |
| 40 | + * Let's split arguments on whitespace (including tabulator and newline). Additionally allow quotes for arguments, |
| 41 | + * such that they can contain whitespace that are kept in the argument without change. |
| 42 | + * |
| 43 | + * The regex matches either a quoted string (single or double quotes are allowed) or a plain unquoted string. |
| 44 | + * It is possible to have double quotes within a single-quoted string and vice-versa. This is then kept 'as-is'. |
| 45 | + * For simplicity, we do not handle escaped quotes. |
| 46 | + */ |
| 47 | + private static final Pattern ARG_MATCHER = Pattern.compile( |
| 48 | + "\"([^\"]*)\"" + // group 1: string in double quotes, with whitespace allowed |
| 49 | + "|" + // OR |
| 50 | + "'([^']*)'" + // group 2: string in single quotes, with whitespace allowed |
| 51 | + "|" + // OR |
| 52 | + "([^\\s\"']+)" // group 3: unquoted string, without whitespace and without any quotes |
| 53 | + ); |
42 | 54 |
|
43 | 55 | /** Parses {@link CommandLineOptions}. */
|
44 | 56 | static CommandLineOptions parse(Iterable<String> options) {
|
@@ -204,16 +216,30 @@ private static void expandParamsFiles(Iterable<String> args, List<String> expand
|
204 | 216 | throw new IllegalArgumentException("parameter file was included recursively: " + filename);
|
205 | 217 | }
|
206 | 218 | paramFilesStack.push(filename);
|
207 |
| - Path path = Paths.get(filename); |
208 |
| - try { |
209 |
| - String sequence = new String(Files.readAllBytes(path), UTF_8); |
210 |
| - expandParamsFiles(ARG_SPLITTER.split(sequence), expanded, paramFilesStack); |
211 |
| - } catch (IOException e) { |
212 |
| - throw new UncheckedIOException(path + ": could not read file: " + e.getMessage(), e); |
213 |
| - } |
| 219 | + expandParamsFiles(getParamsFromFile(filename), expanded, paramFilesStack); |
214 | 220 | String finishedFilename = paramFilesStack.pop();
|
215 | 221 | Preconditions.checkState(filename.equals(finishedFilename));
|
216 | 222 | }
|
217 | 223 | }
|
218 | 224 | }
|
| 225 | + |
| 226 | + /** Read parameters from file and handle quoted parameters. */ |
| 227 | + private static List<String> getParamsFromFile(String filename) { |
| 228 | + String fileContent; |
| 229 | + try { |
| 230 | + fileContent = Files.readString(Path.of(filename)); |
| 231 | + } catch (IOException e) { |
| 232 | + throw new UncheckedIOException(filename + ": could not read file: " + e.getMessage(), e); |
| 233 | + } |
| 234 | + List<String> paramsFromFile = new ArrayList<>(); |
| 235 | + Matcher m = ARG_MATCHER.matcher(fileContent); |
| 236 | + while (m.find()) { |
| 237 | + for (int i = 1; i <= m.groupCount(); i++) { |
| 238 | + if (m.group(i) != null) { // only one group matches: double quote, single quotes or unquoted string. |
| 239 | + paramsFromFile.add(m.group(i)); |
| 240 | + } |
| 241 | + } |
| 242 | + } |
| 243 | + return paramsFromFile; |
| 244 | + } |
219 | 245 | }
|
0 commit comments