102 lines
2.7 KiB
Go
102 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
//"io/ioutil"
|
|
|
|
"github.com/z7zmey/php-parser/node"
|
|
"github.com/z7zmey/php-parser/node/stmt"
|
|
"github.com/z7zmey/php-parser/walker"
|
|
)
|
|
|
|
type normaliseAltsPass struct {
|
|
}
|
|
|
|
func (np *normaliseAltsPass) transformNonRecursive(n node.Node) (node.Node, bool) {
|
|
|
|
switch n := n.(type) {
|
|
case *stmt.AltIf:
|
|
// Build replacement node
|
|
ifStmt := stmt.NewIf(n.Cond, n.Stmt, n.ElseIf, n.Else)
|
|
ifStmt.FreeFloating = n.FreeFloating
|
|
ifStmt.Position = n.Position
|
|
// ifStmt has no .Attributes prop
|
|
return ifStmt, true
|
|
|
|
case *stmt.AltElse:
|
|
elseStmt := stmt.NewElse(n.Stmt)
|
|
elseStmt.FreeFloating = n.FreeFloating
|
|
elseStmt.Position = n.Position
|
|
return elseStmt, true
|
|
|
|
case *stmt.AltElseIf:
|
|
elifStmt := stmt.NewElseIf(n.Cond, n.Stmt)
|
|
elifStmt.FreeFloating = n.FreeFloating
|
|
elifStmt.Position = n.Position
|
|
return elifStmt, true
|
|
|
|
default:
|
|
return n, false // no change
|
|
}
|
|
}
|
|
|
|
func (np *normaliseAltsPass) walkMutateArray(stmts []node.Node) {
|
|
for i, _ := range stmts {
|
|
np.walkMutate(&stmts[i])
|
|
}
|
|
}
|
|
|
|
func (np *normaliseAltsPass) walkMutate(child *node.Node) {
|
|
|
|
v2, didChange := np.transformNonRecursive(*child)
|
|
if didChange {
|
|
v2.Walk(np)
|
|
*child = v2
|
|
} else {
|
|
(*child).Walk(np)
|
|
}
|
|
}
|
|
|
|
func (np *normaliseAltsPass) EnterNode(w walker.Walkable) bool {
|
|
n, ok := w.(node.Node)
|
|
if !ok {
|
|
panic(fmt.Errorf("Tried to walk non-node '%t'", w))
|
|
}
|
|
|
|
// We need to override the .Walk() behaviour for all possible *parents*
|
|
// of affected nodes. This is because the .Walk() interface does not give
|
|
// us any opportunity to override single elements by the time we get there
|
|
// Our custom Walk() implementation is not firing all EnterChildList/LeaveNode
|
|
// visitors - but - that's fine since they're all noops anyway
|
|
|
|
switch n := n.(type) {
|
|
case *stmt.StmtList:
|
|
np.walkMutateArray(n.Stmts) // mutate slice in place
|
|
return false // Signal not to use upstream .Walk() implementation
|
|
|
|
case *node.Root:
|
|
np.walkMutateArray(n.Stmts) // mutate slice in place
|
|
return false // Signal not to use upstream .Walk() implementation
|
|
|
|
case *stmt.AltIf:
|
|
panic("altif")
|
|
np.walkMutate(&n.Cond)
|
|
np.walkMutateArray(n.ElseIf)
|
|
np.walkMutate(&n.Else)
|
|
return false
|
|
|
|
default:
|
|
// No normalisation needed for this node type
|
|
// Recurse deeper
|
|
return true
|
|
}
|
|
}
|
|
|
|
func (np *normaliseAltsPass) LeaveNode(w walker.Walkable) {}
|
|
func (np *normaliseAltsPass) EnterChildNode(key string, w walker.Walkable) {}
|
|
func (np *normaliseAltsPass) LeaveChildNode(key string, w walker.Walkable) {}
|
|
func (np *normaliseAltsPass) EnterChildList(key string, w walker.Walkable) {}
|
|
func (np *normaliseAltsPass) LeaveChildList(key string, w walker.Walkable) {}
|
|
|
|
var _ walker.Visitor = &normaliseAltsPass{} // interface assertion
|