func (nsr *NamespaceResolver) ResolveName(nameNode ast.Vertex, aliasType string) {
	resolved, err := nsr.Namespace.ResolveName(nameNode, aliasType)
	if err == nil {
		nsr.ResolvedNames[nameNode] = resolved
	}
}
ResolveName adds a resolved fully qualified name by node
package nsresolver
import (
	"errors"
	"github.com/z7zmey/php-parser/pkg/ast"
	"github.com/z7zmey/php-parser/pkg/visitor"
	"strings"
)
type NamespaceResolver struct {
	visitor.Null
	Namespace     *Namespace
	ResolvedNames map[ast.Vertex]string
	goDeep bool
}
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.Name).Parts
		nsr.Namespace = NewNamespace(concatNameParts(NSParts))
	}
}
func (nsr *NamespaceResolver) StmtUse(n *ast.StmtUseList) {
	useType := ""
	if n.Type != nil {
		useType = string(n.Type.(*ast.Identifier).Value)
	}
	for _, nn := range n.Uses {
		nsr.AddAlias(useType, nn, nil)
	}
	nsr.goDeep = false
}
func (nsr *NamespaceResolver) StmtGroupUse(n *ast.StmtGroupUseList) {
	useType := ""
	if n.Type != nil {
		useType = string(n.Type.(*ast.Identifier).Value)
	}
	for _, nn := range n.Uses {
		nsr.AddAlias(useType, nn, n.Prefix.(*ast.Name).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.Name != nil {
		nsr.AddNamespacedName(n, string(n.Name.(*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.Name.(*ast.Identifier).Value))
}
func (nsr *NamespaceResolver) StmtTrait(n *ast.StmtTrait) {
	nsr.AddNamespacedName(n, string(n.Name.(*ast.Identifier).Value))
}
func (nsr *NamespaceResolver) StmtFunction(n *ast.StmtFunction) {
	nsr.AddNamespacedName(n, string(n.Name.(*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, "")
			}
		}
	}
}
func (nsr *NamespaceResolver) LeaveNode(n ast.Vertex) {
	switch nn := n.(type) {
	case *ast.StmtNamespace:
		if nn.Stmts != nil {
			nsr.Namespace = NewNamespace("")
		}
	}
}
func (nsr *NamespaceResolver) AddAlias(useType string, nn ast.Vertex, prefix []ast.Vertex) {
	switch use := nn.(type) {
	case *ast.StmtUse:
		if use.Type != nil {
			useType = string(use.Type.(*ast.Identifier).Value)
		}
		useNameParts := use.Use.(*ast.Name).Parts
		var alias string
		if use.Alias == nil {
			alias = string(useNameParts[len(useNameParts)-1].(*ast.NamePart).Value)
		} else {
			alias = string(use.Alias.(*ast.Identifier).Value)
		}
		nsr.Namespace.AddAlias(useType, concatNameParts(prefix, useNameParts), alias)
	}
}
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
	}
}