refactoring: update traverser
This commit is contained in:
2345
pkg/visitor/dumper/dumper.go
Normal file
2345
pkg/visitor/dumper/dumper.go
Normal file
File diff suppressed because it is too large
Load Diff
76
pkg/visitor/dumper/dumper_test.go
Normal file
76
pkg/visitor/dumper/dumper_test.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package dumper_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/z7zmey/php-parser/pkg/position"
|
||||
"github.com/z7zmey/php-parser/pkg/token"
|
||||
"github.com/z7zmey/php-parser/pkg/visitor/dumper"
|
||||
"testing"
|
||||
|
||||
"github.com/z7zmey/php-parser/pkg/ast"
|
||||
)
|
||||
|
||||
func TestDumper_root(t *testing.T) {
|
||||
o := bytes.NewBufferString("")
|
||||
|
||||
p := dumper.NewDumper(o).WithTokens().WithPositions()
|
||||
n := &ast.Root{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 2,
|
||||
StartPos: 3,
|
||||
EndPos: 4,
|
||||
},
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtNop{},
|
||||
},
|
||||
EndTkn: &token.Token{
|
||||
FreeFloating: []*token.Token{
|
||||
{
|
||||
ID: token.T_WHITESPACE,
|
||||
Value: []byte(" "),
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 2,
|
||||
StartPos: 3,
|
||||
EndPos: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
n.Accept(p)
|
||||
|
||||
expected := `&ast.Root{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 2,
|
||||
StartPos: 3,
|
||||
EndPos: 4,
|
||||
},
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtNop{
|
||||
},
|
||||
},
|
||||
EndTkn: &token.Token{
|
||||
FreeFloating: []*token.Token{
|
||||
{
|
||||
ID: token.T_WHITESPACE,
|
||||
Value: []byte(" "),
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 2,
|
||||
StartPos: 3,
|
||||
EndPos: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
`
|
||||
actual := o.String()
|
||||
|
||||
if expected != actual {
|
||||
t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
|
||||
}
|
||||
}
|
||||
2040
pkg/visitor/formatter/formatter.go
Normal file
2040
pkg/visitor/formatter/formatter.go
Normal file
File diff suppressed because it is too large
Load Diff
6802
pkg/visitor/formatter/formatter_test.go
Normal file
6802
pkg/visitor/formatter/formatter_test.go
Normal file
File diff suppressed because it is too large
Load Diff
404
pkg/visitor/nsresolver/namespace_resolver.go
Normal file
404
pkg/visitor/nsresolver/namespace_resolver.go
Normal file
@@ -0,0 +1,404 @@
|
||||
// Package visitor contains walker.visitor implementations
|
||||
package nsresolver
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/z7zmey/php-parser/pkg/ast"
|
||||
"github.com/z7zmey/php-parser/pkg/visitor"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// NamespaceResolver visitor
|
||||
type NamespaceResolver struct {
|
||||
visitor.Null
|
||||
Namespace *Namespace
|
||||
ResolvedNames map[ast.Vertex]string
|
||||
|
||||
goDeep bool
|
||||
}
|
||||
|
||||
// NewNamespaceResolver NamespaceResolver type constructor
|
||||
func NewNamespaceResolver() *NamespaceResolver {
|
||||
return &NamespaceResolver{
|
||||
Namespace: NewNamespace(""),
|
||||
ResolvedNames: map[ast.Vertex]string{},
|
||||
goDeep: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) EnterNode(n ast.Vertex) bool {
|
||||
n.Accept(nsr)
|
||||
|
||||
if !nsr.goDeep {
|
||||
nsr.goDeep = true
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) StmtNamespace(n *ast.StmtNamespace) {
|
||||
if n.Name == nil {
|
||||
nsr.Namespace = NewNamespace("")
|
||||
} else {
|
||||
NSParts := n.Name.(*ast.NameName).Parts
|
||||
nsr.Namespace = NewNamespace(concatNameParts(NSParts))
|
||||
}
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) StmtUse(n *ast.StmtUse) {
|
||||
useType := ""
|
||||
if n.Type != nil {
|
||||
useType = string(n.Type.(*ast.Identifier).Value)
|
||||
}
|
||||
|
||||
for _, nn := range n.UseDeclarations {
|
||||
nsr.AddAlias(useType, nn, nil)
|
||||
}
|
||||
|
||||
nsr.goDeep = false
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) StmtGroupUse(n *ast.StmtGroupUse) {
|
||||
useType := ""
|
||||
if n.Type != nil {
|
||||
useType = string(n.Type.(*ast.Identifier).Value)
|
||||
}
|
||||
|
||||
for _, nn := range n.UseDeclarations {
|
||||
nsr.AddAlias(useType, nn, n.Prefix.(*ast.NameName).Parts)
|
||||
}
|
||||
|
||||
nsr.goDeep = false
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) StmtClass(n *ast.StmtClass) {
|
||||
if n.Extends != nil {
|
||||
nsr.ResolveName(n.Extends, "")
|
||||
}
|
||||
|
||||
if n.Implements != nil {
|
||||
for _, interfaceName := range n.Implements {
|
||||
nsr.ResolveName(interfaceName, "")
|
||||
}
|
||||
}
|
||||
|
||||
if n.ClassName != nil {
|
||||
nsr.AddNamespacedName(n, string(n.ClassName.(*ast.Identifier).Value))
|
||||
}
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) StmtInterface(n *ast.StmtInterface) {
|
||||
if n.Extends != nil {
|
||||
for _, interfaceName := range n.Extends {
|
||||
nsr.ResolveName(interfaceName, "")
|
||||
}
|
||||
}
|
||||
|
||||
nsr.AddNamespacedName(n, string(n.InterfaceName.(*ast.Identifier).Value))
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) StmtTrait(n *ast.StmtTrait) {
|
||||
nsr.AddNamespacedName(n, string(n.TraitName.(*ast.Identifier).Value))
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) StmtFunction(n *ast.StmtFunction) {
|
||||
nsr.AddNamespacedName(n, string(n.FunctionName.(*ast.Identifier).Value))
|
||||
|
||||
for _, parameter := range n.Params {
|
||||
nsr.ResolveType(parameter.(*ast.Parameter).Type)
|
||||
}
|
||||
|
||||
if n.ReturnType != nil {
|
||||
nsr.ResolveType(n.ReturnType)
|
||||
}
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) StmtClassMethod(n *ast.StmtClassMethod) {
|
||||
for _, parameter := range n.Params {
|
||||
nsr.ResolveType(parameter.(*ast.Parameter).Type)
|
||||
}
|
||||
|
||||
if n.ReturnType != nil {
|
||||
nsr.ResolveType(n.ReturnType)
|
||||
}
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) ExprClosure(n *ast.ExprClosure) {
|
||||
for _, parameter := range n.Params {
|
||||
nsr.ResolveType(parameter.(*ast.Parameter).Type)
|
||||
}
|
||||
|
||||
if n.ReturnType != nil {
|
||||
nsr.ResolveType(n.ReturnType)
|
||||
}
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) StmtPropertyList(n *ast.StmtPropertyList) {
|
||||
if n.Type != nil {
|
||||
nsr.ResolveType(n.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) StmtConstList(n *ast.StmtConstList) {
|
||||
for _, constant := range n.Consts {
|
||||
nsr.AddNamespacedName(constant, string(constant.(*ast.StmtConstant).Name.(*ast.Identifier).Value))
|
||||
}
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) ExprStaticCall(n *ast.ExprStaticCall) {
|
||||
nsr.ResolveName(n.Class, "")
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) ExprStaticPropertyFetch(n *ast.ExprStaticPropertyFetch) {
|
||||
nsr.ResolveName(n.Class, "")
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) ExprClassConstFetch(n *ast.ExprClassConstFetch) {
|
||||
nsr.ResolveName(n.Class, "")
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) ExprNew(n *ast.ExprNew) {
|
||||
nsr.ResolveName(n.Class, "")
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) ExprInstanceOf(n *ast.ExprInstanceOf) {
|
||||
nsr.ResolveName(n.Class, "")
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) StmtCatch(n *ast.StmtCatch) {
|
||||
for _, t := range n.Types {
|
||||
nsr.ResolveName(t, "")
|
||||
}
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) ExprFunctionCall(n *ast.ExprFunctionCall) {
|
||||
nsr.ResolveName(n.Function, "function")
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) ExprConstFetch(n *ast.ExprConstFetch) {
|
||||
nsr.ResolveName(n.Const, "const")
|
||||
}
|
||||
|
||||
func (nsr *NamespaceResolver) StmtTraitUse(n *ast.StmtTraitUse) {
|
||||
for _, t := range n.Traits {
|
||||
nsr.ResolveName(t, "")
|
||||
}
|
||||
|
||||
for _, a := range n.Adaptations {
|
||||
switch aa := a.(type) {
|
||||
case *ast.StmtTraitUsePrecedence:
|
||||
refTrait := aa.Trait
|
||||
if refTrait != nil {
|
||||
nsr.ResolveName(refTrait, "")
|
||||
}
|
||||
for _, insteadOf := range aa.Insteadof {
|
||||
nsr.ResolveName(insteadOf, "")
|
||||
}
|
||||
|
||||
case *ast.StmtTraitUseAlias:
|
||||
refTrait := aa.Trait
|
||||
if refTrait != nil {
|
||||
nsr.ResolveName(refTrait, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LeaveNode is invoked after node process
|
||||
func (nsr *NamespaceResolver) LeaveNode(n ast.Vertex) {
|
||||
switch nn := n.(type) {
|
||||
case *ast.StmtNamespace:
|
||||
if nn.Stmts != nil {
|
||||
nsr.Namespace = NewNamespace("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AddAlias adds a new alias
|
||||
func (nsr *NamespaceResolver) AddAlias(useType string, nn ast.Vertex, prefix []ast.Vertex) {
|
||||
switch use := nn.(type) {
|
||||
case *ast.StmtUseDeclaration:
|
||||
if use.Type != nil {
|
||||
useType = string(use.Type.(*ast.Identifier).Value)
|
||||
}
|
||||
|
||||
useNameParts := use.Use.(*ast.NameName).Parts
|
||||
var alias string
|
||||
if use.Alias == nil {
|
||||
alias = string(useNameParts[len(useNameParts)-1].(*ast.NameNamePart).Value)
|
||||
} else {
|
||||
alias = string(use.Alias.(*ast.Identifier).Value)
|
||||
}
|
||||
|
||||
nsr.Namespace.AddAlias(useType, concatNameParts(prefix, useNameParts), alias)
|
||||
}
|
||||
}
|
||||
|
||||
// AddNamespacedName adds namespaced name by node
|
||||
func (nsr *NamespaceResolver) AddNamespacedName(nn ast.Vertex, nodeName string) {
|
||||
if nsr.Namespace.Namespace == "" {
|
||||
nsr.ResolvedNames[nn] = nodeName
|
||||
} else {
|
||||
nsr.ResolvedNames[nn] = nsr.Namespace.Namespace + "\\" + nodeName
|
||||
}
|
||||
}
|
||||
|
||||
// ResolveName adds a resolved fully qualified name by node
|
||||
func (nsr *NamespaceResolver) ResolveName(nameNode ast.Vertex, aliasType string) {
|
||||
resolved, err := nsr.Namespace.ResolveName(nameNode, aliasType)
|
||||
if err == nil {
|
||||
nsr.ResolvedNames[nameNode] = resolved
|
||||
}
|
||||
}
|
||||
|
||||
// ResolveType adds a resolved fully qualified type name
|
||||
func (nsr *NamespaceResolver) ResolveType(n ast.Vertex) {
|
||||
switch nn := n.(type) {
|
||||
case *ast.Nullable:
|
||||
nsr.ResolveType(nn.Expr)
|
||||
case *ast.NameName:
|
||||
nsr.ResolveName(n, "")
|
||||
case *ast.NameRelative:
|
||||
nsr.ResolveName(n, "")
|
||||
case *ast.NameFullyQualified:
|
||||
nsr.ResolveName(n, "")
|
||||
}
|
||||
}
|
||||
|
||||
// Namespace context
|
||||
type Namespace struct {
|
||||
Namespace string
|
||||
Aliases map[string]map[string]string
|
||||
}
|
||||
|
||||
// NewNamespace constructor
|
||||
func NewNamespace(NSName string) *Namespace {
|
||||
return &Namespace{
|
||||
Namespace: NSName,
|
||||
Aliases: map[string]map[string]string{
|
||||
"": {},
|
||||
"const": {},
|
||||
"function": {},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// AddAlias adds a new alias
|
||||
func (ns *Namespace) AddAlias(aliasType string, aliasName string, alias string) {
|
||||
aliasType = strings.ToLower(aliasType)
|
||||
|
||||
if aliasType == "const" {
|
||||
ns.Aliases[aliasType][alias] = aliasName
|
||||
} else {
|
||||
ns.Aliases[aliasType][strings.ToLower(alias)] = aliasName
|
||||
}
|
||||
}
|
||||
|
||||
// ResolveName returns a resolved fully qualified name
|
||||
func (ns *Namespace) ResolveName(nameNode ast.Vertex, aliasType string) (string, error) {
|
||||
switch n := nameNode.(type) {
|
||||
case *ast.NameFullyQualified:
|
||||
// Fully qualifid name is already resolved
|
||||
return concatNameParts(n.Parts), nil
|
||||
|
||||
case *ast.NameRelative:
|
||||
if ns.Namespace == "" {
|
||||
return concatNameParts(n.Parts), nil
|
||||
}
|
||||
return ns.Namespace + "\\" + concatNameParts(n.Parts), nil
|
||||
|
||||
case *ast.NameName:
|
||||
if aliasType == "const" && len(n.Parts) == 1 {
|
||||
part := strings.ToLower(string(n.Parts[0].(*ast.NameNamePart).Value))
|
||||
if part == "true" || part == "false" || part == "null" {
|
||||
return part, nil
|
||||
}
|
||||
}
|
||||
|
||||
if aliasType == "" && len(n.Parts) == 1 {
|
||||
part := strings.ToLower(string(n.Parts[0].(*ast.NameNamePart).Value))
|
||||
|
||||
switch part {
|
||||
case "self":
|
||||
fallthrough
|
||||
case "static":
|
||||
fallthrough
|
||||
case "parent":
|
||||
fallthrough
|
||||
case "int":
|
||||
fallthrough
|
||||
case "float":
|
||||
fallthrough
|
||||
case "bool":
|
||||
fallthrough
|
||||
case "string":
|
||||
fallthrough
|
||||
case "void":
|
||||
fallthrough
|
||||
case "iterable":
|
||||
fallthrough
|
||||
case "object":
|
||||
return part, nil
|
||||
}
|
||||
}
|
||||
|
||||
aliasName, err := ns.ResolveAlias(nameNode, aliasType)
|
||||
if err != nil {
|
||||
// resolve as relative name if alias not found
|
||||
if ns.Namespace == "" {
|
||||
return concatNameParts(n.Parts), nil
|
||||
}
|
||||
return ns.Namespace + "\\" + concatNameParts(n.Parts), nil
|
||||
}
|
||||
|
||||
if len(n.Parts) > 1 {
|
||||
// if name qualified, replace first part by alias
|
||||
return aliasName + "\\" + concatNameParts(n.Parts[1:]), nil
|
||||
}
|
||||
|
||||
return aliasName, nil
|
||||
}
|
||||
|
||||
return "", errors.New("must be instance of name.Names")
|
||||
}
|
||||
|
||||
// ResolveAlias returns alias or error if not found
|
||||
func (ns *Namespace) ResolveAlias(nameNode ast.Vertex, aliasType string) (string, error) {
|
||||
aliasType = strings.ToLower(aliasType)
|
||||
nameParts := nameNode.(*ast.NameName).Parts
|
||||
|
||||
firstPartStr := string(nameParts[0].(*ast.NameNamePart).Value)
|
||||
|
||||
if len(nameParts) > 1 { // resolve aliases for qualified names, always against class alias type
|
||||
firstPartStr = strings.ToLower(firstPartStr)
|
||||
aliasType = ""
|
||||
} else {
|
||||
if aliasType != "const" { // constants are case-sensitive
|
||||
firstPartStr = strings.ToLower(firstPartStr)
|
||||
}
|
||||
}
|
||||
|
||||
aliasName, ok := ns.Aliases[aliasType][firstPartStr]
|
||||
if !ok {
|
||||
return "", errors.New("Not found")
|
||||
}
|
||||
|
||||
return aliasName, nil
|
||||
}
|
||||
|
||||
func concatNameParts(parts ...[]ast.Vertex) string {
|
||||
str := ""
|
||||
|
||||
for _, p := range parts {
|
||||
for _, n := range p {
|
||||
if str == "" {
|
||||
str = string(n.(*ast.NameNamePart).Value)
|
||||
} else {
|
||||
str = str + "\\" + string(n.(*ast.NameNamePart).Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
980
pkg/visitor/nsresolver/namespace_resolver_test.go
Normal file
980
pkg/visitor/nsresolver/namespace_resolver_test.go
Normal file
@@ -0,0 +1,980 @@
|
||||
package nsresolver_test
|
||||
|
||||
import (
|
||||
"github.com/z7zmey/php-parser/pkg/visitor/nsresolver"
|
||||
"github.com/z7zmey/php-parser/pkg/visitor/traverser"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
|
||||
"github.com/z7zmey/php-parser/pkg/ast"
|
||||
)
|
||||
|
||||
func TestResolveStaticCall(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameBC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtUse{
|
||||
UseDeclarations: []ast.Vertex{
|
||||
&ast.StmtUseDeclaration{
|
||||
Use: nameAB,
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.ExprStaticCall{
|
||||
Class: nameBC,
|
||||
Call: &ast.Identifier{Value: []byte("foo")},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameBC: "A\\B\\C",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveStaticPropertyFetch(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameBC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtUse{
|
||||
UseDeclarations: []ast.Vertex{
|
||||
&ast.StmtUseDeclaration{
|
||||
Use: nameAB,
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.ExprStaticPropertyFetch{
|
||||
Class: nameBC,
|
||||
Property: &ast.Identifier{Value: []byte("foo")},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameBC: "A\\B\\C",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveClassConstFetch(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameBC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtUse{
|
||||
UseDeclarations: []ast.Vertex{
|
||||
&ast.StmtUseDeclaration{
|
||||
Use: nameAB,
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.ExprClassConstFetch{
|
||||
Class: nameBC,
|
||||
ConstantName: &ast.Identifier{Value: []byte("FOO")},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameBC: "A\\B\\C",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveNew(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameBC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtUse{
|
||||
UseDeclarations: []ast.Vertex{
|
||||
&ast.StmtUseDeclaration{
|
||||
Use: nameAB,
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.ExprNew{
|
||||
Class: nameBC,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameBC: "A\\B\\C",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveInstanceOf(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameBC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtUse{
|
||||
UseDeclarations: []ast.Vertex{
|
||||
&ast.StmtUseDeclaration{
|
||||
Use: nameAB,
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.ExprInstanceOf{
|
||||
Expr: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("foo")}},
|
||||
Class: nameBC,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameBC: "A\\B\\C",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveInstanceCatch(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameBC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
|
||||
nameDE := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("D")}, &ast.NameNamePart{Value: []byte("E")}}}
|
||||
nameF := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("F")}}}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtUse{
|
||||
UseDeclarations: []ast.Vertex{
|
||||
&ast.StmtUseDeclaration{
|
||||
Use: nameAB,
|
||||
},
|
||||
&ast.StmtUseDeclaration{
|
||||
Use: nameDE,
|
||||
Alias: &ast.Identifier{Value: []byte("F")},
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.StmtTry{
|
||||
Stmts: []ast.Vertex{},
|
||||
Catches: []ast.Vertex{
|
||||
&ast.StmtCatch{
|
||||
Types: []ast.Vertex{
|
||||
nameBC,
|
||||
nameF,
|
||||
},
|
||||
Var: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("foo")}},
|
||||
Stmts: []ast.Vertex{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameBC: "A\\B\\C",
|
||||
nameF: "D\\E",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveFunctionCall(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}}}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtUse{
|
||||
Type: &ast.Identifier{Value: []byte("function")},
|
||||
UseDeclarations: []ast.Vertex{
|
||||
&ast.StmtUseDeclaration{
|
||||
Use: nameAB,
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.ExprFunctionCall{
|
||||
Function: nameB,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameB: "A\\B",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveConstFetch(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}}}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtUse{
|
||||
Type: &ast.Identifier{Value: []byte("const")},
|
||||
UseDeclarations: []ast.Vertex{
|
||||
&ast.StmtUseDeclaration{
|
||||
Use: nameAB,
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.ExprConstFetch{
|
||||
Const: nameB,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameB: "A\\B",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveGroupUse(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameBD := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("D")}}}
|
||||
nameE := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("E")}}}
|
||||
nameC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("C")}}}
|
||||
nameF := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("F")}}}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtGroupUse{
|
||||
Prefix: nameAB,
|
||||
UseDeclarations: []ast.Vertex{
|
||||
&ast.StmtUseDeclaration{
|
||||
Type: &ast.Identifier{Value: []byte("Function")},
|
||||
Use: nameF,
|
||||
},
|
||||
&ast.StmtUseDeclaration{
|
||||
Type: &ast.Identifier{Value: []byte("const")},
|
||||
Use: nameC,
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.StmtGroupUse{
|
||||
Prefix: nameBD,
|
||||
Type: &ast.Identifier{Value: []byte("Function")},
|
||||
UseDeclarations: []ast.Vertex{
|
||||
&ast.StmtUseDeclaration{
|
||||
Use: nameE,
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.ExprConstFetch{
|
||||
Const: nameC,
|
||||
},
|
||||
&ast.ExprFunctionCall{
|
||||
Function: nameF,
|
||||
},
|
||||
&ast.ExprFunctionCall{
|
||||
Function: nameE,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameC: "A\\B\\C",
|
||||
nameF: "A\\B\\F",
|
||||
nameE: "B\\D\\E",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveTraitUse(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameD := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("D")}}}
|
||||
|
||||
fullyQualifiedNameB := &ast.NameFullyQualified{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}}}
|
||||
fullyQualifiedNameBC := &ast.NameFullyQualified{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
relativeNameB := &ast.NameRelative{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}}}
|
||||
relativeNameBC := &ast.NameRelative{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtUse{
|
||||
UseDeclarations: []ast.Vertex{
|
||||
&ast.StmtUseDeclaration{
|
||||
Use: nameAB,
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.StmtTraitUse{
|
||||
Traits: []ast.Vertex{
|
||||
nameB,
|
||||
relativeNameB,
|
||||
},
|
||||
Adaptations: []ast.Vertex{
|
||||
&ast.StmtTraitUsePrecedence{
|
||||
Trait: fullyQualifiedNameB,
|
||||
Method: &ast.Identifier{Value: []byte("foo")},
|
||||
Insteadof: []ast.Vertex{fullyQualifiedNameBC},
|
||||
},
|
||||
&ast.StmtTraitUseAlias{
|
||||
Trait: relativeNameBC,
|
||||
Method: &ast.Identifier{Value: []byte("foo")},
|
||||
Alias: &ast.Identifier{Value: []byte("bar")},
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.StmtTraitUse{
|
||||
Traits: []ast.Vertex{
|
||||
nameD,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameB: "A\\B",
|
||||
nameD: "D",
|
||||
relativeNameB: "B",
|
||||
fullyQualifiedNameB: "B",
|
||||
fullyQualifiedNameBC: "B\\C",
|
||||
relativeNameBC: "B\\C",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveClassName(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameBC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
|
||||
class := &ast.StmtClass{
|
||||
ClassName: &ast.Identifier{Value: []byte("A")},
|
||||
Extends: nameAB,
|
||||
Implements: []ast.Vertex{
|
||||
nameBC,
|
||||
},
|
||||
}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
class,
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
class: "A",
|
||||
nameAB: "A\\B",
|
||||
nameBC: "B\\C",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveInterfaceName(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameBC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
|
||||
interfaceNode := &ast.StmtInterface{
|
||||
InterfaceName: &ast.Identifier{Value: []byte("A")},
|
||||
Extends: []ast.Vertex{
|
||||
nameAB,
|
||||
nameBC,
|
||||
},
|
||||
}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
interfaceNode,
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
interfaceNode: "A",
|
||||
nameAB: "A\\B",
|
||||
nameBC: "B\\C",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveTraitName(t *testing.T) {
|
||||
traitNode := &ast.StmtTrait{
|
||||
TraitName: &ast.Identifier{Value: []byte("A")},
|
||||
Stmts: []ast.Vertex{},
|
||||
}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
traitNode,
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
traitNode: "A",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveFunctionName(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameBC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
|
||||
functionNode := &ast.StmtFunction{
|
||||
FunctionName: &ast.Identifier{Value: []byte("A")},
|
||||
Params: []ast.Vertex{
|
||||
&ast.Parameter{
|
||||
Type: nameAB,
|
||||
Var: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("foo")}},
|
||||
},
|
||||
},
|
||||
ReturnType: &ast.Nullable{Expr: nameBC},
|
||||
Stmts: []ast.Vertex{},
|
||||
}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
functionNode,
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
functionNode: "A",
|
||||
nameAB: "A\\B",
|
||||
nameBC: "B\\C",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveMethodName(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameBC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
|
||||
methodNode := &ast.StmtClassMethod{
|
||||
MethodName: &ast.Identifier{Value: []byte("A")},
|
||||
Params: []ast.Vertex{
|
||||
&ast.Parameter{
|
||||
Type: nameAB,
|
||||
Var: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("foo")}},
|
||||
},
|
||||
},
|
||||
ReturnType: &ast.Nullable{Expr: nameBC},
|
||||
Stmt: &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameAB: "A\\B",
|
||||
nameBC: "B\\C",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(methodNode)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveClosureName(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameBC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("B")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
|
||||
closureNode := &ast.ExprClosure{
|
||||
Params: []ast.Vertex{
|
||||
&ast.Parameter{
|
||||
Type: nameAB,
|
||||
Var: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("foo")}},
|
||||
},
|
||||
},
|
||||
ReturnType: &ast.Nullable{Expr: nameBC},
|
||||
Stmts: []ast.Vertex{},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameAB: "A\\B",
|
||||
nameBC: "B\\C",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(closureNode)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveConstantsName(t *testing.T) {
|
||||
nameAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
|
||||
constantB := &ast.StmtConstant{
|
||||
Name: &ast.Identifier{Value: []byte("B")},
|
||||
Expr: &ast.ScalarLnumber{Value: []byte("1")},
|
||||
}
|
||||
constantC := &ast.StmtConstant{
|
||||
Name: &ast.Identifier{Value: []byte("C")},
|
||||
Expr: &ast.ScalarLnumber{Value: []byte("1")},
|
||||
}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtNamespace{
|
||||
Name: nameAB,
|
||||
},
|
||||
&ast.StmtConstList{
|
||||
Consts: []ast.Vertex{
|
||||
constantB,
|
||||
constantC,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
constantB: "A\\B\\B",
|
||||
constantC: "A\\B\\C",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveNamespaces(t *testing.T) {
|
||||
namespaceAB := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
namespaceCD := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("C")}, &ast.NameNamePart{Value: []byte("D")}}}
|
||||
|
||||
nameAC := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("C")}}}
|
||||
nameCF := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("C")}, &ast.NameNamePart{Value: []byte("F")}}}
|
||||
nameFG := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("F")}, &ast.NameNamePart{Value: []byte("G")}}}
|
||||
relativeNameCE := &ast.NameRelative{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("C")}, &ast.NameNamePart{Value: []byte("E")}}}
|
||||
|
||||
constantB := &ast.StmtConstant{
|
||||
Name: &ast.Identifier{Value: []byte("B")},
|
||||
Expr: &ast.ScalarLnumber{Value: []byte("1")},
|
||||
}
|
||||
constantC := &ast.StmtConstant{
|
||||
Name: &ast.Identifier{Value: []byte("C")},
|
||||
Expr: &ast.ScalarLnumber{Value: []byte("1")},
|
||||
}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtNamespace{
|
||||
Name: namespaceAB,
|
||||
},
|
||||
&ast.StmtConstList{
|
||||
Consts: []ast.Vertex{
|
||||
constantB,
|
||||
constantC,
|
||||
},
|
||||
},
|
||||
&ast.ExprStaticCall{
|
||||
Class: nameFG,
|
||||
Call: &ast.Identifier{Value: []byte("foo")},
|
||||
},
|
||||
&ast.StmtNamespace{
|
||||
Stmts: []ast.Vertex{},
|
||||
},
|
||||
&ast.StmtNamespace{
|
||||
Name: namespaceCD,
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtUse{
|
||||
UseDeclarations: []ast.Vertex{
|
||||
&ast.StmtUseDeclaration{
|
||||
Use: nameAC,
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.ExprStaticCall{
|
||||
Class: relativeNameCE,
|
||||
Call: &ast.Identifier{Value: []byte("foo")},
|
||||
},
|
||||
&ast.ExprStaticCall{
|
||||
Class: nameCF,
|
||||
Call: &ast.Identifier{Value: []byte("foo")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
constantB: "A\\B\\B",
|
||||
constantC: "A\\B\\C",
|
||||
nameFG: "A\\B\\F\\G",
|
||||
relativeNameCE: "C\\D\\C\\E",
|
||||
nameCF: "A\\C\\F",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestResolveStaticCallDinamicClassName(t *testing.T) {
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.ExprStaticCall{
|
||||
Class: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("foo")}},
|
||||
Call: &ast.Identifier{Value: []byte("foo")},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestDoNotResolveReservedConstants(t *testing.T) {
|
||||
namespaceName := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("Foo")}}}
|
||||
|
||||
constantTrue := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("True")},
|
||||
},
|
||||
}
|
||||
|
||||
constantFalse := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("False")},
|
||||
},
|
||||
}
|
||||
|
||||
constantNull := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("NULL")},
|
||||
},
|
||||
}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtNamespace{
|
||||
Name: namespaceName,
|
||||
},
|
||||
&ast.StmtExpression{
|
||||
Expr: &ast.ExprConstFetch{
|
||||
Const: constantTrue,
|
||||
},
|
||||
},
|
||||
&ast.StmtExpression{
|
||||
Expr: &ast.ExprConstFetch{
|
||||
Const: constantFalse,
|
||||
},
|
||||
},
|
||||
&ast.StmtExpression{
|
||||
Expr: &ast.ExprConstFetch{
|
||||
Const: constantNull,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
constantTrue: "true",
|
||||
constantFalse: "false",
|
||||
constantNull: "null",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestDoNotResolveReservedNames(t *testing.T) {
|
||||
|
||||
nameInt := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("int")},
|
||||
},
|
||||
}
|
||||
|
||||
nameFloat := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("float")},
|
||||
},
|
||||
}
|
||||
|
||||
nameBool := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("bool")},
|
||||
},
|
||||
}
|
||||
|
||||
nameString := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("string")},
|
||||
},
|
||||
}
|
||||
|
||||
nameVoid := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("void")},
|
||||
},
|
||||
}
|
||||
|
||||
nameIterable := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("iterable")},
|
||||
},
|
||||
}
|
||||
|
||||
nameObject := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("object")},
|
||||
},
|
||||
}
|
||||
|
||||
function := &ast.StmtFunction{
|
||||
FunctionName: &ast.Identifier{Value: []byte("bar")},
|
||||
Params: []ast.Vertex{
|
||||
&ast.Parameter{
|
||||
Type: nameInt,
|
||||
Var: &ast.ExprVariable{
|
||||
VarName: &ast.Identifier{Value: []byte("Int")},
|
||||
},
|
||||
},
|
||||
&ast.Parameter{
|
||||
Type: nameFloat,
|
||||
Var: &ast.ExprVariable{
|
||||
VarName: &ast.Identifier{Value: []byte("Float")},
|
||||
},
|
||||
},
|
||||
&ast.Parameter{
|
||||
Type: nameBool,
|
||||
Var: &ast.ExprVariable{
|
||||
VarName: &ast.Identifier{Value: []byte("Bool")},
|
||||
},
|
||||
},
|
||||
&ast.Parameter{
|
||||
Type: nameString,
|
||||
Var: &ast.ExprVariable{
|
||||
VarName: &ast.Identifier{Value: []byte("String")},
|
||||
},
|
||||
},
|
||||
&ast.Parameter{
|
||||
Type: nameVoid,
|
||||
Var: &ast.ExprVariable{
|
||||
VarName: &ast.Identifier{Value: []byte("Void")},
|
||||
},
|
||||
},
|
||||
&ast.Parameter{
|
||||
Type: nameIterable,
|
||||
Var: &ast.ExprVariable{
|
||||
VarName: &ast.Identifier{Value: []byte("Iterable")},
|
||||
},
|
||||
},
|
||||
&ast.Parameter{
|
||||
Type: nameObject,
|
||||
Var: &ast.ExprVariable{
|
||||
VarName: &ast.Identifier{Value: []byte("Object")},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtNamespace{
|
||||
Name: &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("Foo")},
|
||||
},
|
||||
},
|
||||
},
|
||||
function,
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
function: "Foo\\bar",
|
||||
nameInt: "int",
|
||||
nameFloat: "float",
|
||||
nameBool: "bool",
|
||||
nameString: "string",
|
||||
nameVoid: "void",
|
||||
nameIterable: "iterable",
|
||||
nameObject: "object",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
|
||||
func TestDoNotResolveReservedSpecialNames(t *testing.T) {
|
||||
|
||||
nameSelf := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("Self")},
|
||||
},
|
||||
}
|
||||
|
||||
nameStatic := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("Static")},
|
||||
},
|
||||
}
|
||||
|
||||
nameParent := &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("Parent")},
|
||||
},
|
||||
}
|
||||
|
||||
cls := &ast.StmtClass{
|
||||
ClassName: &ast.Identifier{Value: []byte("Bar")},
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtExpression{
|
||||
Expr: &ast.ExprStaticCall{
|
||||
Class: nameSelf,
|
||||
Call: &ast.Identifier{Value: []byte("func")},
|
||||
},
|
||||
},
|
||||
&ast.StmtExpression{
|
||||
Expr: &ast.ExprStaticCall{
|
||||
Class: nameStatic,
|
||||
Call: &ast.Identifier{Value: []byte("func")},
|
||||
},
|
||||
},
|
||||
&ast.StmtExpression{
|
||||
Expr: &ast.ExprStaticCall{
|
||||
Class: nameParent,
|
||||
Call: &ast.Identifier{Value: []byte("func")},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
stxTree := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtNamespace{
|
||||
Name: &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("Foo")},
|
||||
},
|
||||
},
|
||||
},
|
||||
cls,
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
cls: "Foo\\Bar",
|
||||
nameSelf: "self",
|
||||
nameStatic: "static",
|
||||
nameParent: "parent",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stxTree)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
func TestResolvePropertyTypeName(t *testing.T) {
|
||||
nameSimple := &ast.NameName{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameRelative := &ast.NameRelative{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
nameFullyQualified := &ast.NameFullyQualified{Parts: []ast.Vertex{&ast.NameNamePart{Value: []byte("A")}, &ast.NameNamePart{Value: []byte("B")}}}
|
||||
|
||||
propertyNodeSimple := &ast.StmtPropertyList{
|
||||
Type: nameSimple,
|
||||
}
|
||||
|
||||
propertyNodeRelative := &ast.StmtPropertyList{
|
||||
Type: nameRelative,
|
||||
}
|
||||
|
||||
propertyNodeFullyQualified := &ast.StmtPropertyList{
|
||||
Type: nameFullyQualified,
|
||||
}
|
||||
|
||||
classNode := &ast.StmtClass{
|
||||
ClassName: &ast.Identifier{Value: []byte("Bar")},
|
||||
Stmts: []ast.Vertex{
|
||||
propertyNodeSimple,
|
||||
propertyNodeRelative,
|
||||
propertyNodeFullyQualified,
|
||||
},
|
||||
}
|
||||
|
||||
stmts := &ast.StmtStmtList{
|
||||
Stmts: []ast.Vertex{
|
||||
&ast.StmtNamespace{
|
||||
Name: &ast.NameName{
|
||||
Parts: []ast.Vertex{
|
||||
&ast.NameNamePart{Value: []byte("Foo")},
|
||||
},
|
||||
},
|
||||
},
|
||||
classNode,
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[ast.Vertex]string{
|
||||
nameSimple: "Foo\\A\\B",
|
||||
nameRelative: "Foo\\A\\B",
|
||||
nameFullyQualified: "A\\B",
|
||||
classNode: "Foo\\Bar",
|
||||
}
|
||||
|
||||
nsResolver := nsresolver.NewNamespaceResolver()
|
||||
traverser.NewTraverser(nsResolver).Traverse(stmts)
|
||||
|
||||
assert.DeepEqual(t, expected, nsResolver.ResolvedNames)
|
||||
}
|
||||
643
pkg/visitor/null.go
Normal file
643
pkg/visitor/null.go
Normal file
@@ -0,0 +1,643 @@
|
||||
package visitor
|
||||
|
||||
import (
|
||||
"github.com/z7zmey/php-parser/pkg/ast"
|
||||
)
|
||||
|
||||
type Null struct {
|
||||
}
|
||||
|
||||
func (v *Null) Enter(_ string, _ bool) {
|
||||
// do nothing
|
||||
}
|
||||
func (v *Null) Leave(_ string, _ bool) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) EnterNode(_ ast.Vertex) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (v *Null) LeaveNode(_ ast.Vertex) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) Root(_ *ast.Root) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) Nullable(_ *ast.Nullable) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) Parameter(_ *ast.Parameter) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) Identifier(_ *ast.Identifier) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) Argument(_ *ast.Argument) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtBreak(_ *ast.StmtBreak) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtCase(_ *ast.StmtCase) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtCatch(_ *ast.StmtCatch) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtClass(_ *ast.StmtClass) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtClassConstList(_ *ast.StmtClassConstList) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtClassMethod(_ *ast.StmtClassMethod) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtConstList(_ *ast.StmtConstList) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtConstant(_ *ast.StmtConstant) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtContinue(_ *ast.StmtContinue) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtDeclare(_ *ast.StmtDeclare) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtDefault(_ *ast.StmtDefault) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtDo(_ *ast.StmtDo) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtEcho(_ *ast.StmtEcho) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtElse(_ *ast.StmtElse) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtElseIf(_ *ast.StmtElseIf) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtExpression(_ *ast.StmtExpression) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtFinally(_ *ast.StmtFinally) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtFor(_ *ast.StmtFor) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtForeach(_ *ast.StmtForeach) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtFunction(_ *ast.StmtFunction) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtGlobal(_ *ast.StmtGlobal) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtGoto(_ *ast.StmtGoto) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtHaltCompiler(_ *ast.StmtHaltCompiler) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtIf(_ *ast.StmtIf) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtInlineHtml(_ *ast.StmtInlineHtml) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtInterface(_ *ast.StmtInterface) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtLabel(_ *ast.StmtLabel) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtNamespace(_ *ast.StmtNamespace) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtNop(_ *ast.StmtNop) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtProperty(_ *ast.StmtProperty) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtPropertyList(_ *ast.StmtPropertyList) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtReturn(_ *ast.StmtReturn) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtStatic(_ *ast.StmtStatic) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtStaticVar(_ *ast.StmtStaticVar) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtStmtList(_ *ast.StmtStmtList) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtSwitch(_ *ast.StmtSwitch) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtThrow(_ *ast.StmtThrow) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtTrait(_ *ast.StmtTrait) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtTraitUse(_ *ast.StmtTraitUse) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtTraitUseAlias(_ *ast.StmtTraitUseAlias) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtTraitUsePrecedence(_ *ast.StmtTraitUsePrecedence) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtTry(_ *ast.StmtTry) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtUnset(_ *ast.StmtUnset) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtUse(_ *ast.StmtUse) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtGroupUse(_ *ast.StmtGroupUse) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtUseDeclaration(_ *ast.StmtUseDeclaration) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) StmtWhile(_ *ast.StmtWhile) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprArray(_ *ast.ExprArray) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprArrayDimFetch(_ *ast.ExprArrayDimFetch) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprArrayItem(_ *ast.ExprArrayItem) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprArrowFunction(_ *ast.ExprArrowFunction) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBitwiseNot(_ *ast.ExprBitwiseNot) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBooleanNot(_ *ast.ExprBooleanNot) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBrackets(_ *ast.ExprBrackets) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprClassConstFetch(_ *ast.ExprClassConstFetch) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprClone(_ *ast.ExprClone) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprClosure(_ *ast.ExprClosure) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprClosureUse(_ *ast.ExprClosureUse) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprConstFetch(_ *ast.ExprConstFetch) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprEmpty(_ *ast.ExprEmpty) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprErrorSuppress(_ *ast.ExprErrorSuppress) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprEval(_ *ast.ExprEval) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprExit(_ *ast.ExprExit) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprFunctionCall(_ *ast.ExprFunctionCall) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprInclude(_ *ast.ExprInclude) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprIncludeOnce(_ *ast.ExprIncludeOnce) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprInstanceOf(_ *ast.ExprInstanceOf) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprIsset(_ *ast.ExprIsset) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprList(_ *ast.ExprList) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprMethodCall(_ *ast.ExprMethodCall) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprNew(_ *ast.ExprNew) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprPostDec(_ *ast.ExprPostDec) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprPostInc(_ *ast.ExprPostInc) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprPreDec(_ *ast.ExprPreDec) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprPreInc(_ *ast.ExprPreInc) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprPrint(_ *ast.ExprPrint) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprPropertyFetch(_ *ast.ExprPropertyFetch) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprRequire(_ *ast.ExprRequire) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprRequireOnce(_ *ast.ExprRequireOnce) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprShellExec(_ *ast.ExprShellExec) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprStaticCall(_ *ast.ExprStaticCall) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprStaticPropertyFetch(_ *ast.ExprStaticPropertyFetch) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprTernary(_ *ast.ExprTernary) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprUnaryMinus(_ *ast.ExprUnaryMinus) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprUnaryPlus(_ *ast.ExprUnaryPlus) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprVariable(_ *ast.ExprVariable) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprYield(_ *ast.ExprYield) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprYieldFrom(_ *ast.ExprYieldFrom) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssign(_ *ast.ExprAssign) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignReference(_ *ast.ExprAssignReference) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignBitwiseAnd(_ *ast.ExprAssignBitwiseAnd) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignBitwiseOr(_ *ast.ExprAssignBitwiseOr) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignBitwiseXor(_ *ast.ExprAssignBitwiseXor) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignCoalesce(_ *ast.ExprAssignCoalesce) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignConcat(_ *ast.ExprAssignConcat) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignDiv(_ *ast.ExprAssignDiv) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignMinus(_ *ast.ExprAssignMinus) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignMod(_ *ast.ExprAssignMod) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignMul(_ *ast.ExprAssignMul) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignPlus(_ *ast.ExprAssignPlus) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignPow(_ *ast.ExprAssignPow) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignShiftLeft(_ *ast.ExprAssignShiftLeft) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprAssignShiftRight(_ *ast.ExprAssignShiftRight) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryBitwiseAnd(_ *ast.ExprBinaryBitwiseAnd) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryBitwiseOr(_ *ast.ExprBinaryBitwiseOr) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryBitwiseXor(_ *ast.ExprBinaryBitwiseXor) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryBooleanAnd(_ *ast.ExprBinaryBooleanAnd) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryBooleanOr(_ *ast.ExprBinaryBooleanOr) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryCoalesce(_ *ast.ExprBinaryCoalesce) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryConcat(_ *ast.ExprBinaryConcat) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryDiv(_ *ast.ExprBinaryDiv) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryEqual(_ *ast.ExprBinaryEqual) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryGreater(_ *ast.ExprBinaryGreater) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryGreaterOrEqual(_ *ast.ExprBinaryGreaterOrEqual) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryIdentical(_ *ast.ExprBinaryIdentical) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryLogicalAnd(_ *ast.ExprBinaryLogicalAnd) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryLogicalOr(_ *ast.ExprBinaryLogicalOr) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryLogicalXor(_ *ast.ExprBinaryLogicalXor) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryMinus(_ *ast.ExprBinaryMinus) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryMod(_ *ast.ExprBinaryMod) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryMul(_ *ast.ExprBinaryMul) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryNotEqual(_ *ast.ExprBinaryNotEqual) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryNotIdentical(_ *ast.ExprBinaryNotIdentical) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryPlus(_ *ast.ExprBinaryPlus) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryPow(_ *ast.ExprBinaryPow) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryShiftLeft(_ *ast.ExprBinaryShiftLeft) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinaryShiftRight(_ *ast.ExprBinaryShiftRight) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinarySmaller(_ *ast.ExprBinarySmaller) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinarySmallerOrEqual(_ *ast.ExprBinarySmallerOrEqual) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprBinarySpaceship(_ *ast.ExprBinarySpaceship) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprCastArray(_ *ast.ExprCastArray) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprCastBool(_ *ast.ExprCastBool) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprCastDouble(_ *ast.ExprCastDouble) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprCastInt(_ *ast.ExprCastInt) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprCastObject(_ *ast.ExprCastObject) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprCastString(_ *ast.ExprCastString) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ExprCastUnset(_ *ast.ExprCastUnset) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ScalarDnumber(_ *ast.ScalarDnumber) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ScalarEncapsed(_ *ast.ScalarEncapsed) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ScalarEncapsedStringPart(_ *ast.ScalarEncapsedStringPart) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ScalarEncapsedStringBrackets(_ *ast.ScalarEncapsedStringBrackets) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ScalarEncapsedStringVar(_ *ast.ScalarEncapsedStringVar) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ScalarHeredoc(_ *ast.ScalarHeredoc) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ScalarLnumber(_ *ast.ScalarLnumber) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ScalarMagicConstant(_ *ast.ScalarMagicConstant) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) ScalarString(_ *ast.ScalarString) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) NameName(_ *ast.NameName) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) NameFullyQualified(_ *ast.NameFullyQualified) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) NameRelative(_ *ast.NameRelative) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (v *Null) NameNamePart(_ *ast.NameNamePart) {
|
||||
// do nothing
|
||||
}
|
||||
1237
pkg/visitor/printer/printer.go
Normal file
1237
pkg/visitor/printer/printer.go
Normal file
File diff suppressed because it is too large
Load Diff
1432
pkg/visitor/printer/printer_php5_test.go
Normal file
1432
pkg/visitor/printer/printer_php5_test.go
Normal file
File diff suppressed because it is too large
Load Diff
1570
pkg/visitor/printer/printer_php7_test.go
Normal file
1570
pkg/visitor/printer/printer_php7_test.go
Normal file
File diff suppressed because it is too large
Load Diff
4737
pkg/visitor/printer/printer_test.go
Normal file
4737
pkg/visitor/printer/printer_test.go
Normal file
File diff suppressed because it is too large
Load Diff
1164
pkg/visitor/traverser/traverser.go
Normal file
1164
pkg/visitor/traverser/traverser.go
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user