From d1f44bd8774d62f7f0f394797f3c4f1dd7f63d36 Mon Sep 17 00:00:00 2001 From: Dmitry Stoletov Date: Tue, 9 Feb 2021 11:41:46 +0300 Subject: [PATCH 1/2] fix funccall with fieldAccessor e.g. a().b() a():b() Signed-off-by: Dmitry Stoletov --- formatter/body.go | 27 +++++++ formatter/exp.go | 8 +- formatter/parser.go | 18 +++-- formatter/prefixexp.go | 52 +++++++++---- formatter/statement_assigment_test.go | 6 +- formatter/statement_func.go | 14 ++-- formatter/statement_func_test.go | 24 +++--- formatter/statement_funccall.go | 10 ++- formatter/statement_funccall_test.go | 102 ++++++++++++++++++++++++++ formatter/statement_return_test.go | 18 ++--- 10 files changed, 224 insertions(+), 55 deletions(-) diff --git a/formatter/body.go b/formatter/body.go index dcf2760..dee134b 100644 --- a/formatter/body.go +++ b/formatter/body.go @@ -15,6 +15,7 @@ package formatter import ( + "errors" "io" ) @@ -70,6 +71,28 @@ func (b *body) AppendStatement(st statement) { b.Qty++ } +var errStatementNotExist = errors.New("statement not exist") + +func (b *body) RemoveStatement(st statement) error { + for i := len(b.Blocks) - 1; i >= 0; i-- { + if b.Blocks[uint64(i)] == st { + b.Blocks[uint64(i)] = nil + return nil + } + } + + return errStatementNotExist +} + +func bodyRemoveStatement(haystack, needle statement) error { + v, ok := haystack.(*body) + if !ok { + return errCastingType + } + + return v.RemoveStatement(needle) +} + func (b *body) GetStatement(prev, cur *element) statement { if prev != nil && prev.Token.Type == nLocal { if cur.Token.Type == nID { @@ -131,6 +154,10 @@ func (b *body) Format(c *Config, p printer, w io.Writer) error { for i := 0; i < int(b.Qty); i++ { st := b.Blocks[uint64(i)] + if st == nil { + continue + } + if !p.IgnoreFirstPad { _, newlineOk := st.(*newlineStatement) commentSt, commentOk := st.(*commentStatement) diff --git a/formatter/exp.go b/formatter/exp.go index 43aa872..83c89fa 100644 --- a/formatter/exp.go +++ b/formatter/exp.go @@ -364,10 +364,10 @@ func (s *exp) AppendStatement(st statement) { s.Prefixexp = &prefixexpStatement{FuncCall: v} // a = func[0].call{} case *prefixexpStatement: - if s.Element != nil { - v.Element = s.Element - s.Element = nil - } + // if s.Element != nil { + // v.Element = s.Element + // s.Element = nil + // } s.Prefixexp = v } diff --git a/formatter/parser.go b/formatter/parser.go index fbefacd..88ee6b2 100644 --- a/formatter/parser.go +++ b/formatter/parser.go @@ -14,6 +14,8 @@ package formatter +import "fmt" + // Parse code. func parse(code []byte) (*document, error) { var ( @@ -45,11 +47,11 @@ func parse(code []byte) (*document, error) { curElement = &el - // if prevElement != nil { - // fmt.Printf("%s%s %s%s = ", mMagenta, TokenIDs[prevElement.Token.Type], prevElement.Token.Value, defaultStyle) - // } + if prevElement != nil { + fmt.Printf("%s%s %s%s = ", mMagenta, TokenIDs[prevElement.Token.Type], prevElement.Token.Value, defaultStyle) + } - // fmt.Printf("%s%s %s%s\n", mMagenta, TokenIDs[el.Token.Type], el.Token.Value, defaultStyle) + fmt.Printf("%s%s %s%s\n", mMagenta, TokenIDs[el.Token.Type], el.Token.Value, defaultStyle) for isBlockEnd, ok := currentStatement.IsEnd(prevElement, curElement); ok; isBlockEnd, ok = currentStatement.IsEnd(prevElement, curElement) { if currentStatement.TypeOf() == tsUnknow && curElement.Token.Type == nComma { @@ -57,6 +59,7 @@ func parse(code []byte) (*document, error) { } cs := chainSt.ExtractPrev() + fmt.Printf("-- ex %p %#v\n", cs, cs) if cs == nil { currentBody = doc.Body chainSt.Append(currentBody) @@ -82,6 +85,7 @@ func parse(code []byte) (*document, error) { } if st := currentStatement.GetStatement(prevElement, curElement); st != nil { + fmt.Printf("-- st %p %#v\n", st, st) var assignmentWithOneVar statement isPrefixexpConvertAssignment := false @@ -112,6 +116,10 @@ func parse(code []byte) (*document, error) { st.AppendStatement(extracted) chainSt.Prev().AppendStatement(st) + } else if currentStatement.TypeOf() == tsFuncCallStatement && st.TypeOf() == tsPrefixexpStatement { + extracted := chainSt.ExctractStatement(tsFuncCallStatement) + bodyRemoveStatement(chainSt.GetLastBody(), extracted) + chainSt.GetLastBody().AppendStatement(st) } else if currentStatement.TypeOf() == tsUnknow && st.TypeOf() == tsFuncCallStatement { st.AppendStatement(chainSt.ExctractStatement(tsUnknow)) chainSt.Prev().AppendStatement(st) @@ -133,7 +141,7 @@ func parse(code []byte) (*document, error) { st.AppendStatement(inner) chainSt.Append(inner) // } - + fmt.Printf("-- in %p %#v\n", inner, inner) st = inner if isBreak { diff --git a/formatter/prefixexp.go b/formatter/prefixexp.go index 7dee93d..3fe0f0a 100644 --- a/formatter/prefixexp.go +++ b/formatter/prefixexp.go @@ -52,6 +52,18 @@ func (s *prefixexpStatement) InnerStatement(prev, cur *element) (bool, statement return false, &funcCallStatement{} } + if cur.Token.Type == nDot { + if prev != nil && prev.Token.Type == nClosingParentheses { + return true, &prefixexpStatement{} + } + } + + if cur.Token.Type == nColon { + if prev != nil && prev.Token.Type == nClosingParentheses { + return true, &prefixexpStatement{} + } + } + return false, nil } @@ -98,6 +110,10 @@ func (s *prefixexpStatement) IsEnd(prev, cur *element) (bool, bool) { return false, false // .id } + if prev != nil && prev.Token.Type == nColon && cur.Token.Type == nID { // function call + return false, false // :id + } + if cur.Token.Type == nComma { // assignment statement return false, true } @@ -149,7 +165,7 @@ func (s *prefixexpStatement) Append(el *element) { return } - if el.Token.Type == nDot { + if el.Token.Type == nDot || el.Token.Type == nColon { s.FieldAccessor = el return @@ -159,8 +175,16 @@ func (s *prefixexpStatement) Append(el *element) { return } - if s.FieldAccessor != nil && s.FieldAccessor.Token.Type == nDot { // .id - s.FieldAccessor = el + if s.FieldAccessor != nil { + if s.FieldAccessor.Token.Type == nDot { // .id + s.Element = s.FieldAccessor + s.FieldAccessor = el + } + + if s.FieldAccessor.Token.Type == nColon { // :id + s.Element = s.FieldAccessor + s.FieldAccessor = el + } return } @@ -197,7 +221,9 @@ func (s *prefixexpStatement) GetStatement(prev, cur *element) statement { } if cur.Token.Type == nParentheses || cur.Token.Type == nString { - return &funcCallStatement{} + return &funcCallStatement{ + // TODO Prefixexp: s, + } } if cur.Token.Type == nCurlyBracket { @@ -232,6 +258,12 @@ func (s *prefixexpStatement) Format(c *Config, p printer, w io.Writer) error { } } + if st := s.FuncCall; st != nil { + if err := st.Format(c, p, w); err != nil { + return err + } + } + if st := s.Element; st != nil { if err := st.Format(c, p, w); err != nil { return err @@ -263,9 +295,9 @@ func (s *prefixexpStatement) Format(c *Config, p printer, w io.Writer) error { } if st := s.FieldAccessor; st != nil { - if _, err := w.Write([]byte(".")); err != nil { - return err - } + // if _, err := w.Write([]byte(".")); err != nil { + // return err + // } if err := st.Format(c, p, w); err != nil { return err @@ -278,11 +310,5 @@ func (s *prefixexpStatement) Format(c *Config, p printer, w io.Writer) error { } } - if st := s.FuncCall; st != nil { - if err := st.Format(c, p, w); err != nil { - return err - } - } - return nil } diff --git a/formatter/statement_assigment_test.go b/formatter/statement_assigment_test.go index c19f37e..f4424bc 100644 --- a/formatter/statement_assigment_test.go +++ b/formatter/statement_assigment_test.go @@ -196,9 +196,9 @@ myvar = function() end List: []*exp{{}}, }, }, - Body: &body{ - Blocks: make(map[uint64]statement), - }, + // Body: &body{ + // Blocks: make(map[uint64]statement), + // }, }, }, }, diff --git a/formatter/statement_func.go b/formatter/statement_func.go index 21b2719..25e315c 100644 --- a/formatter/statement_func.go +++ b/formatter/statement_func.go @@ -66,7 +66,7 @@ func (s *functionStatement) AppendStatement(st statement) { } func (s *functionStatement) GetBody(prevSt statement, cur *element) statement { - if cur.Token.Type != nClosingParentheses { + if s.FuncCall == nil { return prevSt } @@ -123,13 +123,13 @@ func (s *functionStatement) Format(c *Config, p printer, w io.Writer) error { if err := st.Format(c, inner, w); err != nil { return err } - } - if st.Qty > 0 { - // a = function() - // end - if err := newLine(w); err != nil { - return err + if st.Qty > 0 { + // a = function() + // end + if err := newLine(w); err != nil { + return err + } } } diff --git a/formatter/statement_func_test.go b/formatter/statement_func_test.go index 6c40dbf..ce0307d 100644 --- a/formatter/statement_func_test.go +++ b/formatter/statement_func_test.go @@ -52,9 +52,9 @@ end List: []*exp{{}}, }, }, - Body: &body{ - Blocks: make(map[uint64]statement), - }, + // Body: &body{ + // Blocks: make(map[uint64]statement), + // }, }, }, Qty: 1, @@ -95,9 +95,9 @@ end List: []*exp{{}}, }, }, - Body: &body{ - Blocks: make(map[uint64]statement), - }, + // Body: &body{ + // Blocks: make(map[uint64]statement), + // }, }, }, Qty: 1, @@ -141,9 +141,9 @@ end List: []*exp{{}}, }, }, - Body: &body{ - Blocks: make(map[uint64]statement), - }, + // Body: &body{ + // Blocks: make(map[uint64]statement), + // }, }, 1: &newlineStatement{}, 2: &functionStatement{ @@ -166,9 +166,9 @@ end List: []*exp{{}}, }, }, - Body: &body{ - Blocks: make(map[uint64]statement), - }, + // Body: &body{ + // Blocks: make(map[uint64]statement), + // }, }, }, Qty: 3, diff --git a/formatter/statement_funccall.go b/formatter/statement_funccall.go index 4aa1e53..6d066fc 100644 --- a/formatter/statement_funccall.go +++ b/formatter/statement_funccall.go @@ -32,8 +32,8 @@ func (funcCallStatement) TypeOf() typeStatement { } func (s *funcCallStatement) IsEnd(prev, cur *element) (bool, bool) { - if cur.Token.Type == nClosingParentheses { - return true, true + if cur.Token.Type == nClosingParentheses || cur.Token.Type == nDot || cur.Token.Type == nColon { + return false, false } return false, true @@ -56,6 +56,12 @@ func (s *funcCallStatement) GetBody(prevSt statement, cur *element) statement { } func (s *funcCallStatement) GetStatement(prev, cur *element) statement { + if cur.Token.Type == nDot || cur.Token.Type == nColon { + return &prefixexpStatement{ + FuncCall: s, + } + } + return nil } diff --git a/formatter/statement_funccall_test.go b/formatter/statement_funccall_test.go index c9d3919..3871ad4 100644 --- a/formatter/statement_funccall_test.go +++ b/formatter/statement_funccall_test.go @@ -111,6 +111,108 @@ funccall "literal" }, wantErr: false, }, + { + skip: false, + name: "funccall statement of table with funccall statement and etc", + args: args{ + code: []byte(` +a.b().c().d() +`, + ), + }, + want: &document{ + Body: &body{ + Blocks: map[uint64]statement{ + 0: nil, + 1: nil, + 2: &funcCallStatement{ + Prefixexp: &prefixexpStatement{ + FuncCall: &funcCallStatement{ + Prefixexp: &prefixexpStatement{ + FuncCall: &funcCallStatement{ + Prefixexp: &prefixexpStatement{ + Element: &element{ + Token: &lexmachine.Token{ + Type: nID, + Value: "a", + Lexeme: []byte("a"), + TC: 1, + StartLine: 2, + StartColumn: 1, + EndLine: 2, + EndColumn: 1, + }, + }, + Prefixexp: &prefixexpStatement{ + FieldAccessor: &element{ + Token: &lexmachine.Token{ + Type: nID, + Value: "b", + Lexeme: []byte("b"), + TC: 3, + StartLine: 2, + StartColumn: 3, + EndLine: 2, + EndColumn: 3, + }, + }, + }, + IsUnknow: true, + }, + Explist: &explist{ + List: []*exp{ + {}, + }, + }, + }, + Prefixexp: &prefixexpStatement{ + FieldAccessor: &element{ + Token: &lexmachine.Token{ + Type: nID, + Value: "c", + Lexeme: []byte("c"), + TC: 7, + StartLine: 2, + StartColumn: 7, + EndLine: 2, + EndColumn: 7, + }, + }, + }, + }, + Explist: &explist{ + List: []*exp{ + {}, + }, + }, + }, + Prefixexp: &prefixexpStatement{ + FieldAccessor: &element{ + Token: &lexmachine.Token{ + Type: nID, + Value: "d", + Lexeme: []byte("d"), + TC: 11, + StartLine: 2, + StartColumn: 11, + EndLine: 2, + EndColumn: 11, + }, + }, + }, + }, + Explist: &explist{ + List: []*exp{ + {}, + }, + }, + }, + }, + Qty: 3, + }, + }, + wantErr: false, + }, } for _, tt := range tests { if tt.skip == true { diff --git a/formatter/statement_return_test.go b/formatter/statement_return_test.go index 57f00ed..e36c274 100644 --- a/formatter/statement_return_test.go +++ b/formatter/statement_return_test.go @@ -286,9 +286,9 @@ return function () end List: []*exp{{}}, }, }, - Body: &body{ - Blocks: make(map[uint64]statement), - }, + // Body: &body{ + // Blocks: make(map[uint64]statement), + // }, }, }, }, @@ -323,9 +323,9 @@ return function () end, function () end List: []*exp{{}}, }, }, - Body: &body{ - Blocks: make(map[uint64]statement), - }, + // Body: &body{ + // Blocks: make(map[uint64]statement), + // }, }, }, { @@ -336,9 +336,9 @@ return function () end, function () end List: []*exp{{}}, }, }, - Body: &body{ - Blocks: make(map[uint64]statement), - }, + // Body: &body{ + // Blocks: make(map[uint64]statement), + // }, }, }, }, From 8ae48a069bff6d9d060f4905d7b9a35397eebd2c Mon Sep 17 00:00:00 2001 From: Dmitry Stoletov Date: Fri, 12 Feb 2021 12:03:28 +0300 Subject: [PATCH 2/2] exp innner statement returns prefixexpStatement Signed-off-by: Dmitry Stoletov --- formatter/exp.go | 4 ++++ formatter/parser.go | 24 +++++++++++++++++------- formatter/prefixexp.go | 2 +- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/formatter/exp.go b/formatter/exp.go index 83c89fa..d3cc187 100644 --- a/formatter/exp.go +++ b/formatter/exp.go @@ -50,6 +50,10 @@ func (exp) InnerStatement(prev, cur *element) (bool, statement) { } return false, &prefixexpStatement{Enclosed: true} + + case nID: + //z = a().b() + return true, &prefixexpStatement{} } return false, nil diff --git a/formatter/parser.go b/formatter/parser.go index 88ee6b2..9dcae96 100644 --- a/formatter/parser.go +++ b/formatter/parser.go @@ -39,6 +39,8 @@ func parse(code []byte) (*document, error) { currentBody = b currentStatement = b + logging := true + for s.Next() { el, err := s.Scan() if err != nil { @@ -47,11 +49,13 @@ func parse(code []byte) (*document, error) { curElement = &el - if prevElement != nil { - fmt.Printf("%s%s %s%s = ", mMagenta, TokenIDs[prevElement.Token.Type], prevElement.Token.Value, defaultStyle) - } + if logging { + if prevElement != nil { + fmt.Printf("%s%s %s%s = ", mMagenta, TokenIDs[prevElement.Token.Type], prevElement.Token.Value, defaultStyle) + } - fmt.Printf("%s%s %s%s\n", mMagenta, TokenIDs[el.Token.Type], el.Token.Value, defaultStyle) + fmt.Printf("%s%s %s%s\n", mMagenta, TokenIDs[el.Token.Type], el.Token.Value, defaultStyle) + } for isBlockEnd, ok := currentStatement.IsEnd(prevElement, curElement); ok; isBlockEnd, ok = currentStatement.IsEnd(prevElement, curElement) { if currentStatement.TypeOf() == tsUnknow && curElement.Token.Type == nComma { @@ -59,7 +63,9 @@ func parse(code []byte) (*document, error) { } cs := chainSt.ExtractPrev() - fmt.Printf("-- ex %p %#v\n", cs, cs) + if logging { + fmt.Printf("-- ex %p %#v\n", cs, cs) + } if cs == nil { currentBody = doc.Body chainSt.Append(currentBody) @@ -85,7 +91,9 @@ func parse(code []byte) (*document, error) { } if st := currentStatement.GetStatement(prevElement, curElement); st != nil { - fmt.Printf("-- st %p %#v\n", st, st) + if logging { + fmt.Printf("-- st %p %#v\n", st, st) + } var assignmentWithOneVar statement isPrefixexpConvertAssignment := false @@ -141,7 +149,9 @@ func parse(code []byte) (*document, error) { st.AppendStatement(inner) chainSt.Append(inner) // } - fmt.Printf("-- in %p %#v\n", inner, inner) + if logging { + fmt.Printf("-- in %p %#v\n", inner, inner) + } st = inner if isBreak { diff --git a/formatter/prefixexp.go b/formatter/prefixexp.go index 3fe0f0a..27fd411 100644 --- a/formatter/prefixexp.go +++ b/formatter/prefixexp.go @@ -36,7 +36,7 @@ func (s *prefixexpStatement) InnerStatement(prev, cur *element) (bool, statement if cur.Token.Type == nParentheses { if prev != nil && prev.Token.Type == nID { - return false, &funcCallStatement{} + return false, &funcCallStatement{} // Element: cur } s.Enclosed = true