public MethodCall ExtractMethodCall(XmlNode node, IVariableStorage varStorage, AnalysisScope scope = AnalysisScope.File) { int startLine = AstNode.GetStartLine(node); int endLine = AstNode.GetEndLine(node); string methodName = ""; //Get the varNode which includes either (new ClassName())->MethodName or $var->MethodName var varNode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Var); var classNames = new List<string>(); if (varNode.FirstChild.LocalName == AstConstants.Nodes.Expr_New) { //PHP: (new ClassName(args))->MethodName(args); //Extract the ClassName directly, in this case there can be only one ClassName! var className = varNode.FirstChild .GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Class) .GetSubNode(AstConstants.Node + ":" + AstConstants.Nodes.Name) .GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Parts).FirstChild.FirstChild.InnerText; classNames.Add(className); methodName = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Name).InnerText; return new MethodCall(methodName, classNames, node, startLine, endLine) { Arguments = ExtractArgumentNodes(node) }; } else { //PHP: $var->MethodName(args); //Resolve the variable, and get all the possible class names! VariableResolver vr = new VariableResolver(varStorage, scope); VariableResolveResult variableResult = null; if (vr.IsResolvableNode(varNode.FirstChild)) { variableResult = vr.ResolveVariable(varNode.FirstChild); classNames.AddRange(variableResult.Variable.Info.ClassNames.Where(className => !classNames.Contains(className))); } var nameSubnode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Name); XmlNode nameNode = null; bool success = nameSubnode.TryGetSubNode(AstConstants.Node + ":" + AstConstants.Nodes.Name, out nameNode); if (success) { methodName = nameNode.InnerText; } else { if (nameSubnode.FirstChild.LocalName == AstConstants.Scalars.String) { methodName = nameSubnode.FirstChild.InnerText; } } return variableResult == null ? new MethodCall(methodName, classNames, node, startLine, endLine) { Arguments = ExtractArgumentNodes(node) } : new MethodCall(methodName, classNames, node, startLine, endLine, variableResult.Variable) { Arguments = ExtractArgumentNodes(node) }; } }
public void ResolveArrayElement(string phpCode, string varName) { XmlNode ast = PHPParseUtils.ParsePHPCode(phpCode, Config.PHPSettings.PHPParserPath).FirstChild.NextSibling; var xmlNodes = ast.FirstChild.Cast<XmlNode>().ToList(); var varNodes = xmlNodes.Where(node => node.LocalName == AstConstants.Nodes.Expr_ArrayDimFetch); var varResolver = new VariableResolver(new VariableStorage(), AnalysisScope.File); foreach (var varNode in varNodes) { var result = varResolver.ResolveVariable(varNode); Assert.AreEqual(varName, result.Variable.Name, "Names should match"); Assert.IsTrue(result.IsNew, "Variable should be new"); result = varResolver.ResolveVariable(varNode); Assert.AreEqual(varName, result.Variable.Name, "Names should still match"); Assert.IsFalse(result.IsNew, "Variable is no longer new"); } }
public void ResolveArrayElementMixIndexType() { string phpCode = @"<?php $a['1']; $a[1];"; XmlNode ast = PHPParseUtils.ParsePHPCode(phpCode, Config.PHPSettings.PHPParserPath).FirstChild.NextSibling; var xmlNodes = ast.FirstChild.Cast<XmlNode>().ToList(); var varNodes = xmlNodes.Where(node => node.LocalName == AstConstants.Nodes.Expr_ArrayDimFetch); var varResolver = new VariableResolver(new VariableStorage(), AnalysisScope.File); var arrayfetch = varNodes.First(); var result = varResolver.ResolveVariable(arrayfetch); Assert.AreEqual("1", result.Variable.Name, "Names should match"); Assert.IsTrue(result.IsNew, "Variable should be new"); result = varResolver.ResolveVariable(varNodes.ElementAt(1)); Assert.AreEqual("1", result.Variable.Name, "Names should still match"); Assert.IsFalse(result.IsNew, "Variable is no longer new"); }
public void ResolveMultipleArrayElements(string phpCode) { XmlNode ast = PHPParseUtils.ParsePHPCode(phpCode, Config.PHPSettings.PHPParserPath).FirstChild.NextSibling; var xmlNodes = ast.FirstChild.Cast<XmlNode>().ToList(); var varNodes = xmlNodes.Where(node => node.LocalName == AstConstants.Nodes.Expr_ArrayDimFetch); var varResolver = new VariableResolver(new VariableStorage(), AnalysisScope.File); var firstVar = varNodes.First(); var result = varResolver.ResolveVariable(firstVar); result = varResolver.ResolveVariable(firstVar); Assert.IsFalse(result.IsNew, "Var"); result = varResolver.ResolveVariable(varNodes.ElementAt(1)); Assert.IsTrue(result.IsNew, "First lookup of second var"); }
public void ResolveStaticPropertyFetch(string phpCode, string expectedVarName, string nodeType) { XmlNode ast = PHPParseUtils.ParsePHPCode(phpCode, Config.PHPSettings.PHPParserPath).FirstChild.NextSibling; var xmlNodes = ast.FirstChild.Cast<XmlNode>() .Where(node => node.LocalName == nodeType); var propFetch = xmlNodes.First(); var varResolver = new VariableResolver(new VariableStorage(), AnalysisScope.File); var result = varResolver.ResolveVariable(propFetch); Assert.AreEqual(expectedVarName, result.Variable.Name, "Name should match"); Assert.IsTrue(result.IsNew, "New var"); result = varResolver.ResolveVariable(propFetch); Assert.AreEqual(expectedVarName, result.Variable.Name, "Names should still match"); Assert.IsFalse(result.IsNew, "Variable is no longer new"); }