/// <inheritdoc /> public override Result Process(bool resolveOccurances, ConstructIndicator category, SyntaxParser parser) { Debug.Assert(parser.IsParsed, "Source code must be parsed"); Debug.Assert(!parser.Errors.AnyError, "Source code must not have any syntax error"); var functions = MetricRelatedFunctions.Get(category); var calls = FindCalls(parser, functions); var hasCalls = calls.GetEnumerator().MoveNext(); return(new Result(hasCalls, calls)); }
/// <inheritdoc /> public override Result Process(bool resolveOccurances, ConstructIndicator category, SyntaxParser parser) { Debug.Assert(category == ConstructIndicator.DynamicInclude, "Metric of class must be same as passed metric"); Debug.Assert(parser.IsParsed, "Source code must be parsed"); Debug.Assert(!parser.Errors.AnyError, "Source code must not have any syntax error"); if (parser.Inclusions == null) { // No type is inclusions if (resolveOccurances) { return(new Result(false, new IncludingEx[0])); } else { return(new Result(false)); } } var occurrences = new Queue <IncludingEx>(); var stringFunctions = MetricRelatedFunctions.Get(category); Debug.Assert(stringFunctions.GetEnumerator().MoveNext()); var functions = new HashSet <string>(stringFunctions); foreach (var inclusion in parser.Inclusions) { var expressions = new Queue <Expression>(); expressions.Enqueue(inclusion.Target); var isDynamic = false; while (expressions.Count > 0) { var expression = expressions.Dequeue(); // Note that the strings beginning with quotes are automatically broken down by variables var concatenation = expression as ConcatEx; if (concatenation != null) { foreach (var operand in concatenation.Expressions) { expressions.Enqueue(operand); } } else { var functionCall = expression as DirectFcnCall; if (functionCall != null) { // The subroutine must be function, i.e. it must not be member of a class if (functionCall.IsMemberOf == null // The number of parameters must be exactly 1 && functionCall.CallSignature.Parameters.Count == 1 // Function names are case-insensitive && functions.Contains(functionCall.QualifiedName.Name.LowercaseValue)) { expressions.Enqueue(functionCall.CallSignature.Parameters[0].Expression); } else { isDynamic = true; break; } } else if (!(expression is StringLiteral)) { // It is not correct terminal symbol of the expression, a string isDynamic = true; break; } } } if (isDynamic) { occurrences.Enqueue(inclusion); } } var hasOccurrence = occurrences.GetEnumerator().MoveNext(); // Return inclusions (IncludingEx) that cannot be evaluated statically return(new Result(hasOccurrence, occurrences)); }
/// <inheritdoc /> public override Result Process(bool resolveOccurances, ConstructIndicator category, SyntaxParser parser) { Debug.Assert(category == ConstructIndicator.MagicMethods, "Metric of class must be same as passed metric"); Debug.Assert(parser.IsParsed, "Source code must be parsed"); Debug.Assert(!parser.Errors.AnyError, "Source code must not have any syntax error"); if (parser.Types == null) { // No type is declared if (resolveOccurances) { return(new Result(false, new TypeDecl[0])); } else { return(new Result(false)); } } var occurrences = new Queue <TypeDecl>(); var methodNames = MetricRelatedFunctions.Get(category); Debug.Assert(methodNames.GetEnumerator().MoveNext()); var methods = new HashSet <string>(methodNames); foreach (var type in parser.Types) { var node = type.Value.Declaration.GetNode(); var typeNode = node as TypeDecl; Debug.Assert(typeNode != null); // Interfaces cannot have magic methods because they cannot implement them if ((typeNode.AttributeTarget & PhpAttributeTargets.Class) != 0) { foreach (var member in typeNode.Members) { var method = member as MethodDecl; if (method != null) { // Names are defined in IsCallName, IsCallStaticName, IsCloneName, // IsConstructName, IsDestructName, IsToStringName properties and as constants // in PHP.Core.Reflection.DObject.SpecialMethodNames // Names of methods are case insensitive if (methods.Contains(method.Name.LowercaseValue)) { // Correct signature is not checking occurrences.Enqueue(typeNode); if (!resolveOccurances) { return(new Result(true)); } } } } } } var hasOccurrence = occurrences.GetEnumerator().MoveNext(); // Return classes (TypeDecl) which contain any magic method declaration return(new Result(hasOccurrence, occurrences.ToArray())); }
/// <inheritdoc /> public override Result Process(bool resolveOccurances, ConstructIndicator category, SyntaxParser parser) { Debug.Assert(category == ConstructIndicator.Autoload, "Metric of class must be same as passed metric"); Debug.Assert(parser.IsParsed, "Source code must be parsed"); Debug.Assert(!parser.Errors.AnyError, "Source code must not have any syntax error"); if ((parser.Functions == null) && (parser.Types == null)) { // No function or type is declared if (resolveOccurances) { return(new Result(false, new LangElement[0])); } else { return(new Result(false)); } } var occurrences = new Queue <LangElement>(); foreach (var routine in parser.Functions) { var phpFunction = routine.Value.Member as PhpFunction; Debug.Assert(phpFunction != null); var declaration = phpFunction.Declaration.GetNode() as FunctionDecl; Debug.Assert(declaration != null, "PhpFunction is always in function declaration node"); // Check whether name of the function is "__autoload" if (routine.Key.IsAutoloadName) { // Does not check that __autoload takes exactly 1 argument occurrences.Enqueue(declaration); } } var functions = MetricRelatedFunctions.Get(category); // All occurrences of autoload register function calls var calls = FindCalls(parser, functions); foreach (var node in calls) { var call = node as DirectFcnCall; Debug.Assert(call != null); var parameters = call.CallSignature.Parameters; // If no parameter is provided, then the default implementation // of spl_autoload() will be registered if (parameters.Count > 0) { var expression = parameters[0].Expression; // If expression is null, all callbacks are unregistered var literal = expression as StringLiteral; if (literal != null) { var value = literal.Value as string; Debug.Assert(value != null); var declaration = FindFunctionDeclaration(value, parser.Functions); if (declaration != null) { occurrences.Enqueue(declaration); } } else if (expression is ArrayEx) { var array = expression as ArrayEx; var items = array.Items; // Array define class (reference or name) and function name if (items.Count == 2) { var valueItem = array.Items[0] as ValueItem; if (valueItem != null) { // Expression that define class (reference or name) var classExpression = valueItem.ValueExpr; valueItem = array.Items[1] as ValueItem; if (valueItem != null) { var stringLiteral = valueItem.ValueExpr as StringLiteral; if (stringLiteral != null) { // Name of method var methodName = stringLiteral.Value as string; Debug.Assert(methodName != null); var declaration = FindMethodDeclaration(classExpression, methodName, parser.Types); if (declaration != null) { occurrences.Enqueue(declaration); } } } } } } } } var hasOccurrence = occurrences.GetEnumerator().MoveNext(); // Return functions (FunctionDecl) or methods (MethodDecl) possibly // registered as __autoload() implementations. return(new Result(hasOccurrence, occurrences.ToArray())); }