diff --git a/main.go b/main.go index 4010add..1ae093f 100644 --- a/main.go +++ b/main.go @@ -42,6 +42,8 @@ func main() { nsResolver := visitor.NewNsResolver() nodes.Walk(nsResolver) + fmt.Printf("%+v \n", nsResolver.ResolvedNames) + dumper := visitor.Dumper{ Indent: " | ", Comments: comments, diff --git a/visitor/NsResolver.go b/visitor/NsResolver.go index 0c42d9f..9640a7d 100644 --- a/visitor/NsResolver.go +++ b/visitor/NsResolver.go @@ -2,6 +2,7 @@ package visitor import ( + "errors" "strings" "github.com/z7zmey/php-parser/node" @@ -10,6 +11,22 @@ import ( "github.com/z7zmey/php-parser/walker" ) +func concatNameParts(parts ...[]node.Node) string { + str := "" + + for _, p := range parts { + for _, n := range p { + if str == "" { + str = n.(*name.NamePart).Value + } else { + str = str + "\\" + n.(*name.NamePart).Value + } + } + } + + return str +} + type Namespace struct { Namespace string Aliases map[string]map[string]string @@ -17,7 +34,7 @@ type Namespace struct { func NewNamespace(NSName string) *Namespace { return &Namespace{ - Namespace: "", + Namespace: NSName, Aliases: map[string]map[string]string{ "": {}, "const": {}, @@ -36,6 +53,53 @@ func (ns *Namespace) AddAlias(aliasType string, aliasName string, alias string) } } +func (ns *Namespace) resolveName(nameNode node.Node, aliasType string) string { + switch n := nameNode.(type) { + case *name.FullyQualified: + return concatNameParts(n.Parts) + + case *name.Relative: + return ns.Namespace + "\\" + concatNameParts(n.Parts) + + case *name.Name: + aliasName, err := ns.resolveAlias(nameNode, aliasType) + if err != nil { + return ns.Namespace + "\\" + concatNameParts(n.Parts) + } + + if len(n.Parts) > 1 { + return aliasName + "\\" + concatNameParts(n.Parts[1:]) + } + + return aliasName + } + + panic("invalid nameNode variable type") +} + +func (ns *Namespace) resolveAlias(nameNode node.Node, aliasType string) (string, error) { + aliasType = strings.ToLower(aliasType) + nameParts := nameNode.(*name.Name).Parts + + firstPartStr := nameParts[0].(*name.NamePart).Value + + if len(nameParts) > 1 { // resolve aliases for qualified names, always against class alias table + firstPartStr = strings.ToLower(firstPartStr) + aliasType = "" + } else { + if aliasType != "const" { // constans are case-sensitive + firstPartStr = strings.ToLower(firstPartStr) + } + } + + aliasName, ok := ns.Aliases[aliasType][firstPartStr] + if !ok { + return "", errors.New("Not found") + } + + return aliasName, nil +} + type NsResolver struct { Namespace *Namespace ResolvedNames map[node.Node]string @@ -86,11 +150,36 @@ func (nsr *NsResolver) EnterNode(w walker.Walkable) bool { // no reason to iterate into depth return false + case *stmt.Class: + if n.Extends != nil { + nsr.resolveName(n.Extends, "") + } + + for _, _ = range n.Implements { + // todo resolve inteface name + } + + nsr.addNamespacedName(n, n.ClassName.(*node.Identifier).Value) } return true } +// GetChildrenVisitor is invoked at every node parameter that contains children nodes +func (nsr *NsResolver) GetChildrenVisitor(key string) walker.Visitor { + return nsr +} + +// LeaveNode is invoked after node process +func (nsr *NsResolver) LeaveNode(w walker.Walkable) { + switch n := w.(type) { + case *stmt.Namespace: + if n.Stmts != nil { + nsr.Namespace = NewNamespace("") + } + } +} + func (nsr *NsResolver) AddAlias(useType string, nn node.Node, prefix []node.Node) { switch use := nn.(type) { case *stmt.Use: @@ -110,33 +199,14 @@ func (nsr *NsResolver) AddAlias(useType string, nn node.Node, prefix []node.Node } } -// GetChildrenVisitor is invoked at every node parameter that contains children nodes -func (nsr *NsResolver) GetChildrenVisitor(key string) walker.Visitor { - return nsr -} - -// LeaveNode is invoked after node process -func (nsr *NsResolver) LeaveNode(w walker.Walkable) { - switch n := w.(type) { - case *stmt.Namespace: - if n.Stmts != nil { - nsr.Namespace = NewNamespace("") - } +func (nsr *NsResolver) addNamespacedName(nn node.Node, nodeName string) { + if nsr.Namespace.Namespace == "" { + nsr.ResolvedNames[nn] = nodeName + } else { + nsr.ResolvedNames[nn] = nsr.Namespace.Namespace + "\\" + nodeName } } -func concatNameParts(parts ...[]node.Node) string { - str := "" - - for _, p := range parts { - for _, n := range p { - if str == "" { - str = n.(*name.NamePart).Value - } else { - str = str + "\\" + n.(*name.NamePart).Value - } - } - } - - return str +func (nsr *NsResolver) resolveName(nameNode node.Node, aliasType string) { + nsr.ResolvedNames[nameNode] = nsr.Namespace.resolveName(nameNode, aliasType) }