Пример #1
0
        public static async Task <CodeAction> GetFixAsync(
            ImmutableArray <Diagnostic> diagnostics,
            DiagnosticDescriptor descriptor,
            CodeFixProvider fixer,
            Project project,
            CodeFixerOptions options,
            IFormatProvider formatProvider      = null,
            CancellationToken cancellationToken = default)
        {
            if (diagnostics.Length == 1)
            {
                return(await GetFixAsync(diagnostics[0], fixer, project, options, formatProvider, cancellationToken).ConfigureAwait(false));
            }

            FixAllProvider fixAllProvider = fixer.GetFixAllProvider();

            if (fixAllProvider == null)
            {
                if (options.DiagnosticIdsFixableOneByOne.Contains(descriptor.Id))
                {
                    return(await GetFixAsync(diagnostics[0], fixer, project, options, formatProvider, cancellationToken).ConfigureAwait(false));
                }

                WriteLine($"  '{fixer.GetType().FullName}' does not have FixAllProvider", ConsoleColor.Yellow, Verbosity.Diagnostic);
                return(null);
            }

            if (!fixAllProvider.GetSupportedFixAllDiagnosticIds(fixer).Any(f => f == descriptor.Id))
            {
                WriteLine($"  '{fixAllProvider.GetType().FullName}' does not support diagnostic '{descriptor.Id}'", ConsoleColor.Yellow, Verbosity.Diagnostic);
                return(null);
            }

            if (!fixAllProvider.GetSupportedFixAllScopes().Any(f => f == FixAllScope.Project))
            {
                WriteLine($"  '{fixAllProvider.GetType().FullName}' does not support scope '{FixAllScope.Project}'", ConsoleColor.Yellow, Verbosity.Diagnostic);
                return(null);
            }

            var multipleFixesInfos = new HashSet <MultipleFixesInfo>();

            CodeAction action = null;

            options.DiagnosticFixMap.TryGetValue(descriptor.Id, out string equivalenceKey);

            foreach (Diagnostic diagnostic in diagnostics)
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (!diagnostic.Location.IsInSource)
                {
                    continue;
                }

                Document document = project.GetDocument(diagnostic.Location.SourceTree);

                if (document == null)
                {
                    continue;
                }

                CodeAction fixCandidate = await GetFixAsync(diagnostic, fixer, document, multipleFixesInfos, options, cancellationToken).ConfigureAwait(false);

                if (fixCandidate == null)
                {
                    continue;
                }

                if (equivalenceKey != null &&
                    equivalenceKey != fixCandidate.EquivalenceKey)
                {
                    break;
                }

                action = fixCandidate;

                var fixAllContext = new FixAllContext(
                    document,
                    fixer,
                    FixAllScope.Project,
                    action.EquivalenceKey,
                    new string[] { descriptor.Id },
                    new FixAllDiagnosticProvider(diagnostics),
                    cancellationToken);

                CodeAction fix = await fixAllProvider.GetFixAsync(fixAllContext).ConfigureAwait(false);

                if (fix != null)
                {
                    WriteLine($"  CodeFixProvider: '{fixer.GetType().FullName}'", ConsoleColor.DarkGray, Verbosity.Diagnostic);

                    if (!string.IsNullOrEmpty(action.EquivalenceKey))
                    {
                        WriteLine($"  EquivalenceKey:  '{action.EquivalenceKey}'", ConsoleColor.DarkGray, Verbosity.Diagnostic);
                    }

                    WriteLine($"  FixAllProvider:  '{fixAllProvider.GetType().FullName}'", ConsoleColor.DarkGray, Verbosity.Diagnostic);

                    return(fix);
                }

                WriteLine($"  Fixer '{fixer.GetType().FullName}' registered no action for diagnostic '{descriptor.Id}'", ConsoleColor.DarkGray, Verbosity.Diagnostic);
                WriteDiagnostics(diagnostics, baseDirectoryPath: Path.GetDirectoryName(project.FilePath), formatProvider: formatProvider, indentation: "    ", maxCount: 10, verbosity: Verbosity.Diagnostic);
            }

            return(null);
        }
