1
0
mirror of https://github.com/robertkrimen/otto synced 2025-10-05 19:19:10 +08:00

fix: positions of statements (#506)

Fix the positions of various statements:
* Fix Idx1 of BranchStatement so that it points to the character after the label if Label exists,
  or the one after Token if Label does not exist.
* Fix Idx1 of LabelledStatement so that it points to the character after the statement.
* Fix Idx1 of ReturnStatement so that it points to the character after the argument if
  Argument exists, or the one after return keyword if Argument does not exist.
* Set Idx0 of SwitchStatement and fix Idx1 of SwitchStatement so that it points to the
  character after the right brace.
* Fix Idx0 of ThrowStatement to point to the start of throw keyword and fix Idx1 of
  ThrowStatement so that it points to the next character after Argument.
* Fix Idx1 of TryStatement to point to the character after Finally if Finally exists, or after Catch
  if Finally does not exist.
* Set Idx0 of WithStatement which was not previously set.
* Set WhileStatement.While so that Idx0 points to the right place.
* Set Idx0 of DoWhileStatement and fix Idx1 to point to the next character after the right
  parenthesis.
This commit is contained in:
Tomoki Yamaguchi 2023-07-26 02:25:01 +09:00 committed by GitHub
parent 589611c3ae
commit 11288b7564
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 124 additions and 23 deletions

View File

@ -543,16 +543,19 @@ type BranchStatement struct {
Label *Identifier
}
// Idx1 implements Node.
func (bs *BranchStatement) Idx1() file.Idx {
return bs.Idx
}
// Idx0 implements Node.
func (bs *BranchStatement) Idx0() file.Idx {
return bs.Idx
}
// Idx1 implements Node.
func (bs *BranchStatement) Idx1() file.Idx {
if bs.Label == nil {
return file.Idx(int(bs.Idx) + len(bs.Token.String()))
}
return bs.Label.Idx1()
}
// expression implements Statement.
func (*BranchStatement) statement() {}
@ -616,9 +619,10 @@ func (*DebuggerStatement) statement() {}
// DoWhileStatement represents a do while statement.
type DoWhileStatement struct {
Do file.Idx
Test Expression
Body Statement
Do file.Idx
Test Expression
Body Statement
RightParenthesis file.Idx
}
// Idx0 implements Node.
@ -628,7 +632,7 @@ func (dws *DoWhileStatement) Idx0() file.Idx {
// Idx1 implements Node.
func (dws *DoWhileStatement) Idx1() file.Idx {
return dws.Test.Idx1()
return dws.RightParenthesis + 1
}
// expression implements Statement.
@ -769,7 +773,7 @@ func (ls *LabelledStatement) Idx0() file.Idx {
// Idx1 implements Node.
func (ls *LabelledStatement) Idx1() file.Idx {
return ls.Colon + 1
return ls.Statement.Idx1()
}
// expression implements Statement.
@ -788,7 +792,10 @@ func (rs *ReturnStatement) Idx0() file.Idx {
// Idx1 implements Node.
func (rs *ReturnStatement) Idx1() file.Idx {
return rs.Return
if rs.Argument != nil {
return rs.Argument.Idx1()
}
return rs.Return + 6
}
// expression implements Statement.
@ -800,6 +807,7 @@ type SwitchStatement struct {
Discriminant Expression
Default int
Body []*CaseStatement
RightBrace file.Idx
}
// Idx0 implements Node.
@ -809,7 +817,7 @@ func (ss *SwitchStatement) Idx0() file.Idx {
// Idx1 implements Node.
func (ss *SwitchStatement) Idx1() file.Idx {
return ss.Body[len(ss.Body)-1].Idx1()
return ss.RightBrace + 1
}
// expression implements Statement.
@ -828,7 +836,7 @@ func (ts *ThrowStatement) Idx0() file.Idx {
// Idx1 implements Node.
func (ts *ThrowStatement) Idx1() file.Idx {
return ts.Throw
return ts.Argument.Idx1()
}
// expression implements Statement.
@ -849,7 +857,10 @@ func (ts *TryStatement) Idx0() file.Idx {
// Idx1 implements Node.
func (ts *TryStatement) Idx1() file.Idx {
return ts.Try
if ts.Finally != nil {
return ts.Finally.Idx1()
}
return ts.Catch.Idx1()
}
// expression implements Statement.

View File

@ -1025,7 +1025,8 @@ func TestPosition(t *testing.T) {
is(node.Idx0(), 14)
is(parser.slice(node.Idx0(), node.Idx1()), "if (abc) { throw 'failed'; }")
node = node.(*ast.IfStatement).Consequent.(*ast.BlockStatement).List[0].(*ast.ThrowStatement)
is(node.Idx0(), 39)
is(node.Idx0(), 25)
is(parser.slice(node.Idx0(), node.Idx1()), "throw 'failed'")
parser = newParser("", "(function(){ for (x=1; x<=4; x++) { console.log(x); } })", 1, nil)
program, err = parser.parse()
@ -1100,6 +1101,91 @@ func TestPosition(t *testing.T) {
node = block.List[0].(*ast.VariableStatement).List[1].(*ast.VariableExpression)
is(node.Idx0(), 23)
is(parser.slice(node.Idx0(), node.Idx1()), "xyz = 1")
parser = newParser("", "for (i = 0; i < 10; i++) { if (i == 5) break; }", 1, nil)
program, err = parser.parse()
is(err, nil)
block = program.Body[0].(*ast.ForStatement).Body.(*ast.BlockStatement)
node = block.List[0].(*ast.IfStatement).Consequent.(*ast.BranchStatement)
is(node.Idx0(), 40)
is(parser.slice(node.Idx0(), node.Idx1()), "break")
parser = newParser("", "(function(){ xyz: for (i = 0; i < 10; i++) { if (i == 5) continue xyz; } })", 1, nil)
program, err = parser.parse()
is(err, nil)
block = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)
node = block.List[0].(*ast.LabelledStatement)
is(node.Idx0(), 14)
is(parser.slice(node.Idx0(), node.Idx1()), "xyz: for (i = 0; i < 10; i++) { if (i == 5) continue xyz; }")
block = node.(*ast.LabelledStatement).Statement.(*ast.ForStatement).Body.(*ast.BlockStatement)
node = block.List[0].(*ast.IfStatement).Consequent.(*ast.BranchStatement)
is(node.Idx0(), 58)
is(parser.slice(node.Idx0(), node.Idx1()), "continue xyz")
parser = newParser("", "(function(){ return; })", 1, nil)
program, err = parser.parse()
is(err, nil)
block = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)
node = block.List[0].(*ast.ReturnStatement)
is(node.Idx0(), 14)
is(parser.slice(node.Idx0(), node.Idx1()), "return")
parser = newParser("", "(function(){ return 10; })", 1, nil)
program, err = parser.parse()
is(err, nil)
block = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)
node = block.List[0].(*ast.ReturnStatement)
is(node.Idx0(), 14)
is(parser.slice(node.Idx0(), node.Idx1()), "return 10")
parser = newParser("", "(function(){ switch (a) { default: return; }})", 1, nil)
program, err = parser.parse()
is(err, nil)
block = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)
node = block.List[0].(*ast.SwitchStatement)
is(node.Idx0(), 14)
is(parser.slice(node.Idx0(), node.Idx1()), "switch (a) { default: return; }")
parser = newParser("", "(function(){ try { a(); } catch (error) { b(); } })", 1, nil)
program, err = parser.parse()
is(err, nil)
block = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)
node = block.List[0].(*ast.TryStatement)
is(node.Idx0(), 14)
is(parser.slice(node.Idx0(), node.Idx1()), "try { a(); } catch (error) { b(); }")
node = block.List[0].(*ast.TryStatement).Catch
is(node.Idx0(), 27)
is(parser.slice(node.Idx0(), node.Idx1()), "catch (error) { b(); }")
parser = newParser("", "(function(){ try { a(); } catch (error) { b(); } finally { c(); } })", 1, nil)
program, err = parser.parse()
is(err, nil)
block = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)
node = block.List[0].(*ast.TryStatement)
is(node.Idx0(), 14)
is(parser.slice(node.Idx0(), node.Idx1()), "try { a(); } catch (error) { b(); } finally { c(); }")
parser = newParser("", "(function(){ with (1) {} })", 1, nil)
program, err = parser.parse()
is(err, nil)
block = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)
node = block.List[0].(*ast.WithStatement)
is(node.Idx0(), 14)
is(parser.slice(node.Idx0(), node.Idx1()), "with (1) {}")
parser = newParser("", "while (i < 10) { i++; }", 1, nil)
program, err = parser.parse()
is(err, nil)
node = program.Body[0].(*ast.WhileStatement)
is(node.Idx0(), 1)
is(parser.slice(node.Idx0(), node.Idx1()), "while (i < 10) { i++; }")
parser = newParser("", "do { i++; } while (i < 10 )", 1, nil)
program, err = parser.parse()
is(err, nil)
node = program.Body[0].(*ast.DoWhileStatement)
is(node.Idx0(), 1)
is(parser.slice(node.Idx0(), node.Idx1()), "do { i++; } while (i < 10 )")
})
}

