Procházet zdrojové kódy

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
Tomoki Yamaguchi před 2 roky
rodič
revize
fc55792775
3 změnil soubory, kde provedl 119 přidání a 23 odebrání
  1. 31 14
      ast/node.go
  2. 77 0
      parser/parser_test.go
  3. 11 9
      parser/statement.go

+ 31 - 14
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()

+ 77 - 0
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++;
+}`)
 	})
 }
 

+ 11 - 9
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()