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 * @param place Target file path
42 * @param args Tokens to write
43 */
44 public Argfile(final File place, final List<String> args) {
45 this.place = place;
46 this.args = args;
47 }
48
49 /**
50 * Write the argfile and return its path.
51 * @return The path of the just-written argfile
52 */
53 public File save() {
54 final StringBuilder content = new StringBuilder(this.args.size() * 64);
55 for (final String arg : this.args) {
56 content.append('"');
57 for (int idx = 0; idx < arg.length(); idx += 1) {
58 final char chr = arg.charAt(idx);
59 if (chr == '\\' || chr == '"') {
60 content.append('\\');
61 }
62 content.append(chr);
63 }
64 content.append('"').append(System.lineSeparator());
65 }
66 try {
67 Files.writeString(
68 this.place.toPath(),
69 content.toString(),
70 StandardCharsets.UTF_8
71 );
72 } catch (final IOException ex) {
73 throw new UncheckedIOException(
74 String.format("Unable to write argfile %s", this.place), ex
75 );
76 }
77 return this.place;
78 }
79 }