Пример #2
0
        private static void WriteCodeFixProviders(IEnumerable <CodeFixProvider> fixers)
        {
            WriteLine("  CodeFixProviders:", Verbosity.Detailed);

            foreach (CodeFixProvider fixer in fixers.OrderBy(f => f.GetType(), TypeComparer.NamespaceThenName))
            {
                Type type = fixer.GetType();

                ExportCodeFixProviderAttribute attribute = type.GetCustomAttribute <ExportCodeFixProviderAttribute>();

                WriteLine($"    {type.FullName}", Verbosity.Detailed);

                if (ShouldWrite(Verbosity.Diagnostic))
                {
                    WriteLine($"      Languages:            {string.Join(", ", attribute.Languages.Select(f => GetShortLanguageName(f)).OrderBy(f => f))}", ConsoleColors.DarkGray, Verbosity.Diagnostic);
                    WriteLine($"      FixableDiagnosticIds: {string.Join(", ", fixer.FixableDiagnosticIds.Distinct().OrderBy(f => f))}", ConsoleColors.DarkGray, Verbosity.Diagnostic);

                    Write("      FixAllProvider:       ", ConsoleColors.DarkGray, Verbosity.Diagnostic);

                    FixAllProvider fixAllProvider = fixer.GetFixAllProvider();

                    if (fixAllProvider != null)
                    {
                        WriteLine($"{fixAllProvider.GetType().FullName} ({string.Join(", ", fixAllProvider.GetSupportedFixAllScopes().Select(f => f.ToString()).OrderBy(f => f))})", ConsoleColors.DarkGray, Verbosity.Diagnostic);
                    }
                    else
                    {
                        WriteLine("-", ConsoleColors.DarkGray, Verbosity.Diagnostic);
                    }
                }
            }
        }
Пример #3
0
 private static XElement SerializeFixAllProvider(FixAllProvider fixAllProvider)
 {
     return(new XElement("FixAllProvider",
                         new XAttribute("Name", fixAllProvider.GetType().AssemblyQualifiedName),
                         new XElement("Scopes", fixAllProvider.GetSupportedFixAllScopes().Select(f => f.ToString()).OrderBy(f => f).Select(f => new XElement("Scope", f)))));
 }
