Skip to content

Commit

Permalink
Fix indexes of nodes (#532)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
tyamagu2 authored Sep 19, 2023
1 parent 865aea3 commit fc55792
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 23 deletions.
45 changes: 31 additions & 14 deletions ast/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -442,6 +443,7 @@ type (
Discriminant Expression
Default int
Body []*CaseStatement
RightBrace file.Idx
}

ThrowStatement struct {
Expand Down Expand Up @@ -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 }
Expand Down Expand Up @@ -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() }
Expand Down Expand Up @@ -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() }
Expand All @@ -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()
Expand Down
77 changes: 77 additions & 0 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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++;
}`)
})
}

Expand Down
20 changes: 11 additions & 9 deletions parser/statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand All @@ -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
}
Expand All @@ -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()
Expand Down Expand Up @@ -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 {
Expand All @@ -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()
}
Expand All @@ -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()
Expand Down

0 comments on commit fc55792

Please sign in to comment.