Skip to content

Commit 81befb5

Browse files
committed
fix: instruction prefixes with multiline instructions
1 parent 18cfac4 commit 81befb5

2 files changed

Lines changed: 46 additions & 11 deletions

File tree

src/main/java/com/github/jimschubert/rewrite/docker/internal/DockerfileParser.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -687,16 +687,6 @@ public Docker.Document parse(InputStream input) {
687687
continue;
688688
}
689689

690-
if (scanner.hasNext() && !eof.isEmpty()) {
691-
// at this point, we have a line, so eof is the line prefix
692-
state.appendPrefix(eof);
693-
eof = Space.EMPTY;
694-
} else if (!scanner.hasNext()) {
695-
// if we are at the end of the file with a newline
696-
eof = Space.append(eof, eol);
697-
eol = Space.EMPTY;
698-
}
699-
700690
line = handleRightPadding(line, state);
701691

702692
// TODO: consider a better way to handle "inline" comments
@@ -718,12 +708,26 @@ public Docker.Document parse(InputStream input) {
718708
}
719709

720710
parser.append(line);
721-
if (line.endsWith(state.getEscapeString())) {
711+
// TODO: should we throw an error here if the line ends in the escape char and there are no more lines?
712+
if (scanner.hasNext() && line.endsWith(state.getEscapeString())) {
722713
parser.append(eol.getWhitespace());
723714
state.isContinuation(true);
724715
continue;
725716
}
726717

718+
if (!eof.isEmpty() && (state.isContinuation() || scanner.hasNext())) {
719+
// any previously gathered whitespace is the prefix to this instruction
720+
state.appendPrefix(eof);
721+
eof = Space.EMPTY;
722+
}
723+
724+
if (!scanner.hasNext()) {
725+
// if we are at the end of the file with a newline, that is our eof.
726+
// other conditions such as multiple newlines or whitespace are handled earlier
727+
eof = Space.append(eof, eol);
728+
eol = Space.EMPTY;
729+
}
730+
727731
Docker.Instruction instr = parser.parse();
728732
if (instr != null) {
729733
instr = instr.withEol(eol);

src/test/java/com/github/jimschubert/rewrite/docker/internal/DockerfileParserTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,4 +1366,35 @@ void testDockerfileWithCommentBetweenContinuationLines() {
13661366
assertLiteral(args.get(10), Quoting.UNQUOTED, " ", "World", "");
13671367

13681368
}
1369+
1370+
@Test
1371+
void testInstructionPrefixWithContinuationCommands() {
1372+
String monster = """
1373+
ENV LAST_COMMIT=e2db71ff940a8b8c08c4ae894b952bfe7f0cf309
1374+
1375+
RUN set -eux; \\
1376+
\\
1377+
apk add --no-cache --virtual .build-deps
1378+
""";
1379+
1380+
DockerfileParser parser = new DockerfileParser();
1381+
Docker.Document doc = parser.parse(new ByteArrayInputStream(monster.getBytes(StandardCharsets.UTF_8)));
1382+
1383+
Docker.Stage stage = assertSingleStageWithChildCount(doc, 2);
1384+
Docker.Env env = (Docker.Env) stage.getChildren().get(0);
1385+
assertEquals(Space.EMPTY, env.getPrefix());
1386+
assertEquals(1, env.getArgs().size());
1387+
assertRightPaddedArg(env.getArgs().get(0), Quoting.UNQUOTED, " ", "LAST_COMMIT", true, "e2db71ff940a8b8c08c4ae894b952bfe7f0cf309", "");
1388+
1389+
Docker.Run run = (Docker.Run) stage.getChildren().get(1);
1390+
assertEquals(Space.NEWLINE, run.getPrefix());
1391+
assertEquals(7, run.getCommands().size());
1392+
assertLiteral(run.getCommands().get(0), Quoting.UNQUOTED, " ", "set", "");
1393+
assertLiteral(run.getCommands().get(1), Quoting.UNQUOTED, " ", "-eux;", " \\\n\t\\\n\t");
1394+
assertLiteral(run.getCommands().get(2), Quoting.UNQUOTED, "", "apk", "");
1395+
assertLiteral(run.getCommands().get(3), Quoting.UNQUOTED, " ", "add", "");
1396+
assertLiteral(run.getCommands().get(4), Quoting.UNQUOTED, " ", "--no-cache", "");
1397+
assertLiteral(run.getCommands().get(5), Quoting.UNQUOTED, " ", "--virtual", "");
1398+
assertLiteral(run.getCommands().get(6), Quoting.UNQUOTED, " ", ".build-deps", "");
1399+
}
13691400
}

0 commit comments

Comments
 (0)