Пример #4
0
        private static async Task <CodeAction> GetFixAsync(
            string diagnosticId,
            Project project,
            ImmutableArray <Diagnostic> diagnostics,
            CodeFixProvider fixer,
            CancellationToken cancellationToken)
        {
            FixAllProvider fixAll = fixer.GetFixAllProvider();

            if (!fixAll.GetSupportedFixAllDiagnosticIds(fixer).Any(f => f == diagnosticId))
            {
                return(null);
            }

            if (!fixAll.GetSupportedFixAllScopes().Any(f => f == FixAllScope.Project))
            {
                return(null);
            }

            foreach (Diagnostic diagnostic in diagnostics)
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (!diagnostic.Location.IsInSource)
                {
                    continue;
                }

                Document document = project.GetDocument(diagnostic.Location.SourceTree);

                Debug.Assert(document != null, "");

                if (document == null)
                {
                    continue;
                }

                CodeAction action = null;

                var context = new CodeFixContext(
                    document,
                    diagnostic,
                    (a, _) =>
                {
                    if (action == null)
                    {
                        action = a;
                    }
                    else if (!string.Equals(a.EquivalenceKey, action.EquivalenceKey, StringComparison.Ordinal))
                    {
#if DEBUG
                        WriteLine($"'{fixer.GetType().Name}' registered multiple actions for diagnostic '{diagnosticId}'", ConsoleColor.DarkYellow);
                        WriteLine($"  {action.EquivalenceKey}", ConsoleColor.DarkYellow);
                        WriteLine($"  {a.EquivalenceKey}", ConsoleColor.DarkYellow);
#endif
                        action = null;
                    }
                },
                    cancellationToken);

                await fixer.RegisterCodeFixesAsync(context).ConfigureAwait(false);

                if (action == null)
                {
                    continue;
                }

                var fixAllContext = new FixAllContext(
                    document,
                    fixer,
                    FixAllScope.Project,
                    action.EquivalenceKey,
                    new string[] { diagnosticId },
                    new FixAllDiagnosticProvider(diagnostics),
                    cancellationToken);

                CodeAction fixAllAction = await fixAll.GetFixAsync(fixAllContext).ConfigureAwait(false);

                if (fixAllAction == null && diagnosticId.StartsWith("RCS"))
                {
                    WriteLine($"'{fixer.GetType().FullName}' registered no action for diagnostics:", ConsoleColor.Magenta);
                    Write(diagnostics, 10, ConsoleColor.Magenta);
                }

                return(fixAllAction);
            }

            return(null);
        }
        public CommandResult Execute(AnalyzeAssemblyCommandLineOptions options)
        {
            var assemblies = new HashSet <Assembly>();

            foreach ((string filePath, AnalyzerAssembly analyzerAssembly) in options.GetPaths()
                     .SelectMany(path => AnalyzerAssembly.LoadFrom(
                                     path: path,
                                     loadAnalyzers: !options.NoAnalyzers,
                                     loadFixers: !options.NoFixers,
                                     language: Language))
                     .OrderBy(f => f.analyzerAssembly.GetName().Name)
                     .ThenBy(f => f.filePath))
            {
                if (assemblies.Add(analyzerAssembly.Assembly))
                {
                    Write($"{analyzerAssembly.FullName}", ConsoleColor.Cyan, Verbosity.Minimal);
                    WriteLine($" [{filePath}]", Verbosity.Minimal);
                }
                else
                {
                    Write($"{analyzerAssembly.FullName}", ConsoleColor.DarkGray, Verbosity.Minimal);
                    WriteLine($" [{filePath}]", ConsoleColor.DarkGray, Verbosity.Minimal);
                    continue;
                }

                DiagnosticAnalyzer[] analyzers = analyzerAssembly
                                                 .Analyzers
                                                 .SelectMany(f => f.Value)
                                                 .Distinct()
                                                 .ToArray();

                if (analyzers.Length > 0)
                {
                    Write($"  {analyzers.Length} DiagnosticAnalyzers (", Verbosity.Normal);

                    using (IEnumerator <KeyValuePair <string, ImmutableArray <DiagnosticAnalyzer> > > en = analyzerAssembly.Analyzers.OrderBy(f => f.Key).GetEnumerator())
                    {
                        if (en.MoveNext())
                        {
                            while (true)
                            {
                                Write($"{en.Current.Value.Length} {Utilities.GetShortLanguageName(en.Current.Key)}", Verbosity.Normal);

                                if (en.MoveNext())
                                {
                                    Write(", ");
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }

                    WriteLine(")", Verbosity.Normal);

                    foreach (DiagnosticAnalyzer analyzer in analyzers.OrderBy(f => f.GetType().FullName))
                    {
                        Type type = analyzer.GetType();

                        DiagnosticAnalyzerAttribute attribute = type.GetCustomAttribute <DiagnosticAnalyzerAttribute>();

                        WriteLine($"    {type.FullName}", Verbosity.Detailed);
                        WriteLine($"      Supported Languages:   {string.Join(", ", attribute.Languages.Select(f => Utilities.GetShortLanguageName(f)).OrderBy(f => f))}", ConsoleColor.DarkGray, Verbosity.Detailed);
                        WriteLine($"      Supported Diagnostics: {string.Join(", ", analyzer.SupportedDiagnostics.Select(f => f.Id).OrderBy(f => f))}", ConsoleColor.DarkGray, Verbosity.Detailed);
                    }
                }

                CodeFixProvider[] fixers = analyzerAssembly
                                           .Fixers
                                           .SelectMany(f => f.Value)
                                           .Distinct()
                                           .ToArray();

                if (fixers.Length > 0)
                {
                    Write($"  {fixers.Length} CodeFixProviders (", Verbosity.Normal);

                    using (IEnumerator <KeyValuePair <string, ImmutableArray <CodeFixProvider> > > en = analyzerAssembly.Fixers.OrderBy(f => f.Key).GetEnumerator())
                    {
                        if (en.MoveNext())
                        {
                            while (true)
                            {
                                Write($"{en.Current.Value.Length} {Utilities.GetShortLanguageName(en.Current.Key)}", Verbosity.Normal);

                                if (en.MoveNext())
                                {
                                    Write(", ");
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }

                    WriteLine(")", Verbosity.Normal);

                    foreach (CodeFixProvider fixer in fixers.OrderBy(f => f.GetType().FullName))
                    {
                        Type type = fixer.GetType();

                        ExportCodeFixProviderAttribute attribute = type.GetCustomAttribute <ExportCodeFixProviderAttribute>();

                        WriteLine($"    {type.FullName}", Verbosity.Detailed);
                        WriteLine($"      Supported Languages: {string.Join(", ", attribute.Languages.Select(f => Utilities.GetShortLanguageName(f)).OrderBy(f => f))}", ConsoleColor.DarkGray, Verbosity.Detailed);
                        WriteLine($"      Fixable Diagnostics: {string.Join(", ", fixer.FixableDiagnosticIds.OrderBy(f => f))}", ConsoleColor.DarkGray, Verbosity.Detailed);

                        Write("      FixAllProvider:      ", ConsoleColor.DarkGray, Verbosity.Detailed);

                        FixAllProvider fixAllProvider = fixer.GetFixAllProvider();

                        if (fixAllProvider != null)
                        {
                            WriteLine($"{fixAllProvider.GetType().FullName} ({string.Join(", ", fixAllProvider.GetSupportedFixAllScopes().Select(f => f.ToString()).OrderBy(f => f))})", ConsoleColor.DarkGray, Verbosity.Detailed);
                        }
                        else
                        {
                            WriteLine("-", ConsoleColor.DarkGray, Verbosity.Detailed);
                        }
                    }
                }
            }

            WriteLine(Verbosity.Minimal);
            WriteLine($"{assemblies.Count} analyzer {((assemblies.Count == 1) ? "assembly" : "assemblies")} found", ConsoleColor.Green, Verbosity.Minimal);
            WriteLine(Verbosity.Minimal);

            return(CommandResult.Success);
        }