From 063726aac4b6c71d9f185b5e35e84388ea87844d Mon Sep 17 00:00:00 2001 From: z7zmey Date: Mon, 18 Jun 2018 00:15:41 +0300 Subject: [PATCH] #41 Namespace resolver: do not resolve build-in primitives --- visitor/dumper_test.go | 2 +- visitor/namespace_resolver.go | 34 ++++ visitor/namespace_resolver_test.go | 251 +++++++++++++++++++++++++++++ 3 files changed, 286 insertions(+), 1 deletion(-) diff --git a/visitor/dumper_test.go b/visitor/dumper_test.go index 06ae681..c0d3bed 100644 --- a/visitor/dumper_test.go +++ b/visitor/dumper_test.go @@ -99,7 +99,7 @@ func ExampleDumper() { //| "Constant": //| [*name.Name] //| "Position": Pos{Line: 5-5 Pos: 86-89}; - //| "NamespacedName": Foo\null; + //| "NamespacedName": null; //| "Parts": //| [*name.NamePart] //| "Position": Pos{Line: 5-5 Pos: 86-89}; diff --git a/visitor/namespace_resolver.go b/visitor/namespace_resolver.go index 7516358..dc7f78f 100644 --- a/visitor/namespace_resolver.go +++ b/visitor/namespace_resolver.go @@ -286,6 +286,40 @@ func (ns *Namespace) ResolveName(nameNode node.Node, aliasType string) (string, return ns.Namespace + "\\" + concatNameParts(n.Parts), nil case *name.Name: + if aliasType == "const" && len(n.Parts) == 1 { + part := strings.ToLower(n.Parts[0].(*name.NamePart).Value) + if part == "true" || part == "false" || part == "null" { + return part, nil + } + } + + if aliasType == "" && len(n.Parts) == 1 { + part := strings.ToLower(n.Parts[0].(*name.NamePart).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 diff --git a/visitor/namespace_resolver_test.go b/visitor/namespace_resolver_test.go index 80f6917..a407c18 100644 --- a/visitor/namespace_resolver_test.go +++ b/visitor/namespace_resolver_test.go @@ -739,3 +739,254 @@ func TestResolveStaticCallDinamicClassName(t *testing.T) { assertEqual(t, expected, nsResolver.ResolvedNames) } + +func TestDoNotResolveReservedConstants(t *testing.T) { + namespaceName := &name.Name{Parts: []node.Node{&name.NamePart{Value: "Foo"}}} + + constantTrue := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "True"}, + }, + } + + constantFalse := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "False"}, + }, + } + + constantNull := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "NULL"}, + }, + } + + ast := &stmt.StmtList{ + Stmts: []node.Node{ + &stmt.Namespace{ + NamespaceName: namespaceName, + }, + &stmt.Expression{ + Expr: &expr.ConstFetch{ + Constant: constantTrue, + }, + }, + &stmt.Expression{ + Expr: &expr.ConstFetch{ + Constant: constantFalse, + }, + }, + &stmt.Expression{ + Expr: &expr.ConstFetch{ + Constant: constantNull, + }, + }, + }, + } + + expected := map[node.Node]string{ + constantTrue: "true", + constantFalse: "false", + constantNull: "null", + } + + nsResolver := visitor.NewNamespaceResolver() + ast.Walk(nsResolver) + + assertEqual(t, expected, nsResolver.ResolvedNames) +} + +func TestDoNotResolveReservedNames(t *testing.T) { + + nameInt := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "int"}, + }, + } + + nameFloat := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "float"}, + }, + } + + nameBool := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "bool"}, + }, + } + + nameString := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "string"}, + }, + } + + nameVoid := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "void"}, + }, + } + + nameIterable := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "iterable"}, + }, + } + + nameObject := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "object"}, + }, + } + + function := &stmt.Function{ + FunctionName: &node.Identifier{Value: "bar"}, + Params: []node.Node{ + &node.Parameter{ + VariableType: nameInt, + Variable: &expr.Variable{ + VarName: &node.Identifier{Value: "Int"}, + }, + }, + &node.Parameter{ + VariableType: nameFloat, + Variable: &expr.Variable{ + VarName: &node.Identifier{Value: "Float"}, + }, + }, + &node.Parameter{ + VariableType: nameBool, + Variable: &expr.Variable{ + VarName: &node.Identifier{Value: "Bool"}, + }, + }, + &node.Parameter{ + VariableType: nameString, + Variable: &expr.Variable{ + VarName: &node.Identifier{Value: "String"}, + }, + }, + &node.Parameter{ + VariableType: nameVoid, + Variable: &expr.Variable{ + VarName: &node.Identifier{Value: "Void"}, + }, + }, + &node.Parameter{ + VariableType: nameIterable, + Variable: &expr.Variable{ + VarName: &node.Identifier{Value: "Iterable"}, + }, + }, + &node.Parameter{ + VariableType: nameObject, + Variable: &expr.Variable{ + VarName: &node.Identifier{Value: "Object"}, + }, + }, + }, + } + + ast := &stmt.StmtList{ + Stmts: []node.Node{ + &stmt.Namespace{ + NamespaceName: &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "Foo"}, + }, + }, + }, + function, + }, + } + + expected := map[node.Node]string{ + function: "Foo\\bar", + nameInt: "int", + nameFloat: "float", + nameBool: "bool", + nameString: "string", + nameVoid: "void", + nameIterable: "iterable", + nameObject: "object", + } + + nsResolver := visitor.NewNamespaceResolver() + ast.Walk(nsResolver) + + assertEqual(t, expected, nsResolver.ResolvedNames) +} + +func TestDoNotResolveReservedSpecialNames(t *testing.T) { + + nameSelf := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "Self"}, + }, + } + + nameStatic := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "Static"}, + }, + } + + nameParent := &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "Parent"}, + }, + } + + cls := &stmt.Class{ + ClassName: &node.Identifier{Value: "Bar"}, + Stmts: []node.Node{ + &stmt.Expression{ + Expr: &expr.StaticCall{ + Class: nameSelf, + Call: &node.Identifier{Value: "func"}, + ArgumentList: &node.ArgumentList{}, + }, + }, + &stmt.Expression{ + Expr: &expr.StaticCall{ + Class: nameStatic, + Call: &node.Identifier{Value: "func"}, + ArgumentList: &node.ArgumentList{}, + }, + }, + &stmt.Expression{ + Expr: &expr.StaticCall{ + Class: nameParent, + Call: &node.Identifier{Value: "func"}, + ArgumentList: &node.ArgumentList{}, + }, + }, + }, + } + + ast := &stmt.StmtList{ + Stmts: []node.Node{ + &stmt.Namespace{ + NamespaceName: &name.Name{ + Parts: []node.Node{ + &name.NamePart{Value: "Foo"}, + }, + }, + }, + cls, + }, + } + + expected := map[node.Node]string{ + cls: "Foo\\Bar", + nameSelf: "self", + nameStatic: "static", + nameParent: "parent", + } + + nsResolver := visitor.NewNamespaceResolver() + ast.Walk(nsResolver) + + assertEqual(t, expected, nsResolver.ResolvedNames) +}