private static Options ParseCommandLineArgs(string[] args) { var options = new Options(); bool result = CommandLine.Parser.Default.ParseArguments(args, options); if (!result) { Console.WriteLine(HelpText.AutoBuild(options).ToString()); return null; } return options; }
private static Tuple<string, Assembly> ValidateOptionsAndLoadAnalyzer(Options options) { if (Path.GetExtension(options.Solution) != ".sln") { Console.WriteLine($"'{options.Solution}' is not a valid solution file."); return null; } if (!File.Exists(options.Solution)) { Console.WriteLine($"Provided solution file ('{options.Solution}') does not exists. "); return null; } var analyzerExtension = Path.GetExtension(options.Analyzer); if (analyzerExtension != ".dll" && analyzerExtension != ".exe") { Console.WriteLine($"Provided analyzer '{options.Analyzer}' is not dll or exe"); return null; } if (!File.Exists(options.Analyzer)) { Console.WriteLine($"Provided analyzer ('{options.Analyzer}') does not exists. "); } if (!string.IsNullOrEmpty(options.LogFile)) { options.LogFile = Path.GetFullPath(options.LogFile); Console.WriteLine($"Log file enabled ('{options.LogFile}')"); if (File.Exists(options.LogFile)) { // Need to move it out! File.Delete(options.LogFile); } } try { return Tuple.Create(options.Solution, Assembly.LoadFile(options.Analyzer)); } catch (Exception e) { Console.WriteLine($"Failed to load analyzer '{options.Analyzer}':{Environment.NewLine}:{e}"); return null; } }
private static async Task AnalyzeSolutionAsync(string solutionFile, Assembly analyzer, Options options) { var analyzers = GetAnalyzers(analyzer).ToImmutableArray(); // Loading the solution var sw = Stopwatch.StartNew(); var workspace = MSBuildWorkspace.Create(); WriteInfo($"Opening solution '{solutionFile}'...", enabled: true); var solution = await workspace.OpenSolutionAsync(solutionFile); WriteInfo($"Loaded solution in {sw.ElapsedMilliseconds}ms with '{solution.ProjectIds.Count}' projects and '{solution.DocumentsCount()}' documents", enabled: true); WriteInfo("Running the analysis...", enabled: true); // Running the analysis sw.Restart(); var diagnostics = await AnalyseSolutionAsync(solution, analyzers, options); WriteInfo($"Found {diagnostics.SelectMany(d => d.Diagnostics).Count()} diagnostics in {sw.ElapsedMilliseconds}ms", enabled: true); //PrintDiagnostics(diagnostics, options); }
private static async Task<List<ProjectAnalysisResult>> AnalyseSolutionAsync(Solution solution, ImmutableArray<DiagnosticAnalyzer> analyzers, Options options) { var ruleIds = analyzers.SelectMany(a => a.SupportedDiagnostics.Select(d => d.Id)).ToImmutableHashSet(); var projectAnalysisTasks = solution.Projects.Select(p => new {Project = p, Task = AnalyzeProjectAsync(p, analyzers)}).ToList(); foreach (var task in projectAnalysisTasks) { var local = task; #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed task.Task.ContinueWith(tsk => { var relevantRules = tsk.Result.Where(d => ruleIds.Contains(d.Id)).ToImmutableArray(); if (options.PrintWarningsAndErrors) { PrintDiagnostics(local.Project, relevantRules); } if (!string.IsNullOrEmpty(options.LogFile)) { WriteDiagnosticsToLog(options.LogFile, local.Project, relevantRules); } }, TaskContinuationOptions.OnlyOnRanToCompletion); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed } await Task.WhenAll(projectAnalysisTasks.Select(p => p.Task)); var result = projectAnalysisTasks .Select(r => new ProjectAnalysisResult(r.Project, r.Task.Result.Where(d => ruleIds.Contains(d.Id)).ToImmutableArray())).ToList(); return result; }