Skip to content

Commit 28fd5e7

Browse files
committed
feat(lang): implement chomped text blocks
1 parent 87e08f4 commit 28fd5e7

File tree

4 files changed

+85
-5
lines changed

4 files changed

+85
-5
lines changed

rsjsonnet-lang/src/lexer/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,8 @@ impl<'a, 'p, 'ast> Lexer<'a, 'p, 'ast> {
472472

473473
#[inline]
474474
fn lex_text_block(&mut self) -> Result<Token<'p, 'ast>, LexError> {
475+
let strip_last_lf = self.eat_byte(b'-');
476+
475477
let mut string = String::new();
476478
let mut prefix;
477479
while self.eat_byte_if(|b| matches!(b, b' ' | b'\t' | b'\r')) {}
@@ -539,7 +541,15 @@ impl<'a, 'p, 'ast> Lexer<'a, 'p, 'ast> {
539541
}
540542
}
541543

542-
Ok(self.commit_token(TokenKind::TextBlock(self.ast_arena.alloc_str(&string))))
544+
let actual_string = if strip_last_lf {
545+
string.strip_suffix('\n').unwrap()
546+
} else {
547+
string.as_str()
548+
};
549+
550+
Ok(self.commit_token(TokenKind::TextBlock(
551+
self.ast_arena.alloc_str(actual_string),
552+
)))
543553
}
544554

545555
#[must_use]

rsjsonnet-lang/tests/lexer.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,22 @@ fn test_text_block() {
900900
test(b"|||\n a\n\t|||", "a\n");
901901
test(b"|||\n \xFF\n\t|||", "\u{FFFD}\n");
902902

903+
test(b"|||-\n \n|||", "");
904+
test(b"|||-\n a\n|||", "a");
905+
test(b"|||-\n \n a\n|||", "\na");
906+
test(b"|||- \n a\n|||", "a");
907+
test(b"|||-\t\n a\n|||", "a");
908+
test(b"|||-\n\n a\n|||", "\na");
909+
test(b"|||-\n\n\n a\n|||", "\n\na");
910+
test(b"|||-\n a\n b\n|||", "a\nb");
911+
test(b"|||-\n a\n b\n|||", "a\nb");
912+
test(b"|||-\n a\n\n b\n|||", "a\n\nb");
913+
test(b"|||-\n a\n \n b\n|||", "a\n\nb");
914+
test(b"|||-\n a\n\n\n b\n|||", "a\n\n\nb");
915+
test(b"|||-\n a\n b\n\n|||", "a\nb\n");
916+
test(b"|||-\n a\n\t|||", "a");
917+
test(b"|||-\n \xFF\n\t|||", "\u{FFFD}");
918+
903919
// error: unfinished
904920
LexerTest {
905921
input: b"|||\n a",
@@ -915,6 +931,20 @@ fn test_text_block() {
915931
}
916932
.run();
917933

934+
LexerTest {
935+
input: b"|||-\n a",
936+
check: |session, error, tokens| {
937+
assert_eq!(
938+
error,
939+
Some(LexError::UnfinishedString {
940+
span: session.intern_span(0, 7),
941+
}),
942+
);
943+
assert_eq!(tokens, []);
944+
},
945+
}
946+
.run();
947+
918948
// error: invalid start
919949
LexerTest {
920950
input: b"||| x\n y\n|||",
@@ -930,6 +960,20 @@ fn test_text_block() {
930960
}
931961
.run();
932962

963+
LexerTest {
964+
input: b"|||- x\n y\n|||",
965+
check: |session, error, tokens| {
966+
assert_eq!(
967+
error,
968+
Some(LexError::MissingLineBreakAfterTextBlockStart {
969+
span: session.intern_span(0, 5),
970+
}),
971+
);
972+
assert_eq!(tokens, []);
973+
},
974+
}
975+
.run();
976+
933977
LexerTest {
934978
input: b"|||\nx\ny\n|||",
935979
check: |session, error, tokens| {
@@ -943,6 +987,20 @@ fn test_text_block() {
943987
},
944988
}
945989
.run();
990+
991+
LexerTest {
992+
input: b"|||-\nx\ny\n|||",
993+
check: |session, error, tokens| {
994+
assert_eq!(
995+
error,
996+
Some(LexError::MissingWhitespaceTextBlockStart {
997+
span: session.intern_span(5, 5),
998+
}),
999+
);
1000+
assert_eq!(tokens, []);
1001+
},
1002+
}
1003+
.run();
9461004
}
9471005

9481006
#[test]

ui-tests/pass/text_block_crlf.jsonnet

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
local value = |||
1+
local value1 = |||
22
first line
33
second line
44
|||;
55

6-
std.assertEqual(value, "first line\r\nsecond line\r\n")
6+
local value2 = |||-
7+
first line
8+
second line
9+
|||;
10+
11+
std.assertEqual(value1, "first line\r\nsecond line\r\n") &&
12+
std.assertEqual(value2, "first line\r\nsecond line\r")

ui-tests/pass/text_block_lf.jsonnet

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
local value = |||
1+
local value1 = |||
22
first line
33
second line
44
|||;
55

6-
std.assertEqual(value, "first line\nsecond line\n")
6+
local value2 = |||-
7+
first line
8+
second line
9+
|||;
10+
11+
std.assertEqual(value1, "first line\nsecond line\n") &&
12+
std.assertEqual(value2, "first line\nsecond line")

0 commit comments

Comments
 (0)