/// <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); }