public void Run() { IAnalysisResult analysisResult; if (!ProjectAnalysisUtils.TryChooseAnalysisResult(out analysisResult)) { return; } Debug.Assert(analysisResult != null); var codeBase = analysisResult.CodeBase; Func <string, IQueryCompiled> compileQueryProc = queryString => queryString.Compile(codeBase); // ... but if we can get a compareContext, then compile and execute the query against the compareContext ICompareContext compareContext; string baselineDesc; if (ProjectAnalysisUtils.TryGetCompareContextDefinedByBaseline(analysisResult, out compareContext, out baselineDesc)) { Debug.Assert(compareContext != null); compileQueryProc = queryString => queryString.Compile(compareContext); Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(baselineDesc); } // // Fill queriesPreviouslyEdited with current project queries // IPreviousNextStack <string> queriesPreviouslyEdited = new PreviousNextStack <string>( analysisResult.AnalysisResultRef.Project.CodeQueries.CodeQueriesSet.AllQueriesRecursive.Reverse().Select(q => q.QueryString), "", (s1, s2) => s1 == s2); // With this line, make sure to begin with the first queries of the project. queriesPreviouslyEdited.GetPrevious(); // // Loop for each query edition // while (true) { IQueryCompiled queryCompiled; using (var queryEditSession = new QueryEditSession(queriesPreviouslyEdited)) { var queryString = queryEditSession.GetQueryString(); COMPILE_QUERY: Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.White; if (queryString == null) { break; } // Try compile query queryCompiled = compileQueryProc(queryString); var queryCompiledError = queryCompiled.QueryCompiledError; if (queryCompiledError != null) { queryString = queryEditSession.ShowCompilatioErrorsAndThenGetQueryString(queryCompiledError); goto COMPILE_QUERY; } } // Execute query compiled var queryCompiledSuccess = queryCompiled.QueryCompiledSuccess; Debug.Assert(queryCompiledSuccess != null); var result = queryCompiledSuccess.Execute(); if (result.Status != QueryExecutionStatus.Success) { var exception = result.Exception; // The error must be an Exception thrown by the query, since we don't use the Execute(...) overload with time-out! Debug.Assert(exception != null); DisplayQueryThrowAnException(exception); continue; } QueryExecutionResultDisplayer.Go(result.SuccessResult); Console.WriteLine(); } }
public void Run() { // Choose project and analysis result IAnalysisResult analysisResult; if (!ProjectAnalysisUtils.TryChooseAnalysisResult(out analysisResult)) { return; } Debug.Assert(analysisResult != null); var project = analysisResult.AnalysisResultRef.Project; // Try load the project baseline ICompareContext compareContext; string baselineDesc; if (!ProjectAnalysisUtils.TryGetCompareContextDefinedByBaseline(analysisResult, out compareContext, out baselineDesc)) { Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Cannot load a baseline for the project {" + project.Properties.Name + "}"); return; } Debug.Assert(compareContext != null); SetRegularColors(); Console.WriteLine(baselineDesc); // Compute issues-set-diff // To compute issue only on a single analysisResult just use: analysisResult.ComputeIssues() SetRegularColors(); Console.WriteLine("Computing issues on both now and baseline snapshots."); var issuesSetDiff = analysisResult.ComputeIssuesDiff(compareContext); var debtFormatter = project.DebtSettings.Values.CreateDebtFormatter(); // // Technical Debt // WriteTitle("Technical Debt"); ShowFromToLine("Technical debt", issuesSetDiff, issuesSet => debtFormatter.ToManDayString(issuesSet.AllDebt)); ShowFromToLine("Technical debt Rating", issuesSetDiff, issuesSet => { DebtRating?debtRatingNullable = issuesSet.DebtRating(issuesSet.CodeBase); if (!debtRatingNullable.HasValue) { return("N/A"); } DebtRating debtRating = debtRatingNullable.Value; // Possible to change color in this getValueProc because it is called just before outputing the value on console // However cannot use debtRating.ToForeColor() and debtRating.ToBackColor() to change the console // since console colors are fixed with the enum ConsoleColor. ConsoleColor foreColor, backColor; switch (debtRating) { default: backColor = ConsoleColor.Green; foreColor = ConsoleColor.White; break; // Case DebtRating.A case DebtRating.B: backColor = ConsoleColor.DarkGreen; foreColor = ConsoleColor.White; break; case DebtRating.C: backColor = ConsoleColor.Yellow; foreColor = ConsoleColor.Black; break; case DebtRating.D: backColor = ConsoleColor.DarkRed; foreColor = ConsoleColor.White; break; case DebtRating.E: backColor = ConsoleColor.Red; foreColor = ConsoleColor.White; break; } SetColors(backColor, foreColor); return(debtRatingNullable.Value.ToString()); }); ShowFromToLine("Annual Interest", issuesSetDiff, issuesSet => debtFormatter.ToManDayString(issuesSet.AllAnnualInterest)); // // Quality Gates // WriteTitle("Quality Gates"); ShowFromToLine("# Quality Gates Fail", issuesSetDiff, issuesSet => issuesSet.AllQualityGates.Count(qg => qg.Fail).ToString(), SetValueRedColors); ShowFromToLine("# Quality Gates Warn", issuesSetDiff, issuesSet => issuesSet.AllQualityGates.Count(qg => qg.Warn).ToString(), SetValueYellowColors); ShowFromToLine("# Quality Gates Pass", issuesSetDiff, issuesSet => issuesSet.AllQualityGates.Count(qg => qg.Pass).ToString(), SetValueGreenColors); SetInfoColors(); Console.WriteLine("Quality Gates that rely on diff since baseline are not counted in the 'from' number."); // // Rules // WriteTitle("Rules"); ShowFromToLine("# Critical Rules violated", issuesSetDiff, issuesSet => issuesSet.AllRules.Count(r => r.IsCritical && issuesSet.IsViolated(r)).ToString(), SetValueRedColors); ShowFromToLine("# Rules violated", issuesSetDiff, issuesSet => issuesSet.AllRules.Count(issuesSet.IsViolated).ToString(), SetValueDarkRedColors); ShowFromToLine("# Rules non violated", issuesSetDiff, issuesSet => issuesSet.AllRules.Count(r => !issuesSet.IsViolated(r)).ToString(), SetValueGreenColors); SetInfoColors(); Console.WriteLine("Rules that rely on diff since baseline are not counted in the 'from' number."); // // Issues // WriteTitle("Issues"); ShowFromToLineForIssues("# issues", issuesSetDiff, issuesSet => issuesSet.AllIssues.ToArray()); foreach (var severity in new[] { Severity.Blocker, Severity.Critical, Severity.High, Severity.Medium, Severity.Low }) { var severityTmp = severity; // Needed to avoid access foreach variable in closure! ShowFromToLineForIssues("# " + Enum.GetName(typeof(Severity), severityTmp) + " issues", issuesSetDiff, issuesSet => issuesSet.AllIssues.Where(i => i.Severity == severityTmp).ToArray()); } SetInfoColors(); Console.WriteLine("In red # issues added since baseline, in green # issues fixed since baseline."); Console.WriteLine("The severity of an issue can change. Hence a change in # total issues for a certain severity level"); Console.WriteLine("doesn't necessarily correspond to a change in # added / # fixed."); // // Quality Gates Details // WriteTitle("Quality Gates Details"); foreach (var qualityGate in issuesSetDiff.NewerIssuesSet.AllQualityGates) { WriteQualityGateDetails(qualityGate, issuesSetDiff.OlderVersion(qualityGate)); } SetInfoColors(); Console.WriteLine("Quality Gates that rely on diff don't have a value computed on baseline."); }