コード例 #1
0
        /// <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));
        }
コード例 #2
0
        /// <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));
        }
コード例 #3
0
        /// <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()));
        }
コード例 #4
0
        /// <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()));
        }