From bc8f18005540c48748f76f296712c65c4c4daf2e Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Tue, 6 Jun 2023 14:47:40 -0700 Subject: [PATCH] d2parser: Error on unquoted strings starting with ...@ --- d2ast/d2ast.go | 7 +++ d2parser/parse.go | 8 ++++ d2parser/parse_test.go | 6 +++ .../d2parser/TestParse/import/#03.exp.json | 2 +- .../d2parser/TestParse/import/#08.exp.json | 48 +++++++++++++++++++ 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 testdata/d2parser/TestParse/import/#08.exp.json diff --git a/d2ast/d2ast.go b/d2ast/d2ast.go index 40979145e..9ffdcd76e 100644 --- a/d2ast/d2ast.go +++ b/d2ast/d2ast.go @@ -257,6 +257,13 @@ func (p Position) Subtract(r rune, byUTF16 bool) Position { return p } +func (p Position) AdvanceString(s string, byUTF16 bool) Position { + for _, r := range s { + p = p.Advance(r, byUTF16) + } + return p +} + func (p Position) SubtractString(s string, byUTF16 bool) Position { for _, r := range s { p = p.Subtract(r, byUTF16) diff --git a/d2parser/parse.go b/d2parser/parse.go index a19690081..f388d4926 100644 --- a/d2parser/parse.go +++ b/d2parser/parse.go @@ -1046,6 +1046,14 @@ func (p *parser) parseUnquotedString(inKey bool) (s *d2ast.UnquotedString) { s.Value = append(s.Value, d2ast.InterpolationBox{String: &sv, StringRaw: &rawv}) }() + _s, eof := p.peekn(4) + p.rewind() + if !eof { + if _s == "...@" { + p.errorf(p.readerPos, p.pos.AdvanceString("...@", p.utf16), "unquoted strings cannot begin with ...@ as that's import spread syntax") + } + } + for { r, eof := p.peek() if eof { diff --git a/d2parser/parse_test.go b/d2parser/parse_test.go index ffe2464b5..cca249787 100644 --- a/d2parser/parse_test.go +++ b/d2parser/parse_test.go @@ -463,6 +463,12 @@ func testImport(t *testing.T) { assert.ErrorString(t, err, "d2/testdata/d2parser/TestParse/import/#07.d2:1:1: @file is not a valid import, did you mean ...@file?") }, }, + { + text: "meow: ...@file", + assert: func(t testing.TB, ast *d2ast.Map, err error) { + assert.ErrorString(t, err, "d2/testdata/d2parser/TestParse/import/#08.d2:1:10: unquoted strings cannot begin with ...@ as that's import spread syntax") + }, + }, } runa(t, tca) diff --git a/testdata/d2parser/TestParse/import/#03.exp.json b/testdata/d2parser/TestParse/import/#03.exp.json index f964faf08..95c1a6f95 100644 --- a/testdata/d2parser/TestParse/import/#03.exp.json +++ b/testdata/d2parser/TestParse/import/#03.exp.json @@ -24,7 +24,7 @@ "primary": {}, "value": { "array": { - "range": "d2/testdata/d2parser/TestParse/import/#03.d2,0:3:3-0:15:15", + "range": "d2/testdata/d2parser/TestParse/import/#03.d2,0:3:3-0:16:16", "nodes": [ { "import": { diff --git a/testdata/d2parser/TestParse/import/#08.exp.json b/testdata/d2parser/TestParse/import/#08.exp.json new file mode 100644 index 000000000..a79694a98 --- /dev/null +++ b/testdata/d2parser/TestParse/import/#08.exp.json @@ -0,0 +1,48 @@ +{ + "ast": { + "range": "d2/testdata/d2parser/TestParse/import/#08.d2,0:0:0-0:14:14", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2parser/TestParse/import/#08.d2,0:0:0-0:14:14", + "key": { + "range": "d2/testdata/d2parser/TestParse/import/#08.d2,0:0:0-0:4:4", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2parser/TestParse/import/#08.d2,0:0:0-0:4:4", + "value": [ + { + "string": "meow", + "raw_string": "meow" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2parser/TestParse/import/#08.d2,0:6:6-0:14:14", + "value": [ + { + "string": "...@file", + "raw_string": "...@file" + } + ] + } + } + } + } + ] + }, + "err": { + "errs": [ + { + "range": "d2/testdata/d2parser/TestParse/import/#08.d2,0:9:9-0:10:10", + "errmsg": "d2/testdata/d2parser/TestParse/import/#08.d2:1:10: unquoted strings cannot begin with ...@ as that's import spread syntax" + } + ] + } +}