Example #1
0
        public async Task FixAsync(CancellationToken cancellationToken = default)
        {
            ImmutableArray <ProjectId> projects = CurrentSolution
                                                  .GetProjectDependencyGraph()
                                                  .GetTopologicallySortedProjects(cancellationToken)
                                                  .ToImmutableArray();

            foreach (string projectName in Options.IgnoredProjectNames.OrderBy(f => f))
            {
                WriteLine($"Project '{projectName}' will be ignored");
            }

            foreach (string id in Options.IgnoredDiagnosticIds.OrderBy(f => f))
            {
                WriteLine($"Diagnostic '{id}' will be ignored");
            }

            foreach (string id in Options.IgnoredCompilerDiagnosticIds.OrderBy(f => f))
            {
                WriteLine($"Compiler diagnostic '{id}' will be ignored");
            }

            Stopwatch stopwatch = Stopwatch.StartNew();

            TimeSpan lastElapsed = TimeSpan.Zero;

            for (int i = 0; i < projects.Length; i++)
            {
                cancellationToken.ThrowIfCancellationRequested();

                Project project = CurrentSolution.GetProject(projects[i]);

                WriteLine($"Fix project {$"{i + 1}/{projects.Length}"} '{project.Name}'", ConsoleColor.Cyan);

                if (Options.IgnoredProjectNames.Contains(project.Name))
                {
                    WriteLine($"  Project '{project.Name}' is ignored");
                }
                else
                {
                    FixResult result = await FixProjectAsync(project, cancellationToken).ConfigureAwait(false);

                    if (result == FixResult.CompilerError)
                    {
                        break;
                    }
                }

                TimeSpan elapsed = stopwatch.Elapsed;

                WriteLine($"Done fixing project {$"{i + 1}/{projects.Length}"} {elapsed - lastElapsed:mm\\:ss\\.ff} '{project.Name}'", ConsoleColor.Green);

                lastElapsed = elapsed;
            }

            stopwatch.Stop();

            WriteLine($"Done fixing solution {stopwatch.Elapsed:mm\\:ss\\.ff} '{CurrentSolution.FilePath}'", ConsoleColor.Green);
        }
 public bool BetterThan(FixResult anotherResult)
 {
     if (Success && !anotherResult.Success ||
         Length < anotherResult.Length ||
         ErrSum / anotherResult.ErrSum < 0.01)
     {
         return(true);
     }
     return(false);
 }
Example #3
0
        public async Task <ProjectFixResult> FixProjectAsync(Project project, CancellationToken cancellationToken = default)
        {
            (ImmutableArray <DiagnosticAnalyzer> analyzers, ImmutableArray <CodeFixProvider> fixers) = _analyzerLoader.GetAnalyzersAndFixers(project: project);

            FixResult fixResult = await FixProjectAsync(project, analyzers, fixers, cancellationToken).ConfigureAwait(false);

            project = CurrentSolution.GetProject(project.Id);

            Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            Dictionary <string, ImmutableArray <CodeFixProvider> > fixersById = fixers
                                                                                .SelectMany(f => f.FixableDiagnosticIds.Select(id => (id, fixer: f)))
                                                                                .GroupBy(f => f.id)
                                                                                .ToDictionary(f => f.Key, g => g.Select(f => f.fixer).Distinct().ToImmutableArray());

            ImmutableArray <Diagnostic> unfixableDiagnostics = await GetDiagnosticsAsync(
                analyzers,
                fixResult.FixedDiagnostics,
                compilation,
                project.AnalyzerOptions,
                f => !fixersById.ContainsKey(f.id),
                cancellationToken)
                                                               .ConfigureAwait(false);

            ImmutableArray <Diagnostic> unfixedDiagnostics = await GetDiagnosticsAsync(
                analyzers,
                fixResult.FixedDiagnostics.Concat(unfixableDiagnostics),
                compilation,
                project.AnalyzerOptions,
                f => fixersById.ContainsKey(f.id),
                cancellationToken)
                                                             .ConfigureAwait(false);

            int numberOfAddedFileBanners = 0;

            if (Options.FileBannerLines.Any())
            {
                numberOfAddedFileBanners = await AddFileBannerAsync(CurrentSolution.GetProject(project.Id), Options.FileBannerLines, cancellationToken).ConfigureAwait(false);
            }

            ImmutableArray <DocumentId> formattedDocuments = ImmutableArray <DocumentId> .Empty;

            if (Options.Format)
            {
                formattedDocuments = await FormatProjectAsync(CurrentSolution.GetProject(project.Id), cancellationToken).ConfigureAwait(false);
            }

            var result = new ProjectFixResult(
                kind: fixResult.Kind,
                fixedDiagnostics: fixResult.FixedDiagnostics.Select(f => DiagnosticInfo.Create(f)),
                unfixedDiagnostics: unfixedDiagnostics.Select(f => DiagnosticInfo.Create(f)),
                unfixableDiagnostics: unfixableDiagnostics.Select(f => DiagnosticInfo.Create(f)),
                numberOfFormattedDocuments: (Options.FileBannerLines.Any()) ? formattedDocuments.Length : -1,
                numberOfAddedFileBanners: (Options.Format) ? numberOfAddedFileBanners : -1);

            LogHelpers.WriteFixSummary(
                fixResult.FixedDiagnostics,
                unfixedDiagnostics,
                unfixableDiagnostics,
                baseDirectoryPath: Path.GetDirectoryName(project.FilePath),
                indentation: "  ",
                formatProvider: FormatProvider,
                verbosity: Verbosity.Detailed);

            return(result);
        }
