From fc55792775de82c4841e3139fa6ef423ed1de659 Mon Sep 17 00:00:00 2001 From: Tomoki Yamaguchi Date: Wed, 20 Sep 2023 00:19:41 +0900 Subject: [PATCH] Fix indexes of nodes (#532) * Fix ConditionalExpression.Idx1() to point to the Idx1 of Alternate * Fix Idx0 of UnaryExpression in case of a postfix operation * Fix Idx1 of LabelledStatement to point to Idx1 of Statement * Set WhileStatement.While * Fix Idx0 and Idx1 of DoWhileStatement * Set WithStatement.With * Fix Idx1 of BranchStatement * Fix Idx1 of ReturnStatement when Argument exists * Set Switch and fix Idx1 of SwitchStatement --- ast/node.go | 45 +++++++++++++++++-------- parser/parser_test.go | 77 +++++++++++++++++++++++++++++++++++++++++++ parser/statement.go | 20 ++++++----- 3 files changed, 119 insertions(+), 23 deletions(-) diff --git a/ast/node.go b/ast/node.go index 176c1f3b..3bec89db 100644 --- a/ast/node.go +++ b/ast/node.go @@ -384,9 +384,10 @@ type ( } DoWhileStatement struct { - Do file.Idx - Test Expression - Body Statement + Do file.Idx + Test Expression + Body Statement + RightParenthesis file.Idx } EmptyStatement struct { @@ -442,6 +443,7 @@ type ( Discriminant Expression Default int Body []*CaseStatement + RightBrace file.Idx } ThrowStatement struct { @@ -669,8 +671,13 @@ func (self *TemplateElement) Idx0() file.Idx { return self.Idx } func (self *TemplateLiteral) Idx0() file.Idx { return self.OpenQuote } func (self *ThisExpression) Idx0() file.Idx { return self.Idx } func (self *SuperExpression) Idx0() file.Idx { return self.Idx } -func (self *UnaryExpression) Idx0() file.Idx { return self.Idx } -func (self *MetaProperty) Idx0() file.Idx { return self.Idx } +func (self *UnaryExpression) Idx0() file.Idx { + if self.Postfix { + return self.Operand.Idx0() + } + return self.Idx +} +func (self *MetaProperty) Idx0() file.Idx { return self.Idx } func (self *BadStatement) Idx0() file.Idx { return self.From } func (self *BlockStatement) Idx0() file.Idx { return self.LeftBrace } @@ -728,7 +735,7 @@ func (self *BinaryExpression) Idx1() file.Idx { return self.Right.Idx1() } func (self *BooleanLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } func (self *BracketExpression) Idx1() file.Idx { return self.RightBracket + 1 } func (self *CallExpression) Idx1() file.Idx { return self.RightParenthesis + 1 } -func (self *ConditionalExpression) Idx1() file.Idx { return self.Test.Idx1() } +func (self *ConditionalExpression) Idx1() file.Idx { return self.Alternate.Idx1() } func (self *DotExpression) Idx1() file.Idx { return self.Identifier.Idx1() } func (self *PrivateDotExpression) Idx1() file.Idx { return self.Identifier.Idx1() } func (self *FunctionLiteral) Idx1() file.Idx { return self.Body.Idx1() } @@ -764,13 +771,18 @@ func (self *MetaProperty) Idx1() file.Idx { return self.Property.Idx1() } -func (self *BadStatement) Idx1() file.Idx { return self.To } -func (self *BlockStatement) Idx1() file.Idx { return self.RightBrace + 1 } -func (self *BranchStatement) Idx1() file.Idx { return self.Idx } +func (self *BadStatement) Idx1() file.Idx { return self.To } +func (self *BlockStatement) Idx1() file.Idx { return self.RightBrace + 1 } +func (self *BranchStatement) Idx1() file.Idx { + if self.Label == nil { + return file.Idx(int(self.Idx) + len(self.Token.String())) + } + return self.Label.Idx1() +} func (self *CaseStatement) Idx1() file.Idx { return self.Consequent[len(self.Consequent)-1].Idx1() } func (self *CatchStatement) Idx1() file.Idx { return self.Body.Idx1() } func (self *DebuggerStatement) Idx1() file.Idx { return self.Debugger + 8 } -func (self *DoWhileStatement) Idx1() file.Idx { return self.Test.Idx1() } +func (self *DoWhileStatement) Idx1() file.Idx { return self.RightParenthesis + 1 } func (self *EmptyStatement) Idx1() file.Idx { return self.Semicolon + 1 } func (self *ExpressionStatement) Idx1() file.Idx { return self.Expression.Idx1() } func (self *ForInStatement) Idx1() file.Idx { return self.Body.Idx1() } @@ -782,11 +794,16 @@ func (self *IfStatement) Idx1() file.Idx { } return self.Consequent.Idx1() } -func (self *LabelledStatement) Idx1() file.Idx { return self.Colon + 1 } +func (self *LabelledStatement) Idx1() file.Idx { return self.Statement.Idx1() } func (self *Program) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() } -func (self *ReturnStatement) Idx1() file.Idx { return self.Return + 6 } -func (self *SwitchStatement) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() } -func (self *ThrowStatement) Idx1() file.Idx { return self.Argument.Idx1() } +func (self *ReturnStatement) Idx1() file.Idx { + if self.Argument != nil { + return self.Argument.Idx1() + } + return self.Return + 6 +} +func (self *SwitchStatement) Idx1() file.Idx { return self.RightBrace + 1 } +func (self *ThrowStatement) Idx1() file.Idx { return self.Argument.Idx1() } func (self *TryStatement) Idx1() file.Idx { if self.Finally != nil { return self.Finally.Idx1() diff --git a/parser/parser_test.go b/parser/parser_test.go index 341b1cf0..43924194 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -1087,6 +1087,83 @@ func TestPosition(t *testing.T) { is(err, nil) node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral) is(node.(*ast.FunctionLiteral).Source, "function(){ return abc; }") + node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.List[0].(*ast.ReturnStatement) + is(parser.slice(node.Idx0(), node.Idx1()), "return abc") + + parser = newParser("", "(function(){ return; })") + program, err = parser.parse() + is(err, nil) + node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.List[0].(*ast.ReturnStatement) + is(parser.slice(node.Idx0(), node.Idx1()), "return") + + parser = newParser("", "true ? 1 : 2") + program, err = parser.parse() + is(err, nil) + node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ConditionalExpression) + is(parser.slice(node.Idx0(), node.Idx1()), "true ? 1 : 2") + + parser = newParser("", "a++") + program, err = parser.parse() + is(err, nil) + node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.UnaryExpression) + is(parser.slice(node.Idx0(), node.Idx1()), "a++") + + parser = newParser("", "++a") + program, err = parser.parse() + is(err, nil) + node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.UnaryExpression) + is(parser.slice(node.Idx0(), node.Idx1()), "++a") + + parser = newParser("", "xyz: for (i = 0; i < 10; i++) { if (i == 5) continue xyz; }") + program, err = parser.parse() + is(err, nil) + node = program.Body[0].(*ast.LabelledStatement) + is(parser.slice(node.Idx0(), node.Idx1()), "xyz: for (i = 0; i < 10; i++) { if (i == 5) continue xyz; }") + node = program.Body[0].(*ast.LabelledStatement).Statement.(*ast.ForStatement) + is(parser.slice(node.Idx0(), node.Idx1()), "for (i = 0; i < 10; i++) { if (i == 5) continue xyz; }") + block := program.Body[0].(*ast.LabelledStatement).Statement.(*ast.ForStatement).Body.(*ast.BlockStatement) + node = block.List[0].(*ast.IfStatement).Consequent.(*ast.BranchStatement) + is(parser.slice(node.Idx0(), node.Idx1()), "continue xyz") + + parser = newParser("", "for (p in o) { break; }") + program, err = parser.parse() + is(err, nil) + node = program.Body[0].(*ast.ForInStatement) + is(parser.slice(node.Idx0(), node.Idx1()), "for (p in o) { break; }") + node = program.Body[0].(*ast.ForInStatement).Body.(*ast.BlockStatement).List[0].(*ast.BranchStatement) + is(parser.slice(node.Idx0(), node.Idx1()), "break") + + parser = newParser("", "while (i < 10) { i++; }") + program, err = parser.parse() + is(err, nil) + node = program.Body[0].(*ast.WhileStatement) + is(parser.slice(node.Idx0(), node.Idx1()), "while (i < 10) { i++; }") + + parser = newParser("", "do { i++; } while (i < 10 )") + program, err = parser.parse() + is(err, nil) + node = program.Body[0].(*ast.DoWhileStatement) + is(parser.slice(node.Idx0(), node.Idx1()), "do { i++; } while (i < 10 )") + + parser = newParser("", "with (1) {}") + program, err = parser.parse() + is(err, nil) + node = program.Body[0].(*ast.WithStatement) + is(parser.slice(node.Idx0(), node.Idx1()), "with (1) {}") + + parser = newParser("", `switch (a) { + case 1: x--; + case 2: + default: x++; +}`) + program, err = parser.parse() + is(err, nil) + node = program.Body[0].(*ast.SwitchStatement) + is(parser.slice(node.Idx0(), node.Idx1()), `switch (a) { + case 1: x--; + case 2: + default: x++; +}`) }) } diff --git a/parser/statement.go b/parser/statement.go index adc220a3..8ec5cdeb 100644 --- a/parser/statement.go +++ b/parser/statement.go @@ -511,9 +511,10 @@ func (self *_parser) parseThrowStatement() ast.Statement { } func (self *_parser) parseSwitchStatement() ast.Statement { - self.expect(token.SWITCH) + idx := self.expect(token.SWITCH) self.expect(token.LEFT_PARENTHESIS) node := &ast.SwitchStatement{ + Switch: idx, Discriminant: self.parseExpression(), Default: -1, } @@ -529,6 +530,7 @@ func (self *_parser) parseSwitchStatement() ast.Statement { for index := 0; self.token != token.EOF; index++ { if self.token == token.RIGHT_BRACE { + node.RightBrace = self.idx self.next() break } @@ -547,11 +549,10 @@ func (self *_parser) parseSwitchStatement() ast.Statement { } func (self *_parser) parseWithStatement() ast.Statement { - self.expect(token.WITH) + node := &ast.WithStatement{} + node.With = self.expect(token.WITH) self.expect(token.LEFT_PARENTHESIS) - node := &ast.WithStatement{ - Object: self.parseExpression(), - } + node.Object = self.parseExpression() self.expect(token.RIGHT_PARENTHESIS) self.scope.allowLet = false node.Body = self.parseStatement() @@ -816,8 +817,8 @@ func (self *_parser) parseDoWhileStatement() ast.Statement { self.scope.inIteration = inIteration }() - self.expect(token.DO) node := &ast.DoWhileStatement{} + node.Do = self.expect(token.DO) if self.token == token.LEFT_BRACE { node.Body = self.parseBlockStatement() } else { @@ -828,7 +829,7 @@ func (self *_parser) parseDoWhileStatement() ast.Statement { self.expect(token.WHILE) self.expect(token.LEFT_PARENTHESIS) node.Test = self.parseExpression() - self.expect(token.RIGHT_PARENTHESIS) + node.RightParenthesis = self.expect(token.RIGHT_PARENTHESIS) if self.token == token.SEMICOLON { self.next() } @@ -837,10 +838,11 @@ func (self *_parser) parseDoWhileStatement() ast.Statement { } func (self *_parser) parseWhileStatement() ast.Statement { - self.expect(token.WHILE) + idx := self.expect(token.WHILE) self.expect(token.LEFT_PARENTHESIS) node := &ast.WhileStatement{ - Test: self.parseExpression(), + While: idx, + Test: self.parseExpression(), } self.expect(token.RIGHT_PARENTHESIS) node.Body = self.parseIterationStatement()