/// <summary>
 /// Initializes a new instance of the <see cref="TypeMetricsThresholds"/> class
 /// Thresholds for Types (Classes)
 /// </summary>
 /// <param name="activity">Code metrics activity, from where we pick off the incoming values for thresholds</param>
 /// <param name="methodMetricsThresholds">The class thresholds depends on the method thresholds, so we need this first</param>
 internal TypeMetricsThresholds(CodeMetrics activity, MethodMetricsThresholds methodMetricsThresholds)
 {
     this.methodMetricsThresholds      = methodMetricsThresholds;
     this.depthOfInheritanceThresholds = new MetricThresholds(activity.DepthOfInheritanceWarningThreshold.Get(activity.Context), activity.DepthOfInheritanceErrorThreshold.Get(activity.Context));
     this.couplingThresholds           = new MetricThresholds(methodMetricsThresholds.CouplingThresholds);
     this.couplingThresholds          *= CouplingFactor;
     this.linesOfCodeThresholds        = new MetricThresholds(methodMetricsThresholds.LinesOfCodeThresholds);
     this.linesOfCodeThresholds       *= LinesOfCodeFactor;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="TypeMetricsThresholds"/> class
 /// Thresholds for Types (Classes)
 /// </summary>
 /// <param name="activity">Code metrics activity, from where we pick off the incoming values for thresholds</param>
 /// <param name="methodMetricsThresholds">The class thresholds depends on the method thresholds, so we need this first</param>
 internal TypeMetricsThresholds(CodeMetrics activity, MethodMetricsThresholds methodMetricsThresholds)
 {
     this.methodMetricsThresholds = methodMetricsThresholds;
     this.depthOfInheritanceThresholds = new MetricThresholds(activity.DepthOfInheritanceWarningThreshold.Get(activity.Context), activity.DepthOfInheritanceErrorThreshold.Get(activity.Context));
     this.couplingThresholds = new MetricThresholds(methodMetricsThresholds.CouplingThresholds);
     this.couplingThresholds *= CouplingFactor;
     this.linesOfCodeThresholds = new MetricThresholds(methodMetricsThresholds.LinesOfCodeThresholds);
     this.linesOfCodeThresholds *= LinesOfCodeFactor;
 }
        /// <summary>
        /// Executes the logic for this workflow activity
        /// </summary>
        protected override void InternalExecute()
        {
            this.logCodeMetrics = this.LogCodeMetrics.Get(this.ActivityContext);
            this.BuildDetail = this.ActivityContext.GetExtension<IBuildDetail>();
            string generatedFile = "Metrics.xml";

            string outputLocation = this.BuildDetail.DropLocation;
            if (string.IsNullOrEmpty(outputLocation))
            {
                outputLocation = this.BinariesDirectory.Get(this.ActivityContext);
            }

            if (this.GeneratedFileName != null && !string.IsNullOrEmpty(this.GeneratedFileName.Get(this.ActivityContext)))
            {
                generatedFile = Path.Combine(outputLocation, this.GeneratedFileName.Get(this.ActivityContext));
            }

            if (!this.RunCodeMetrics(generatedFile))
            {
                return;
            }

            IActivityTracking currentTracking = this.ActivityContext.GetExtension<IBuildLoggingExtension>().GetActivityTracking(this.ActivityContext);

            if (!this.AnalyzeMetricsResult.Get(this.ActivityContext))
            {
                BaseCodeActivity.AddTextNode("Skipped code metrics analysis (not set to run)", currentTracking.Node);
                return;
            }

            IBuildInformationNode rootNode = AddTextNode("Analyzing code metrics results", currentTracking.Node);

            string fileName = Path.GetFileName(generatedFile);
            string pathToFileInDropFolder = Path.Combine(outputLocation, fileName);
            BaseCodeActivity.AddLinkNode(fileName, new Uri(pathToFileInDropFolder), rootNode);

            CodeMetricsReport result = CodeMetricsReport.LoadFromFile(generatedFile);
            if (result == null)
            {
                this.LogBuildMessage("Could not load metric result file ");
                return;
            }

            // Get thresholds for each level.
            var memberMetricThresholds = new MethodMetricsThresholds(this);
            var typeMetricThresholds = new TypeMetricsThresholds(this, memberMetricThresholds);

            // var namespaceMetricThresholds = new NameSpaceMetricsThresholds(this);  //Uncomment in this if you want to perform metric checks on namespaces
            // var assemblyMetricThresholds = new AssemblyMetricsThresholds(this);  // Uncomment in this if you want to perform metric checks on assemblies
            int noOfTypeViolations = 0;
            int noOfMethodViolations = 0;
            foreach (var target in result.Targets)
            {
                var targetNode = this.logCodeMetrics ? AddTextNode("Target: " + target.Name, rootNode) : null;
                foreach (var module in target.Modules)
                {
                    var moduleNode = this.logCodeMetrics ? AddTextNode("Module: " + module.Name, targetNode) : null;

                    foreach (var ns in module.Namespaces)
                    {
                        var namespaceNode = this.logCodeMetrics ? AddTextNode("Namespace: " + ns.Name, moduleNode) : null;

                        foreach (var type in ns.Types)
                        {
                            var typeNode = this.logCodeMetrics ? AddTextNode("Type: " + type.Name, namespaceNode) : null;
                            var typeInformation = new MemberInformation(null, type, ns, module);
                            noOfTypeViolations += this.ProcessMetrics(typeNode, typeInformation.TheClass.Metrics, typeMetricThresholds, typeInformation.FullyQualifiedName, typeInformation.TheClass.Name);
                            noOfMethodViolations += (from member in type.Members let memberNode = this.logCodeMetrics ? AddTextNode("Member: " + member.Name + " " + member.MetricsInformation, typeNode) : null let memberInformation = new MemberInformation(member, type, ns, module) select this.ProcessMetrics(memberNode, memberInformation.TheMember.Metrics, memberMetricThresholds, memberInformation.FullyQualifiedName, memberInformation.TheMember.Name)).Sum();
                        }
                    }
                }
            }

            var numberMessageTypes = string.Format("Number of Code Metric warnings/errors on types: {0}", noOfTypeViolations);
            var numberMessageMethods = string.Format("Number of Code Metric warnings/errors on methods: {0}", noOfMethodViolations);
            BaseCodeActivity.AddTextNode(numberMessageTypes, rootNode);
            BaseCodeActivity.AddTextNode(numberMessageMethods, rootNode);
        }