public CommandResult Execute(AnalyzeAssemblyCommandLineOptions options) { var assemblies = new HashSet <Assembly>(); AnalyzerAssemblyInfo[] analyzerAssemblies = options.GetPaths() .SelectMany(path => AnalyzerAssemblyLoader.LoadFrom( path: path, loadAnalyzers: !options.NoAnalyzers, loadFixers: !options.NoFixers, language: Language)) .OrderBy(f => f.AnalyzerAssembly.Assembly.GetName().Name) .ThenBy(f => f.FilePath) .ToArray(); for (int i = 0; i < analyzerAssemblies.Length; i++) { AnalyzerAssembly analyzerAssembly = analyzerAssemblies[i].AnalyzerAssembly; if (assemblies.Add(analyzerAssembly.Assembly)) { WriteLine(analyzerAssembly.FullName, ConsoleColor.Cyan, Verbosity.Minimal); if (ShouldWrite(Verbosity.Normal)) { WriteAnalyzerAssembly(analyzerAssemblies[i], DiagnosticMap.Create(analyzerAssembly)); if (i < analyzerAssemblies.Length - 1) { WriteLine(Verbosity.Normal); } } } else { Write(analyzerAssembly.FullName, ConsoleColor.DarkGray, Verbosity.Minimal); WriteLine($" [{analyzerAssemblies[i].FilePath}]", ConsoleColor.DarkGray, Verbosity.Minimal); } } if (ShouldWrite(Verbosity.Detailed) && analyzerAssemblies.Length > 1) { DiagnosticMap map = DiagnosticMap.Create(analyzerAssemblies.Select(f => f.AnalyzerAssembly)); WriteLine(Verbosity.Detailed); WriteDiagnostics(map, allProperties: true, useAssemblyQualifiedName: true); } WriteLine(Verbosity.Minimal); WriteLine($"{assemblies.Count} analyzer {((assemblies.Count == 1) ? "assembly" : "assemblies")} found", ConsoleColor.Green, Verbosity.Minimal); WriteLine(Verbosity.Minimal); if (options.Output != null && analyzerAssemblies.Length > 0) { AnalyzerAssemblyXmlSerializer.Serialize(analyzerAssemblies, options.Output); } return(CommandResult.Success); }
private static (int maxLength, int maxDigitLength) CalculateMaxLength(AnalyzerAssembly analyzerAssembly, DiagnosticMap map) { int maxLength = 22; int maxDigitLength = 0; if (analyzerAssembly.HasAnalyzers) { maxLength = Math.Max(maxLength, analyzerAssembly.AnalyzersByLanguage.Max(f => GetShortLanguageName(f.Key).Length + 3)); maxLength = Math.Max(maxLength, map.SupportedDiagnosticsByPrefix.Max(f => f.Key.Length + 3)); maxDigitLength = Math.Max(maxDigitLength, map.Analyzers.Length.ToString().Length); maxDigitLength = Math.Max(maxDigitLength, map.SupportedDiagnostics.Length.ToString().Length); } if (analyzerAssembly.HasFixers) { maxLength = Math.Max(maxLength, analyzerAssembly.FixersByLanguage.Max(f => GetShortLanguageName(f.Key).Length + 3)); maxLength = Math.Max(maxLength, map.FixableDiagnosticIdsByPrefix.Max(f => f.Key.Length + 3)); maxDigitLength = Math.Max(maxDigitLength, map.Fixers.Length.ToString().Length); maxDigitLength = Math.Max(maxDigitLength, map.FixableDiagnosticIds.Length.ToString().Length); } return(maxLength, maxDigitLength); }
public static AnalyzerAssembly LoadFile( string filePath, bool loadAnalyzers = true, bool loadFixers = true, string language = null) { Assembly assembly = Assembly.LoadFrom(filePath); return(AnalyzerAssembly.Load(assembly, loadAnalyzers: loadAnalyzers, loadFixers: loadFixers, language: language)); }
public static IEnumerable <AnalyzerAssemblyInfo> LoadFrom( string path, bool loadAnalyzers = true, bool loadFixers = true, string language = null) { if (File.Exists(path)) { AnalyzerAssembly analyzerAssembly = Load(path); if (analyzerAssembly?.IsEmpty == false) { yield return(new AnalyzerAssemblyInfo(analyzerAssembly, path)); } } else if (Directory.Exists(path)) { using (IEnumerator <string> en = Directory.EnumerateFiles(path, "*.dll", SearchOption.AllDirectories).GetEnumerator()) { while (true) { string filePath = null; AnalyzerAssembly analyzerAssembly = null; try { if (en.MoveNext()) { filePath = en.Current; analyzerAssembly = Load(filePath); } else { break; } } catch (Exception ex) when(ex is IOException || ex is SecurityException || ex is UnauthorizedAccessException) { WriteLine(ex.Message, ConsoleColor.DarkGray, Verbosity.Diagnostic); continue; } if (analyzerAssembly?.IsEmpty == false) { yield return(new AnalyzerAssemblyInfo(analyzerAssembly, filePath)); } } } } else { WriteLine($"File or directory not found: '{path}'", ConsoleColor.DarkGray, Verbosity.Normal); } AnalyzerAssembly Load(string filePath) { try { return(LoadFile(filePath, loadAnalyzers, loadFixers, language)); } catch (Exception ex) when(ex is FileLoadException || ex is BadImageFormatException || ex is SecurityException) { WriteLine($"Cannot load assembly '{filePath}'", ConsoleColor.DarkGray, Verbosity.Diagnostic); return(null); } } }
public CommandStatus Execute(AnalyzeAssemblyCommandLineOptions options) { var assemblies = new HashSet <Assembly>(); AnalyzerAssemblyInfo[] analyzerAssemblies = options.GetPaths() .SelectMany(path => AnalyzerAssemblyLoader.LoadFrom( path: path, searchPattern: options.FileNamePattern ?? AnalyzerAssemblyLoader.DefaultSearchPattern, loadAnalyzers: !options.NoAnalyzers, loadFixers: !options.NoFixers, language: Language)) .OrderBy(f => f.AnalyzerAssembly.Assembly.GetName().Name) .ThenBy(f => f.FilePath) .ToArray(); for (int i = 0; i < analyzerAssemblies.Length; i++) { AnalyzerAssembly analyzerAssembly = analyzerAssemblies[i].AnalyzerAssembly; if (assemblies.Add(analyzerAssembly.Assembly)) { WriteLine(analyzerAssembly.FullName, ConsoleColors.Cyan, Verbosity.Minimal); if (ShouldWrite(Verbosity.Normal)) { WriteAnalyzerAssembly(analyzerAssemblies[i], DiagnosticMap.Create(analyzerAssembly)); if (i < analyzerAssemblies.Length - 1) { WriteLine(Verbosity.Normal); } } } else { Write(analyzerAssembly.FullName, ConsoleColors.DarkGray, Verbosity.Minimal); WriteLine($" [{analyzerAssemblies[i].FilePath}]", ConsoleColors.DarkGray, Verbosity.Minimal); } } if (ShouldWrite(Verbosity.Detailed) && analyzerAssemblies.Length > 1) { DiagnosticMap map = DiagnosticMap.Create(analyzerAssemblies.Select(f => f.AnalyzerAssembly)); WriteLine(Verbosity.Detailed); WriteDiagnostics(map, allProperties: true, useAssemblyQualifiedName: true); } WriteLine(Verbosity.Minimal); WriteLine($"{assemblies.Count} analyzer {((assemblies.Count == 1) ? "assembly" : "assemblies")} found", ConsoleColors.Green, Verbosity.Minimal); if (analyzerAssemblies.Length > 0) { CultureInfo culture = (options.Culture != null) ? CultureInfo.GetCultureInfo(options.Culture) : null; foreach (string path in options.Output) { WriteLine($"Save '{path}'", ConsoleColors.DarkGray, Verbosity.Diagnostic); string extension = Path.GetExtension(path); if (string.Equals(extension, ".xml", StringComparison.OrdinalIgnoreCase)) { AnalyzerAssemblyXmlSerializer.Serialize(path, analyzerAssemblies, culture); } else if (string.Equals(extension, ".ruleset", StringComparison.OrdinalIgnoreCase)) { WriteLine($"Save ruleset to '{path}'", ConsoleColors.DarkGray, Verbosity.Diagnostic); using (var fileStream = new FileStream(path, FileMode.Create)) using (XmlWriter xmlWriter = XmlWriter.Create(fileStream, new XmlWriterSettings() { Indent = true, IndentChars = " ", CloseOutput = false })) { RuleSetUtility.WriteXml( writer: xmlWriter, analyzerAssemblies: analyzerAssemblies.Select(f => f.AnalyzerAssembly), name: "", toolsVersion: new Version(15, 0), description: null, formatProvider: culture); } } } } return((analyzerAssemblies.Length > 0) ? CommandStatus.Success : CommandStatus.NotSuccess); }
private static void WriteAnalyzerAssembly(AnalyzerAssemblyInfo analyzerAssemblyInfo, DiagnosticMap map) { AnalyzerAssembly analyzerAssembly = analyzerAssemblyInfo.AnalyzerAssembly; WriteLine(Verbosity.Normal); WriteLine($" Location: {analyzerAssemblyInfo.FilePath}", Verbosity.Normal); (int maxLength, int maxDigitLength) = CalculateMaxLength(analyzerAssembly, map); if (analyzerAssembly.HasAnalyzers) { WriteLine($" DiagnosticAnalyzers: {map.Analyzers.Length.ToString().PadLeft(maxDigitLength)}", Verbosity.Normal); foreach (KeyValuePair <string, ImmutableArray <DiagnosticAnalyzer> > kvp in analyzerAssembly.AnalyzersByLanguage.OrderBy(f => f.Key)) { WriteLine($" {GetShortLanguageName(kvp.Key).PadRight(maxLength - 2)}{kvp.Value.Length.ToString().PadLeft(maxDigitLength)}", Verbosity.Normal); } WriteLine($" SupportedDiagnostics: {map.SupportedDiagnostics.Length.ToString().PadLeft(maxDigitLength)}", Verbosity.Normal); foreach (KeyValuePair <string, ImmutableArray <DiagnosticDescriptor> > kvp in map.SupportedDiagnosticsByPrefix .OrderBy(f => f.Key)) { WriteLine($" {kvp.Key.PadRight(maxLength - 2)}{kvp.Value.Length.ToString().PadLeft(maxDigitLength)}", Verbosity.Normal); } } if (analyzerAssembly.HasFixers) { WriteLine($" CodeFixProviders: {map.Fixers.Length.ToString().PadLeft(maxDigitLength)}", Verbosity.Normal); foreach (KeyValuePair <string, ImmutableArray <CodeFixProvider> > kvp in analyzerAssembly.FixersByLanguage.OrderBy(f => f.Key)) { WriteLine($" {GetShortLanguageName(kvp.Key).PadRight(maxLength - 2)}{kvp.Value.Length.ToString().PadLeft(maxDigitLength)}", Verbosity.Normal); } WriteLine($" FixableDiagnosticIds: {map.FixableDiagnosticIds.Length}", Verbosity.Normal); foreach (KeyValuePair <string, ImmutableArray <string> > kvp in map.FixableDiagnosticIdsByPrefix .OrderBy(f => f.Key)) { WriteLine($" {kvp.Key.PadRight(maxLength - 2)}{kvp.Value.Length.ToString().PadLeft(maxDigitLength)}", Verbosity.Normal); } } if (ShouldWrite(Verbosity.Detailed)) { if (analyzerAssembly.HasAnalyzers) { WriteLine(Verbosity.Detailed); WriteDiagnosticAnalyzers(map.Analyzers); } if (analyzerAssembly.HasFixers) { WriteLine(Verbosity.Detailed); WriteCodeFixProviders(map.Fixers); } WriteLine(Verbosity.Detailed); WriteDiagnostics(map, allProperties: false, useAssemblyQualifiedName: false); } }
private static XElement SerializeAnalyzerAssembly(AnalyzerAssemblyInfo analyzerAssemblyInfo, IFormatProvider formatProvider) { AnalyzerAssembly analyzerAssembly = analyzerAssemblyInfo.AnalyzerAssembly; DiagnosticMap map = DiagnosticMap.Create(analyzerAssembly); return(new XElement( "AnalyzerAssembly", new XAttribute("Name", analyzerAssembly.FullName), new XElement("Location", analyzerAssemblyInfo.FilePath), new XElement("Summary", SerializeSummary()), new XElement("Analyzers", SerializeDiagnosticAnalyzers()), new XElement("Fixers", SerializeCodeFixProviders()), SerializeDiagnostics(map, allProperties: false, useAssemblyQualifiedName: false, formatProvider: formatProvider))); IEnumerable <XElement> SerializeSummary() { if (analyzerAssembly.HasAnalyzers) { yield return(new XElement("Analyzers", new XAttribute("Count", map.Analyzers.Length), new XElement("Languages", analyzerAssembly.AnalyzersByLanguage .OrderBy(f => f.Key) .Select(f => new XElement("Language", new XAttribute("Name", f.Key), new XAttribute("Count", f.Value.Length)))), new XElement("SupportedDiagnostics", new XAttribute("Count", map.SupportedDiagnostics.Length), new XElement("Prefixes", map.SupportedDiagnosticsByPrefix .OrderBy(f => f.Key) .Select(f => new XElement("Prefix", new XAttribute("Value", f.Key), new XAttribute("Count", f.Value.Length))))))); } if (analyzerAssembly.HasFixers) { yield return(new XElement("Fixers", new XAttribute("Count", map.Fixers.Length), new XElement("Languages", analyzerAssembly.FixersByLanguage .OrderBy(f => f.Key) .Select(f => new XElement("Language", new XAttribute("Name", f.Key), new XAttribute("Count", f.Value.Length)))), new XElement("FixableDiagnostics", new XAttribute("Count", map.FixableDiagnosticIds.Length), new XElement("Prefixes", map.FixableDiagnosticIdsByPrefix .OrderBy(f => f.Key) .Select(f => new XElement("Prefix", new XAttribute("Value", f.Key), new XAttribute("Count", f.Value.Length))))))); } } IEnumerable <XElement> SerializeDiagnosticAnalyzers() { foreach (DiagnosticAnalyzer analyzer in map.Analyzers.OrderBy(f => f.GetType(), TypeComparer.NamespaceThenName)) { Type type = analyzer.GetType(); DiagnosticAnalyzerAttribute attribute = type.GetCustomAttribute <DiagnosticAnalyzerAttribute>(); yield return(new XElement("Analyzer", new XAttribute("Name", type.FullName), new XElement("Languages", attribute.Languages.Select(f => new XElement("Language", f))), new XElement("SupportedDiagnostics", analyzer.SupportedDiagnostics .Select(f => f.Id) .Distinct() .OrderBy(f => f) .Select(f => new XElement("Id", f))))); } } IEnumerable <XElement> SerializeCodeFixProviders() { foreach (CodeFixProvider fixer in map.Fixers.OrderBy(f => f.GetType(), TypeComparer.NamespaceThenName)) { Type type = fixer.GetType(); ExportCodeFixProviderAttribute attribute = type.GetCustomAttribute <ExportCodeFixProviderAttribute>(); yield return(new XElement("Fixer", new XAttribute("Name", type.FullName), new XElement("Languages", attribute.Languages.Select(f => new XElement("Language", f))), new XElement("FixableDiagnostics", fixer.FixableDiagnosticIds .Distinct() .OrderBy(f => f) .Select(f => new XElement("Id", f))), CreateFixAllProviderElement(fixer))); } XElement CreateFixAllProviderElement(CodeFixProvider fixer) { FixAllProvider fixAllProvider = fixer.GetFixAllProvider(); if (fixAllProvider != null) { return(new XElement("FixAllProvider", new XAttribute("Name", fixAllProvider.GetType().FullName))); } 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); }
public static DiagnosticMap Create(AnalyzerAssembly analyzerAssembly) { return(Create(analyzerAssembly.GetAnalyzers(), analyzerAssembly.GetFixers())); }
public AnalyzerAssemblyInfo(AnalyzerAssembly analyzerAssembly, string filePath) { AnalyzerAssembly = analyzerAssembly; FilePath = filePath; }