Skip to content

Commit

Permalink
Fix trait application and empty string parsing (#197)
Browse files Browse the repository at this point in the history
#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.
  • Loading branch information
milesziemer authored Feb 13, 2025
1 parent 795159b commit 8999cb9
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 4 deletions.
2 changes: 0 additions & 2 deletions src/main/java/software/amazon/smithy/lsp/syntax/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ private Syntax.Node traitValueKvps(int from) {
while (!eof()) {
if (is(')')) {
setEnd(kvps);
skip();
return kvps;
}

Expand Down Expand Up @@ -398,7 +397,6 @@ private Syntax.Node str() {
}

// Empty string
skip();
int strEnd = position();
return new Syntax.Node.Str(start, strEnd, "");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,21 @@ public record TextWithPositions(String text, Position... positions) {
public static TextWithPositions from(String raw) {
Document document = Document.of(safeString(raw));
List<Position> positions = new ArrayList<>();

Position lastPosition = null;
int i = 0;
while (true) {
int next = document.nextIndexOf(POSITION_MARKER, i);
if (next < 0) {
break;
}
Position position = document.positionAtIndex(next);
if (lastPosition != null && position.getLine() == lastPosition.getLine()) {
// If there's two or more markers on the same line, any markers after the
// first will be off by one when we do the replacement.
position.setCharacter(position.getCharacter() - 1);
}
lastPosition = position;
positions.add(position);
i = next + 1;
}
Expand Down
30 changes: 28 additions & 2 deletions src/test/java/software/amazon/smithy/lsp/syntax/IdlParserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import software.amazon.smithy.lsp.TextWithPositions;
import software.amazon.smithy.lsp.document.Document;

public class IdlParserTest {
Expand Down Expand Up @@ -304,6 +305,27 @@ public void stringKeysInTraits() {
Syntax.Node.Type.Str));
}

@Test
public void traitApplicationsDontContainTrailingWhitespace() {
var twp = TextWithPositions.from("""
%@foo(foo: "")%
structure Foo {
foo: Foo
}
""");
Document document = Document.of(twp.text());
Syntax.IdlParseResult parse = Syntax.parseIdl(document);

assertThat(getTypes(parse), contains(
Syntax.Statement.Type.TraitApplication,
Syntax.Statement.Type.ShapeDef,
Syntax.Statement.Type.MemberDef));

Syntax.Statement traitApplication = parse.statements().get(0);
assertThat(document.positionAtIndex(traitApplication.start()), equalTo(twp.positions()[0]));
assertThat(document.positionAtIndex(traitApplication.end()), equalTo(twp.positions()[1]));
}

@ParameterizedTest
@MethodSource("brokenProvider")
public void broken(String desc, String text, List<String> expectedErrorMessages, List<Syntax.Statement.Type> expectedTypes) {
Expand Down Expand Up @@ -460,10 +482,14 @@ private static Stream<Arguments> brokenProvider() {

private static void assertTypesEqual(String text, Syntax.Statement.Type... types) {
Syntax.IdlParseResult parse = Syntax.parseIdl(Document.of(text));
List<Syntax.Statement.Type> actualTypes = parse.statements().stream()
var actualTypes = getTypes(parse);
assertThat(actualTypes, contains(types));
}

private static List<Syntax.Statement.Type> getTypes(Syntax.IdlParseResult parse) {
return parse.statements().stream()
.map(Syntax.Statement::type)
.filter(type -> type != Syntax.Statement.Type.Block)
.toList();
assertThat(actualTypes, contains(types));
}
}

0 comments on commit 8999cb9

Please sign in to comment.