View File

@ -356,7 +356,7 @@ func (p *parser) parseThrowStatement() ast.Statement {
}
node := &ast.ThrowStatement{
Throw: p.idx,
Throw: idx,
Argument: p.parseExpression(),
}
if p.mode&StoreComments != 0 {
@ -373,12 +373,13 @@ func (p *parser) parseSwitchStatement() ast.Statement {
if p.mode&StoreComments != 0 {
comments = p.comments.FetchAll()
}
p.expect(token.SWITCH)
idx := p.expect(token.SWITCH)
if p.mode&StoreComments != 0 {
comments = append(comments, p.comments.FetchAll()...)
}
p.expect(token.LEFT_PARENTHESIS)
node := &ast.SwitchStatement{
Switch: idx,
Discriminant: p.parseExpression(),
Default: -1,
}
@ -397,6 +398,7 @@ func (p *parser) parseSwitchStatement() ast.Statement {
for index := 0; p.token != token.EOF; index++ {
if p.token == token.RIGHT_BRACE {
node.RightBrace = p.idx
p.next()
break
}
@ -423,7 +425,7 @@ func (p *parser) parseWithStatement() ast.Statement {
if p.mode&StoreComments != 0 {
comments = p.comments.FetchAll()
}
p.expect(token.WITH)
idx := p.expect(token.WITH)
var withComments []*ast.Comment
if p.mode&StoreComments != 0 {
withComments = p.comments.FetchAll()
@ -432,6 +434,7 @@ func (p *parser) parseWithStatement() ast.Statement {
p.expect(token.LEFT_PARENTHESIS)
node := &ast.WithStatement{
With: idx,
Object: p.parseExpression(),
}
p.expect(token.RIGHT_PARENTHESIS)
@ -658,13 +661,13 @@ func (p *parser) parseDoWhileStatement() ast.Statement {
if p.mode&StoreComments != 0 {
comments = p.comments.FetchAll()
}
p.expect(token.DO)
idx := p.expect(token.DO)
var doComments []*ast.Comment
if p.mode&StoreComments != 0 {
doComments = p.comments.FetchAll()
}
node := &ast.DoWhileStatement{}
node := &ast.DoWhileStatement{Do: idx}
if p.token == token.LEFT_BRACE {
node.Body = p.parseBlockStatement()
} else {
@ -678,7 +681,7 @@ func (p *parser) parseDoWhileStatement() ast.Statement {
}
p.expect(token.LEFT_PARENTHESIS)
node.Test = p.parseExpression()
p.expect(token.RIGHT_PARENTHESIS)
node.RightParenthesis = p.expect(token.RIGHT_PARENTHESIS)
p.implicitSemicolon = true
p.optionalSemicolon()
@ -697,7 +700,7 @@ func (p *parser) parseWhileStatement() ast.Statement {
if p.mode&StoreComments != 0 {
comments = p.comments.FetchAll()
}
p.expect(token.WHILE)
idx := p.expect(token.WHILE)
var whileComments []*ast.Comment
if p.mode&StoreComments != 0 {
@ -706,7 +709,8 @@ func (p *parser) parseWhileStatement() ast.Statement {
p.expect(token.LEFT_PARENTHESIS)
node := &ast.WhileStatement{
Test: p.parseExpression(),
While: idx,
Test: p.parseExpression(),
}
p.expect(token.RIGHT_PARENTHESIS)
node.Body = p.parseIterationStatement()