Skip to content

Commit 25f02d5

Browse files
polo7fmbenhassine
authored andcommitted
Fix quote handling in commented lines
Resolves #277
1 parent 5ad9282 commit 25f02d5

File tree

2 files changed

+112
-1
lines changed

2 files changed

+112
-1
lines changed

spring-shell-core/src/main/java/org/springframework/shell/jline/FileInputProvider.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,13 @@ public Input readInput() {
6666
if (line == null) {
6767
return null;
6868
} else {
69-
ParsedLine parsedLine = parser.parse(sb.toString(), sb.toString().length());
69+
// gh-277: if it's a commented line then skip as it is equal to NO_INPUT
70+
ParsedLine parsedLine;
71+
if (isCommentedLine(line)) {
72+
parsedLine = parser.parse("", -1, Parser.ParseContext.COMPLETE);
73+
} else {
74+
parsedLine = parser.parse(sb.toString(), sb.toString().length());
75+
}
7076
return new ParsedLineInput(parsedLine);
7177
}
7278
}
@@ -75,4 +81,8 @@ public Input readInput() {
7581
public void close() throws IOException {
7682
reader.close();
7783
}
84+
85+
private boolean isCommentedLine(String line) {
86+
return line.matches("\\s*//.*");
87+
}
7888
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.shell.jline;
17+
18+
import org.jline.reader.EOFError;
19+
import org.jline.reader.impl.DefaultParser;
20+
import org.junit.jupiter.params.ParameterizedTest;
21+
import org.junit.jupiter.params.provider.Arguments;
22+
import org.junit.jupiter.params.provider.MethodSource;
23+
24+
import java.io.Reader;
25+
import java.io.StringReader;
26+
import java.util.stream.Stream;
27+
28+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
29+
import static org.junit.jupiter.api.Assertions.assertThrows;
30+
import static org.junit.jupiter.api.Assertions.assertTrue;
31+
32+
class FileInputProviderTests {
33+
34+
private final ExtendedDefaultParser springParser = new ExtendedDefaultParser();
35+
private final DefaultParser jlineParser = new DefaultParser();
36+
private FileInputProvider fileInputProvider;
37+
38+
static Stream<Arguments> regularLinesUnclosedQuotes() {
39+
return Stream.of(
40+
Arguments.of("Regular line with unclosed 'quote"),
41+
Arguments.of("Regular line with unclosed \"quote")
42+
);
43+
}
44+
45+
static Stream<Arguments> commentsUnclosedQuotes() {
46+
return Stream.of(
47+
Arguments.of("//Commented line with unclosed 'quote"),
48+
Arguments.of("//Commented line with unclosed \"quote")
49+
);
50+
}
51+
52+
@ParameterizedTest
53+
@MethodSource("regularLinesUnclosedQuotes")
54+
void shouldThrowOnUnclosedQuoteDefaultParser(String line) {
55+
jlineParser.setEofOnUnclosedQuote(true);
56+
Reader reader = new StringReader(line);
57+
fileInputProvider = new FileInputProvider(reader, jlineParser);
58+
Exception exception = assertThrows(EOFError.class, () -> {
59+
fileInputProvider.readInput();
60+
});
61+
String expectedExceptionMessage = "Missing closing quote";
62+
String actualExceptionMessage = exception.getMessage();
63+
assertTrue(actualExceptionMessage.contains(expectedExceptionMessage));
64+
}
65+
66+
@ParameterizedTest
67+
@MethodSource("regularLinesUnclosedQuotes")
68+
void shouldThrowOnUnclosedQuoteExtendedParser(String line) {
69+
springParser.setEofOnUnclosedQuote(true);
70+
Reader reader = new StringReader(line);
71+
fileInputProvider = new FileInputProvider(reader, springParser);
72+
Exception exception = assertThrows(EOFError.class, () -> {
73+
fileInputProvider.readInput();
74+
});
75+
String expectedExceptionMessage = "Missing closing quote";
76+
String actualExceptionMessage = exception.getMessage();
77+
assertTrue(actualExceptionMessage.contains(expectedExceptionMessage));
78+
}
79+
80+
@ParameterizedTest
81+
@MethodSource("commentsUnclosedQuotes")
82+
void shouldNotThrowOnUnclosedQuoteDefaultParser(String line) {
83+
jlineParser.setEofOnUnclosedQuote(true);
84+
Reader reader = new StringReader(line);
85+
fileInputProvider = new FileInputProvider(reader, jlineParser);
86+
assertDoesNotThrow(() -> {
87+
fileInputProvider.readInput();
88+
});
89+
}
90+
91+
@ParameterizedTest
92+
@MethodSource("commentsUnclosedQuotes")
93+
void shouldNotThrowOnUnclosedQuoteExtendedParser(String line) {
94+
springParser.setEofOnUnclosedQuote(true);
95+
Reader reader = new StringReader(line);
96+
fileInputProvider = new FileInputProvider(reader, springParser);
97+
assertDoesNotThrow(() -> {
98+
fileInputProvider.readInput();
99+
});
100+
}
101+
}

0 commit comments

Comments
 (0)