From b650c8c4250718bdee8604ce87f29a6540ece9ef Mon Sep 17 00:00:00 2001 From: kesonan Date: Sat, 18 Jan 2025 23:46:24 +0800 Subject: [PATCH] fix syntax of the key expression (#4586) --- .../goctl/pkg/parser/api/ast/infostatement.go | 3 +- .../goctl/pkg/parser/api/ast/kvexpression.go | 5 +- .../pkg/parser/api/ast/servicestatement.go | 6 +- tools/goctl/pkg/parser/api/parser/parser.go | 21 +++-- .../pkg/parser/api/parser/parser_test.go | 52 +++++------ .../parser/api/parser/testdata/example.api | 8 +- tools/goctl/pkg/parser/api/scanner/scanner.go | 10 --- .../pkg/parser/api/scanner/scanner_test.go | 89 +++++++++++++++---- tools/goctl/pkg/parser/api/token/token.go | 2 - 9 files changed, 127 insertions(+), 69 deletions(-) diff --git a/tools/goctl/pkg/parser/api/ast/infostatement.go b/tools/goctl/pkg/parser/api/ast/infostatement.go index 8aa0d1d0..c936d51c 100644 --- a/tools/goctl/pkg/parser/api/ast/infostatement.go +++ b/tools/goctl/pkg/parser/api/ast/infostatement.go @@ -46,7 +46,8 @@ func (i *InfoStmt) Format(prefix ...string) string { w.Write(withNode(infoNode, i.LParen)) w.NewLine() for _, v := range i.Values { - node := transferTokenNode(v.Key, withTokenNodePrefix(peekOne(prefix)+Indent), ignoreLeadingComment()) + node := transferNilInfixNode([]*TokenNode{v.Key, v.Colon}) + node = transferTokenNode(node, withTokenNodePrefix(peekOne(prefix)+Indent), ignoreLeadingComment()) w.Write(withNode(node, v.Value), expectIndentInfix(), expectSameLine()) w.NewLine() } diff --git a/tools/goctl/pkg/parser/api/ast/kvexpression.go b/tools/goctl/pkg/parser/api/ast/kvexpression.go index a5472407..cbd18eff 100644 --- a/tools/goctl/pkg/parser/api/ast/kvexpression.go +++ b/tools/goctl/pkg/parser/api/ast/kvexpression.go @@ -6,6 +6,8 @@ import "github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/token" type KVExpr struct { // Key is the key of the key value expression. Key *TokenNode + // Colon is the colon of the key value expression. + Colon *TokenNode // Value is the value of the key value expression. Value *TokenNode } @@ -24,7 +26,8 @@ func (i *KVExpr) CommentGroup() (head, leading CommentGroup) { func (i *KVExpr) Format(prefix ...string) string { w := NewBufferWriter() - w.Write(withNode(i.Key, i.Value), withPrefix(prefix...), withInfix(Indent), withRawText()) + node := transferNilInfixNode([]*TokenNode{i.Key, i.Colon}) + w.Write(withNode(node, i.Value), withPrefix(prefix...), withInfix(Indent), withRawText()) return w.String() } diff --git a/tools/goctl/pkg/parser/api/ast/servicestatement.go b/tools/goctl/pkg/parser/api/ast/servicestatement.go index ba0b704d..4489e320 100644 --- a/tools/goctl/pkg/parser/api/ast/servicestatement.go +++ b/tools/goctl/pkg/parser/api/ast/servicestatement.go @@ -46,7 +46,8 @@ func (a *AtServerStmt) Format(prefix ...string) string { w.Write(withNode(atServerNode, a.LParen), expectSameLine()) w.NewLine() for _, v := range a.Values { - node := transferTokenNode(v.Key, withTokenNodePrefix(peekOne(prefix)+Indent), ignoreLeadingComment()) + node := transferNilInfixNode([]*TokenNode{v.Key, v.Colon}) + node = transferTokenNode(node, withTokenNodePrefix(peekOne(prefix)+Indent), ignoreLeadingComment()) w.Write(withNode(node, v.Value), expectIndentInfix(), expectSameLine()) w.NewLine() } @@ -148,7 +149,8 @@ func (a *AtDocGroupStmt) Format(prefix ...string) string { w.Write(withNode(atDocNode, a.LParen), expectSameLine()) w.NewLine() for _, v := range a.Values { - node := transferTokenNode(v.Key, withTokenNodePrefix(peekOne(prefix)+Indent), ignoreLeadingComment()) + node := transferNilInfixNode([]*TokenNode{v.Key, v.Colon}) + node = transferTokenNode(node, withTokenNodePrefix(peekOne(prefix)+Indent), ignoreLeadingComment()) w.Write(withNode(node, v.Value), expectIndentInfix(), expectSameLine()) w.NewLine() } diff --git a/tools/goctl/pkg/parser/api/parser/parser.go b/tools/goctl/pkg/parser/api/parser/parser.go index d4c267d6..c4d7a512 100644 --- a/tools/goctl/pkg/parser/api/parser/parser.go +++ b/tools/goctl/pkg/parser/api/parser/parser.go @@ -545,7 +545,7 @@ func (p *Parser) parseAtDocGroupStmt() ast.AtDocStmt { } stmt.Values = append(stmt.Values, expr) - if p.notExpectPeekToken(token.RPAREN, token.KEY) { + if p.notExpectPeekToken(token.RPAREN, token.IDENT) { return nil } } @@ -605,7 +605,7 @@ func (p *Parser) parseAtServerStmt() *ast.AtServerStmt { } stmt.Values = append(stmt.Values, expr) - if p.notExpectPeekToken(token.RPAREN, token.KEY) { + if p.notExpectPeekToken(token.RPAREN, token.IDENT) { return nil } } @@ -1115,7 +1115,7 @@ func (p *Parser) parseInfoStmt() *ast.InfoStmt { } stmt.Values = append(stmt.Values, expr) - if p.notExpectPeekToken(token.RPAREN, token.KEY) { + if p.notExpectPeekToken(token.RPAREN, token.IDENT) { return nil } } @@ -1134,12 +1134,17 @@ func (p *Parser) parseAtServerKVExpression() *ast.KVExpr { var expr = &ast.KVExpr{} // token IDENT - if !p.advanceIfPeekTokenIs(token.KEY, token.RPAREN) { + if !p.advanceIfPeekTokenIs(token.IDENT, token.RPAREN) { return nil } expr.Key = p.curTokenNode() + if !p.advanceIfPeekTokenIs(token.COLON) { + return nil + } + expr.Colon = p.curTokenNode() + var valueTok token.Token var leadingCommentGroup ast.CommentGroup if p.notExpectPeekToken(token.QUO, token.DURATION, token.IDENT, token.INT, token.STRING) { @@ -1324,12 +1329,18 @@ func (p *Parser) parseKVExpression() *ast.KVExpr { var expr = &ast.KVExpr{} // token IDENT - if !p.advanceIfPeekTokenIs(token.KEY) { + if !p.advanceIfPeekTokenIs(token.IDENT) { return nil } expr.Key = p.curTokenNode() + // token COLON + if !p.advanceIfPeekTokenIs(token.COLON) { + return nil + } + expr.Colon = p.curTokenNode() + // token STRING if !p.advanceIfPeekTokenIs(token.STRING) { return nil diff --git a/tools/goctl/pkg/parser/api/parser/parser_test.go b/tools/goctl/pkg/parser/api/parser/parser_test.go index adc7b3ac..4d1cd9f6 100644 --- a/tools/goctl/pkg/parser/api/parser/parser_test.go +++ b/tools/goctl/pkg/parser/api/parser/parser_test.go @@ -125,11 +125,11 @@ var infoTestAPI string func TestParser_Parse_infoStmt(t *testing.T) { t.Run("valid", func(t *testing.T) { expected := map[string]string{ - "title:": `"type title here"`, - "desc:": `"type desc here"`, - "author:": `"type author here"`, - "email:": `"type email here"`, - "version:": `"type version here"`, + "title": `"type title here"`, + "desc": `"type desc here"`, + "author": `"type author here"`, + "email": `"type email here"`, + "version": `"type version here"`, } p := New("foo.api", infoTestAPI) result := p.Parse() @@ -285,27 +285,27 @@ var atServerTestAPI string func TestParser_Parse_atServerStmt(t *testing.T) { t.Run("valid", func(t *testing.T) { var expectedData = map[string]string{ - "foo:": `bar`, - "bar:": `baz`, - "baz:": `foo`, - "qux:": `/v1`, - "quux:": `/v1/v2`, - "middleware:": `M1,M2`, - "timeout1:": "1h", - "timeout2:": "10m", - "timeout3:": "10s", - "timeout4:": "10ms", - "timeout5:": "10µs", - "timeout6:": "10ns", - "timeout7:": "1h10m10s10ms10µs10ns", - "maxBytes:": `1024`, - "prefix:": "/v1", - "prefix1:": "/v1/v2_test/v2-beta", - "prefix2:": "v1/v2_test/v2-beta", - "prefix3:": "v1/v2_", - "prefix4:": "a-b-c", - "summary:": `"test"`, - "key:": `"bar"`, + "foo": `bar`, + "bar": `baz`, + "baz": `foo`, + "qux": `/v1`, + "quux": `/v1/v2`, + "middleware": `M1,M2`, + "timeout1": "1h", + "timeout2": "10m", + "timeout3": "10s", + "timeout4": "10ms", + "timeout5": "10µs", + "timeout6": "10ns", + "timeout7": "1h10m10s10ms10µs10ns", + "maxBytes": `1024`, + "prefix": "/v1", + "prefix1": "/v1/v2_test/v2-beta", + "prefix2": "v1/v2_test/v2-beta", + "prefix3": "v1/v2_", + "prefix4": "a-b-c", + "summary": `"test"`, + "key": `"bar"`, } p := New("foo.api", atServerTestAPI) diff --git a/tools/goctl/pkg/parser/api/parser/testdata/example.api b/tools/goctl/pkg/parser/api/parser/testdata/example.api index 078ef04c..8756edf6 100644 --- a/tools/goctl/pkg/parser/api/parser/testdata/example.api +++ b/tools/goctl/pkg/parser/api/parser/testdata/example.api @@ -151,13 +151,13 @@ service example { @doc ( desc: "path demo" ) - @handler postPath - post /example/path (PostPathReq) returns (PostPathResp) + @handler getPath + get /example/path (PostPathReq) returns (PostPathResp) } @server ( - group: array - prefix: /array + group : array + prefix : /array maxBytes: 1024 ) service example { diff --git a/tools/goctl/pkg/parser/api/scanner/scanner.go b/tools/goctl/pkg/parser/api/scanner/scanner.go index e1989104..992566f1 100644 --- a/tools/goctl/pkg/parser/api/scanner/scanner.go +++ b/tools/goctl/pkg/parser/api/scanner/scanner.go @@ -444,16 +444,6 @@ func (s *Scanner) scanIdent() token.Token { } ident := string(s.data[position:s.position]) - - if s.ch == ':' { - s.readRune() - return token.Token{ - Type: token.KEY, - Text: string(s.data[position:s.position]), - Position: s.newPosition(position), - } - } - if ident == "interface" && s.ch == '{' && s.peekRune() == '}' { s.readRune() s.readRune() diff --git a/tools/goctl/pkg/parser/api/scanner/scanner_test.go b/tools/goctl/pkg/parser/api/scanner/scanner_test.go index 42d20ff4..51e1e6e0 100644 --- a/tools/goctl/pkg/parser/api/scanner/scanner_test.go +++ b/tools/goctl/pkg/parser/api/scanner/scanner_test.go @@ -581,8 +581,8 @@ func TestScanner_NextToken_Key(t *testing.T) { }, }, { - Type: token.KEY, - Text: "foo:", + Type: token.IDENT, + Text: "foo", Position: token.Position{ Filename: "foo.api", Line: 2, @@ -590,14 +590,32 @@ func TestScanner_NextToken_Key(t *testing.T) { }, }, { - Type: token.KEY, - Text: "bar:", + Type: token.COLON, + Text: ":", + Position: token.Position{ + Filename: "foo.api", + Line: 2, + Column: 4, + }, + }, + { + Type: token.IDENT, + Text: "bar", Position: token.Position{ Filename: "foo.api", Line: 3, Column: 1, }, }, + { + Type: token.COLON, + Text: ":", + Position: token.Position{ + Filename: "foo.api", + Line: 3, + Column: 4, + }, + }, { Type: token.COLON, Text: ":", @@ -1090,50 +1108,75 @@ func TestScanner_NextToken(t *testing.T) { Position: position(3, 5), }, { - Type: token.KEY, - Text: `title:`, + Type: token.IDENT, + Text: `title`, Position: position(4, 5), }, + { + Type: token.COLON, + Text: `:`, + Position: position(4, 10), + }, { Type: token.STRING, Text: `"type title here"`, Position: position(4, 12), }, { - Type: token.KEY, - Text: `desc:`, + Type: token.IDENT, + Text: `desc`, Position: position(5, 5), }, + { + Type: token.COLON, + Text: `:`, + Position: position(5, 9), + }, { Type: token.STRING, Text: `"type desc here"`, Position: position(5, 11), }, { - Type: token.KEY, - Text: `author:`, + Type: token.IDENT, + Text: `author`, Position: position(6, 5), }, + { + Type: token.COLON, + Text: `:`, + Position: position(6, 11), + }, { Type: token.STRING, Text: `"type author here"`, Position: position(6, 13), }, { - Type: token.KEY, - Text: `email:`, + Type: token.IDENT, + Text: `email`, Position: position(7, 5), }, + { + Type: token.COLON, + Text: `:`, + Position: position(7, 10), + }, { Type: token.STRING, Text: `"type email here"`, Position: position(7, 12), }, { - Type: token.KEY, - Text: `version:`, + Type: token.IDENT, + Text: `version`, Position: position(8, 5), }, + { + Type: token.COLON, + Text: `:`, + Position: position(8, 12), + }, { Type: token.STRING, Text: `"type version here"`, @@ -1205,20 +1248,30 @@ func TestScanner_NextToken(t *testing.T) { Position: position(20, 8), }, { - Type: token.KEY, - Text: `jwt:`, + Type: token.IDENT, + Text: `jwt`, Position: position(21, 5), }, + { + Type: token.COLON, + Text: `:`, + Position: position(21, 8), + }, { Type: token.IDENT, Text: `Auth`, Position: position(21, 10), }, { - Type: token.KEY, - Text: `group:`, + Type: token.IDENT, + Text: `group`, Position: position(22, 5), }, + { + Type: token.COLON, + Text: `:`, + Position: position(22, 10), + }, { Type: token.IDENT, Text: `template`, diff --git a/tools/goctl/pkg/parser/api/token/token.go b/tools/goctl/pkg/parser/api/token/token.go index 627a20f8..aaec895c 100644 --- a/tools/goctl/pkg/parser/api/token/token.go +++ b/tools/goctl/pkg/parser/api/token/token.go @@ -127,7 +127,6 @@ const ( STRING // "abc" RAW_STRING // `abc` PATH // `abc` - KEY // `abc:` literal_end operator_beg @@ -213,7 +212,6 @@ var tokens = [...]string{ STRING: "STRING", RAW_STRING: "RAW_STRING", PATH: "PATH", - KEY: "KEY", SUB: "-", MUL: "*",