Exemplo n.º 1
0
        /// <summary>
        /// Returns functions which presence indicates metric usage.
        /// </summary>
        /// <param name="metric">Metric that looks for presence of returned functions.</param>
        /// <returns>Functions which presence indicates metric usage.</returns>
        public static IEnumerable <string> Get(ConstructIndicator metric)
        {
            string[] output;
            if (!functions.TryGetValue(metric, out output))
            {
                return(new string[0]);
            }

            return(output);
        }
Exemplo n.º 2
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));
        }
Exemplo n.º 3
0
        /// <inheritdoc />
        public override Result Process(bool resolveOccurances, ConstructIndicator category,
                                       SyntaxParser parser)
        {
            Debug.Assert(category == ConstructIndicator.References,
                         "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");

            var visitor = new AliasVisitor();

            parser.Ast.VisitMe(visitor);

            var occurrences   = visitor.GetOccurrences();
            var hasOccurrence = occurrences.GetEnumerator().MoveNext();

            return(new Result(hasOccurrence, occurrences));
        }
Exemplo n.º 4
0
        /// <inheritdoc />
        public override Result Process(bool resolveOccurances, ConstructIndicator category,
                                       SyntaxParser parser)
        {
            Debug.Assert(category == ConstructIndicator.DuckTyping,
                         "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");

            var visitor = new DuckTypingVisitor();

            parser.Ast.VisitMe(visitor);

            var occurrences   = visitor.GetOccurrences();
            var hasOccurrence = occurrences.GetEnumerator().MoveNext();

            // Return all variable-like constructs (VarLikeConstructUse) with use of member of unknown object
            return(new Result(hasOccurrence, occurrences));
        }
Exemplo n.º 5
0
        /// <inheritdoc />
        public override Result Process(bool resolveOccurances, ConstructIndicator category,
                                       SyntaxParser parser)
        {
            Debug.Assert(category == ConstructIndicator.InsideFunctionDeclaration,
                         "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");

            // PHP.Core.AST.FunctionDecl.Function.IsIdentityDefinite may imply that
            // if declaration is inside function, it is conditional (but not otherwise).
            var visitor = new InsideFunctionDeclarationVisitor();

            parser.Ast.VisitMe(visitor);

            var occurrences   = visitor.GetOccurrences();
            var hasOccurrence = occurrences.GetEnumerator().MoveNext();

            // Return classes (TypeDecl) and functions (FunctionDecl) declared inside a subroutine.
            return(new Result(hasOccurrence, occurrences));
        }
Exemplo n.º 6
0
        /// <inheritdoc />
        public override Result Process(bool resolveOccurances, ConstructIndicator category,
                                       SyntaxParser parser)
        {
            Debug.Assert(category == ConstructIndicator.ClassOrInterface,
                         "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");

            var types = new Queue <TypeDecl>();

            foreach (var type in parser.Types)
            {
                var node            = type.Value.Declaration.GetNode();
                var typeDeclaration = node as TypeDecl;
                Debug.Assert(typeDeclaration != null, "PhpType is always in type declaration node");

                types.Enqueue(typeDeclaration);
            }

            var hasTypes = types.GetEnumerator().MoveNext();

            return(new Result(hasTypes, types));
        }
Exemplo n.º 7
0
        /// <inheritdoc />
        public override Result Process(bool resolveOccurances, ConstructIndicator category,
                                       SyntaxParser parser)
        {
            System.Diagnostics.Debug.Assert(category == ConstructIndicator.PassingByReferenceAtCallSide,
                                            "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 type is declared
                if (resolveOccurances)
                {
                    return(new Result(false, new FunctionCall[0]));
                }
                else
                {
                    return(new Result(false));
                }
            }

            var functions = (parser.Functions != null) ? parser.Functions
                : new Dictionary <QualifiedName, ScopedDeclaration <DRoutine> >();
            var types = (parser.Types != null) ? parser.Types
                : new Dictionary <QualifiedName, PhpType>();

            var visitor = new PassingByReferenceVisitor(functions, types);

            parser.Ast.VisitMe(visitor);

            var occurrences   = visitor.GetOccurrences();
            var hasOccurrence = occurrences.GetEnumerator().MoveNext();

            // Return function (DirectFcnCall) or static method (DirectStMtdCall) calls
            // (both are subtypes of FunctionCall) which pass at least one parameter by reference
            return(new Result(hasOccurrence, occurrences));
        }
Exemplo n.º 8
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));
        }
