Skip to content

Commit 8999cb9

Browse files
authored
Fix trait application and empty string parsing (#197)
#190 fixed trait application parsing for traits like `@foo()`, making it so the end of the trait doesn't include trailing whitespace. This commit fixes the case for non-empty traits, like `@foo(bar: "")`. It also fixes parsing of empty strings. Previously the character _after_ the end of the string would be skipped.
1 parent 795159b commit 8999cb9

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

src/main/java/software/amazon/smithy/lsp/syntax/Parser.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ private Syntax.Node traitValueKvps(int from) {
193193
while (!eof()) {
194194
if (is(')')) {
195195
setEnd(kvps);
196-
skip();
197196
return kvps;
198197
}
199198

@@ -398,7 +397,6 @@ private Syntax.Node str() {
398397
}
399398

400399
// Empty string
401-
skip();
402400
int strEnd = position();
403401
return new Syntax.Node.Str(start, strEnd, "");
404402
}

src/test/java/software/amazon/smithy/lsp/TextWithPositions.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,21 @@ public record TextWithPositions(String text, Position... positions) {
3838
public static TextWithPositions from(String raw) {
3939
Document document = Document.of(safeString(raw));
4040
List<Position> positions = new ArrayList<>();
41+
42+
Position lastPosition = null;
4143
int i = 0;
4244
while (true) {
4345
int next = document.nextIndexOf(POSITION_MARKER, i);
4446
if (next < 0) {
4547
break;
4648
}
4749
Position position = document.positionAtIndex(next);
50+
if (lastPosition != null && position.getLine() == lastPosition.getLine()) {
51+
// If there's two or more markers on the same line, any markers after the
52+
// first will be off by one when we do the replacement.
53+
position.setCharacter(position.getCharacter() - 1);
54+
}
55+
lastPosition = position;
4856
positions.add(position);
4957
i = next + 1;
5058
}

src/test/java/software/amazon/smithy/lsp/syntax/IdlParserTest.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.junit.jupiter.params.ParameterizedTest;
1919
import org.junit.jupiter.params.provider.Arguments;
2020
import org.junit.jupiter.params.provider.MethodSource;
21+
import software.amazon.smithy.lsp.TextWithPositions;
2122
import software.amazon.smithy.lsp.document.Document;
2223

2324
public class IdlParserTest {
@@ -304,6 +305,27 @@ public void stringKeysInTraits() {
304305
Syntax.Node.Type.Str));
305306
}
306307

308+
@Test
309+
public void traitApplicationsDontContainTrailingWhitespace() {
310+
var twp = TextWithPositions.from("""
311+
%@foo(foo: "")%
312+
structure Foo {
313+
foo: Foo
314+
}
315+
""");
316+
Document document = Document.of(twp.text());
317+
Syntax.IdlParseResult parse = Syntax.parseIdl(document);
318+
319+
assertThat(getTypes(parse), contains(
320+
Syntax.Statement.Type.TraitApplication,
321+
Syntax.Statement.Type.ShapeDef,
322+
Syntax.Statement.Type.MemberDef));
323+
324+
Syntax.Statement traitApplication = parse.statements().get(0);
325+
assertThat(document.positionAtIndex(traitApplication.start()), equalTo(twp.positions()[0]));
326+
assertThat(document.positionAtIndex(traitApplication.end()), equalTo(twp.positions()[1]));
327+
}
328+
307329
@ParameterizedTest
308330
@MethodSource("brokenProvider")
309331
public void broken(String desc, String text, List<String> expectedErrorMessages, List<Syntax.Statement.Type> expectedTypes) {
@@ -460,10 +482,14 @@ private static Stream<Arguments> brokenProvider() {
460482

461483
private static void assertTypesEqual(String text, Syntax.Statement.Type... types) {
462484
Syntax.IdlParseResult parse = Syntax.parseIdl(Document.of(text));
463-
List<Syntax.Statement.Type> actualTypes = parse.statements().stream()
485+
var actualTypes = getTypes(parse);
486+
assertThat(actualTypes, contains(types));
487+
}
488+
489+
private static List<Syntax.Statement.Type> getTypes(Syntax.IdlParseResult parse) {
490+
return parse.statements().stream()
464491
.map(Syntax.Statement::type)
465492
.filter(type -> type != Syntax.Statement.Type.Block)
466493
.toList();
467-
assertThat(actualTypes, contains(types));
468494
}
469495
}

0 commit comments

Comments
 (0)