Example #4
0
        private async Task <FixResult> FixProjectAsync(Project project, CancellationToken cancellationToken = default)
        {
            string language = project.Language;

            ImmutableArray <Assembly> assemblies = (Options.IgnoreAnalyzerReferences) ? ImmutableArray <Assembly> .Empty : project.AnalyzerReferences
                                                   .Distinct()
                                                   .OfType <AnalyzerFileReference>()
                                                   .Select(f => f.GetAssembly())
                                                   .Where(f => !_analyzerFiles.Contains(f.FullName))
                                                   .ToImmutableArray();

            ImmutableArray <DiagnosticAnalyzer> analyzers = _analyzerFiles
                                                            .GetAnalyzers(language)
                                                            .AddRange(_analyzerFileCache.GetAnalyzers(assemblies, language));

            if (!analyzers.Any())
            {
                return(FixResult.NoAnalyzers);
            }

            ImmutableArray <CodeFixProvider> fixers = _analyzerFiles
                                                      .GetFixers(language)
                                                      .AddRange(_analyzerFileCache.GetFixers(assemblies, language));

            if (!fixers.Any())
            {
                return(FixResult.NoFixers);
            }

            Dictionary <string, ImmutableArray <DiagnosticAnalyzer> > analyzersById = analyzers
                                                                                      .SelectMany(f => f.SupportedDiagnostics.Select(id => (id.Id, analyzer: f)))
                                                                                      .GroupBy(f => f.Id)
                                                                                      .ToDictionary(f => f.Key, g => g.Select(f => f.analyzer).Distinct().ToImmutableArray());

            Dictionary <string, ImmutableArray <CodeFixProvider> > fixersById = fixers
                                                                                .Where(f => f.GetFixAllProvider() != null)
                                                                                .SelectMany(f => f.FixableDiagnosticIds.Select(id => (id, fixer: f)))
                                                                                .GroupBy((f) => f.id)
                                                                                .ToDictionary(f => f.Key, g => g.Select(f => f.fixer).ToImmutableArray());

            ImmutableArray <Diagnostic> previousDiagnostics = ImmutableArray <Diagnostic> .Empty;

            int iterationCount = 1;

            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                project = CurrentSolution.GetProject(project.Id);

                WriteLine($"  Compile '{project.Name}'{((iterationCount > 1) ? $" iteration {iterationCount}" : "")}");

                Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                if (!VerifyCompilerDiagnostics(compilation, cancellationToken))
                {
                    return(FixResult.CompilerError);
                }

                var compilationWithAnalyzers = new CompilationWithAnalyzers(compilation, analyzers, DefaultCompilationWithAnalyzersOptions);

                WriteLine($"  Analyze '{project.Name}'");

                ImmutableArray <Diagnostic> diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);

                foreach (string message in diagnostics
                         .Where(f => f.Id.StartsWith("AD", StringComparison.Ordinal))
                         .Select(f => f.ToString())
                         .Distinct())
                {
                    WriteLine(message, ConsoleColor.Yellow);
                }

                diagnostics = diagnostics
                              .Where(f => f.Severity != DiagnosticSeverity.Hidden &&
                                     analyzersById.ContainsKey(f.Id) &&
                                     fixersById.ContainsKey(f.Id) &&
                                     !Options.IgnoredDiagnosticIds.Contains(f.Id))
                              .ToImmutableArray();

                int length = diagnostics.Length;

                if (length == 0)
                {
                    break;
                }

                if (length == previousDiagnostics.Length &&
                    !diagnostics.Except(previousDiagnostics, DiagnosticDeepEqualityComparer.Instance).Any())
                {
                    break;
                }

                WriteLine($"  Found {length} {((length == 1) ? "diagnostic" : "diagnostics")} in '{project.Name}'");

                foreach (string diagnosticId in diagnostics
                         .Select(f => f.Id)
                         .Distinct()
                         .OrderBy(f => f))
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    FixResult result = await FixDiagnosticsAsync(
                        diagnosticId,
                        CurrentSolution.GetProject(project.Id),
                        analyzersById[diagnosticId],
                        fixersById[diagnosticId],
                        cancellationToken).ConfigureAwait(false);

                    if (result == FixResult.CompilerError)
                    {
                        return(result);
                    }
                }

                previousDiagnostics = diagnostics;
                iterationCount++;
            }

            return(FixResult.Success);
        }
        private void InitializeBackgroundWorker()
        {
            this.MainProgressBar.Value = 5;
            var backgroundWorker = new BackgroundWorker();

            backgroundWorker.WorkerReportsProgress = true;
            backgroundWorker.DoWork += (sender, e) =>
            {
                var bgWorker = sender as BackgroundWorker;
                if (bgWorker != null)
                {
                    OverallResult overallResult = OverallResult.None;
                    var           stringTable   = Localization.LocalizationManager.Get();

                    var agents = Utilities.RemovalAgentFactory.GetRemovalAgents().ToList();
                    if (agents != null && agents.Any())
                    {
                        foreach (var agent in agents)
                        {
                            try
                            {
                                double    percentageComplete = ((double)(agents.IndexOf(agent) + 1) / (double)agents.Count) * 100;
                                FixResult removalResult      = TryToExecuteRemoval(agent);
                                bgWorker.ReportProgress(Convert.ToInt32(percentageComplete), removalResult);
                                OverallResult thisResult = CalculateSingleResult(removalResult);
                                overallResult = CalculateMergedResult(overallResult, thisResult);
                                System.Threading.Thread.Sleep(1000);     // Some of the agents perform very quickly.  Slow it down to show each step
                            }
                            catch (Exception ex)
                            {
                                Logging.Logger.Log(Logging.LogSeverity.Error, ex.Message);
                            }
                        }
                    }

                    bgWorker.ReportProgress(100, overallResult);
                    System.Threading.Thread.Sleep(500);     // Let the user see the final 100% before hiding progress bar
                }
            };


            backgroundWorker.ProgressChanged += (sender, e) =>
            {
                if (e != null)
                {
                    if (e.UserState == null)
                    {
                        this.UpdateOverallStatusLabel(OverallResult.Error);
                    }
                    else
                    {
                        this.MainProgressBar.Value = e.ProgressPercentage;
                        var result = e.UserState as Utilities.FixResult;
                        if (result != null)
                        {
                            this.AddLabelBasedOnIndividualResult(result);
                        }
                        else
                        {
                            var overallStatus = (OverallResult)e.UserState;
                            if (overallStatus != OverallResult.None)
                            {
                                this.UpdateOverallStatusLabel(overallStatus);
                                this.UpdateRestartButtons(overallStatus);
                            }
                        }
                    }
                }
            };
            backgroundWorker.RunWorkerCompleted += (sender, e) =>
            {
                this.IsDoingWork           = false;
                this.MainProgressBar.Value = 0;
            };

            backgroundWorker.RunWorkerAsync(); // Start!
        }