Exemplo n.º 9
0
        private static void RunMetrics(string[] files)
        {
            Dictionary <ConstructIndicator, string> contructMetrics = new Dictionary <ConstructIndicator, string>();

            contructMetrics.Add(ConstructIndicator.Autoload, "__autoload redeclaration presence or spl_autoload_register call");
            contructMetrics.Add(ConstructIndicator.MagicMethods, "Magic function presence");
            contructMetrics.Add(ConstructIndicator.ClassOrInterface, "Class construct presence");
            contructMetrics.Add(ConstructIndicator.DynamicInclude, "Include based on dynamic variable presence");
            contructMetrics.Add(ConstructIndicator.References, "Alias presence");

            contructMetrics.Add(ConstructIndicator.Session, "Session usage");
            contructMetrics.Add(ConstructIndicator.InsideFunctionDeclaration, "Declaration of class/function inside another function presence");
            contructMetrics.Add(ConstructIndicator.SuperGlobalVariable, "Super global variable usage");
            contructMetrics.Add(ConstructIndicator.Eval, "Eval function usage");
            contructMetrics.Add(ConstructIndicator.DynamicCall, "Dynamic call presence");

            contructMetrics.Add(ConstructIndicator.DynamicDereference, "Dynamic dereference presence");
            contructMetrics.Add(ConstructIndicator.DuckTyping, "Duck Typing presence");
            contructMetrics.Add(ConstructIndicator.PassingByReferenceAtCallSide, "Passing variable by reference at call site");
            contructMetrics.Add(ConstructIndicator.MySql, "My SQL functions presence");
            contructMetrics.Add(ConstructIndicator.ClassAlias, "Class alias construction presence");

            Dictionary <Rating, string> ratingMetrics = new Dictionary <Rating, string>();

            ratingMetrics.Add(Rating.ClassCoupling, "Class coupling");
            ratingMetrics.Add(Rating.PhpFunctionsCoupling, "PHP standard functions coupling");

            Dictionary <Quantity, string> quantityMetrics = new Dictionary <Quantity, string>();

            quantityMetrics.Add(Quantity.MaxInheritanceDepth, "Maximum inheritance depth");
            quantityMetrics.Add(Quantity.NumberOfLines, "Number of lines");
            quantityMetrics.Add(Quantity.NumberOfSources, "Number of sources");
            quantityMetrics.Add(Quantity.MaxMethodOverridingDepth, "Maximum method overriding depth");


            var console = new ConsoleOutput();

            foreach (string file in files)
            {
                console.CommentLine(string.Format("File path: {0}\n", file));
                try
                {
                    string code;
                    using (StreamReader reader = new StreamReader(file))
                    {
                        code = reader.ReadToEnd();
                    }

                    PhpSourceFile source_file = new PhpSourceFile(new FullPath(Path.GetDirectoryName(file)), new FullPath(file));
                    var           metrics     = MetricInfo.FromParsers(true, new SyntaxParser(source_file, code));
                    Console.WriteLine();
                    console.CommentLine("Indicator Metrics");
                    Console.WriteLine();
                    foreach (ConstructIndicator value in ConstructIndicator.GetValues(typeof(ConstructIndicator)))
                    {
                        string result = contructMetrics[value] + " : ";
                        if (metrics.HasIndicator(value))
                        {
                            result += "YES";
                        }
                        else
                        {
                            result += "NO";
                        }
                        console.Metric(result);
                    }
                    Console.WriteLine();
                    console.CommentLine("Rating Metrics");
                    Console.WriteLine();
                    foreach (Rating value in Rating.GetValues(typeof(Rating)))
                    {
                        if (value != Rating.Cyclomacity)
                        {
                            string result = ratingMetrics[value] + " : ";
                            result += metrics.GetRating(value);
                            console.Metric(result);
                        }
                    }
                    Console.WriteLine();
                    console.CommentLine("Quantity Metrics");
                    Console.WriteLine();
                    foreach (Quantity value in Quantity.GetValues(typeof(Quantity)))
                    {
                        string result = quantityMetrics[value] + " : ";
                        result += metrics.GetQuantity(value);
                        console.Metric(result);
                    }
                }
                catch (Exception e)
                {
                    console.Error(e.Message);
                }
            }
            Console.ReadKey();
            Console.WriteLine();
        }
Exemplo n.º 10
0
 /// <summary>
 /// Get predicate for testing of presence given indicator.
 /// </summary>
 /// <param name="indicator"></param>
 /// <returns></returns>
 internal static MetricPredicate GetContainsIndicatorPredicate(ConstructIndicator indicator)
 {
     return((info) => info.HasIndicator(indicator));
 }
Exemplo n.º 11
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()));
        }
Exemplo n.º 12
0
 /// <summary>
 /// Get occurrences for given metric.
 /// NOTE: Occurrence resolving has to be enabled when creating metric info for GetOccurrences usage.
 /// </summary>
 /// <param name="indicator">Metric which occurrences will be returned.</param>
 /// <returns>Resolved occurrences.</returns>
 public IEnumerable <AstNode> GetOccurrences(ConstructIndicator indicator)
 {
     ThrowOnUnresolvedOccurrences();
     return(indicatorBatch.GetResult(indicator).Occurrences);
 }
Exemplo n.º 13
0
 /// <summary>
 /// Determine that metric info has specified indicator set on true.
 /// </summary>
 /// <param name="indicator">A concrete metric from indicators category.</param>
 /// <returns><c>true</c> whether construct appeared in source code.</returns>
 public bool HasIndicator(ConstructIndicator indicator)
 {
     return(indicatorBatch.GetResult(indicator).Property);
 }
Exemplo n.º 14
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()));
        }
Exemplo n.º 15
0
 public static string FormatMetricsResult(ConstructIndicator quantity, MetricResult <bool> metricResult)
 {
     return(string.Format(MetricsResources.ResourceManager.GetString(quantity.ToString()), metricResult.Result ? Resources.Yes : Resources.No));
 }