1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2011-2026 Yegor Bugayenko
3 * SPDX-License-Identifier: MIT
4 */
5 package com.qulice.errorprone;
6
7 import java.io.File;
8 import java.io.IOException;
9 import java.io.UncheckedIOException;
10 import java.nio.charset.StandardCharsets;
11 import java.nio.file.Files;
12 import java.util.List;
13
14 /**
15 * A {@code javac} argfile materialised on disk.
16 *
17 * <p>Wraps a list of command-line tokens and writes them to a single
18 * file in {@code javac}'s argfile format — one double-quoted token per
19 * line with backslashes and double quotes escaped — so even very long
20 * classpaths and source lists stay below the Windows
21 * {@code CreateProcess} command-line limit when passed to {@code javac}
22 * as {@code @path}. The {@code -J} launcher flags must NOT be included
23 * here; {@code javac} forbids them inside argfiles.</p>
24 *
25 * @since 1.0
26 */
27 public final class Argfile {
28
29 /**
30 * Where the argfile will be written.
31 */
32 private final File place;
33
34 /**
35 * Tokens to write, in order, one per line.
36 */
37 private final List<String> args;
38
39 /**
40 * Constructor.
41 *
42 * @param place Target file path
43 * @param args Tokens to write
44 */
45 public Argfile(final File place, final List<String> args) {
46 this.place = place;
47 this.args = args;
48 }
49
50 /**
51 * Write the argfile and return its path.
52 *
53 * @return The path of the just-written argfile
54 */
55 public File save() {
56 final StringBuilder content = new StringBuilder(this.args.size() * 64);
57 for (final String arg : this.args) {
58 content.append('"');
59 for (int idx = 0; idx < arg.length(); idx += 1) {
60 final char chr = arg.charAt(idx);
61 if (chr == '\\' || chr == '"') {
62 content.append('\\');
63 }
64 content.append(chr);
65 }
66 content.append('"').append(System.lineSeparator());
67 }
68 try {
69 Files.writeString(
70 this.place.toPath(),
71 content.toString(),
72 StandardCharsets.UTF_8
73 );
74 } catch (final IOException ex) {
75 throw new UncheckedIOException(
76 String.format("Unable to write argfile %s", this.place), ex
77 );
78 }
79 return this.place;
80 }
81 }