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); }
public static void WriteXml( XmlWriter writer, IEnumerable <AnalyzerAssembly> analyzerAssemblies, string name, Version toolsVersion, string description = null, IFormatProvider formatProvider = null) { writer.WriteStartDocument(); writer.WriteStartElement("RuleSet"); writer.WriteAttributeString("Name", name); writer.WriteAttributeString("ToolsVersion", toolsVersion.ToString(2)); if (!string.IsNullOrEmpty(description)) { writer.WriteAttributeString("Description", description); } foreach (AnalyzerAssembly analyzerAssembly in analyzerAssemblies.OrderBy(f => f.Name)) { using (IEnumerator <DiagnosticDescriptor> en = DiagnosticMap.Create(analyzerAssembly).SupportedDiagnostics .Where(f => !f.CustomTags.Contains(WellKnownDiagnosticTags.NotConfigurable) && !f.IsAnalyzerExceptionDescriptor()) .OrderBy(f => f.Id) .GetEnumerator()) { if (en.MoveNext()) { writer.WriteStartElement("Rules"); writer.WriteAttributeString("AnalyzerId", analyzerAssembly.Name); writer.WriteAttributeString("RuleNamespace", analyzerAssembly.Name); do { writer.WriteWhitespace(writer.Settings.NewLineChars); writer.WriteWhitespace(writer.Settings.IndentChars); writer.WriteWhitespace(writer.Settings.IndentChars); writer.WriteStartElement("Rule"); DiagnosticDescriptor current = en.Current; writer.WriteAttributeString("Id", current.Id); writer.WriteAttributeString("Action", GetAction(current)); writer.WriteEndElement(); string title = current.Title.ToString(formatProvider); if (!string.IsNullOrEmpty(title)) { writer.WriteWhitespace(" "); writer.WriteComment($" {title} "); } }while (en.MoveNext()); writer.WriteWhitespace(writer.Settings.NewLineChars); writer.WriteWhitespace(writer.Settings.IndentChars); writer.WriteEndElement(); } } }
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 WriteDiagnostics( DiagnosticMap map, bool allProperties = true, bool useAssemblyQualifiedName = false) { WriteLine(" Diagnostics:", Verbosity.Detailed); foreach (KeyValuePair <string, DiagnosticDescriptor> kvp in map.DiagnosticsById.OrderBy(f => f.Key)) { WriteDiagnostic(kvp.Key, kvp.Value); } void WriteDiagnostic(string diagnosticId, DiagnosticDescriptor descriptor) { if (descriptor == null) { WriteLine($" {diagnosticId}", Verbosity.Detailed); } else { string title = descriptor.Title?.ToString(); string messageFormat = descriptor.MessageFormat?.ToString(); if (string.IsNullOrEmpty(title)) { title = messageFormat; } WriteLine($" {diagnosticId} {title}", Verbosity.Detailed); if (allProperties && ShouldWrite(Verbosity.Diagnostic)) { if (title != messageFormat) { WriteLine($" MessageFormat: {messageFormat}", ConsoleColors.DarkGray, Verbosity.Diagnostic); } WriteLine($" Category: {descriptor.Category}", ConsoleColors.DarkGray, Verbosity.Diagnostic); WriteLine($" DefaultSeverity: {descriptor.DefaultSeverity}", ConsoleColors.DarkGray, Verbosity.Diagnostic); WriteLine($" IsEnabledByDefault: {descriptor.IsEnabledByDefault}", ConsoleColors.DarkGray, Verbosity.Diagnostic); string description = descriptor.Description?.ToString(); if (!string.IsNullOrEmpty(description)) { WriteLine($" Description: {description}", ConsoleColors.DarkGray, Verbosity.Diagnostic); } if (!string.IsNullOrEmpty(descriptor.HelpLinkUri)) { WriteLine($" HelpLinkUri: {descriptor.HelpLinkUri}", ConsoleColors.DarkGray, Verbosity.Diagnostic); } string customTags = string.Join(", ", descriptor.CustomTags.OrderBy(f => f)); if (!string.IsNullOrEmpty(customTags)) { WriteLine($" CustomTags: {customTags}", ConsoleColors.DarkGray, Verbosity.Diagnostic); } } } if (ShouldWrite(Verbosity.Diagnostic)) { if (map.AnalyzersById.TryGetValue(diagnosticId, out IEnumerable <DiagnosticAnalyzer> analyzers2)) { Write(" DiagnosticAnalyzers: ", ConsoleColors.DarkGray, Verbosity.Diagnostic); WriteTypes(analyzers2.Select(f => f.GetType())); } if (map.FixersById.TryGetValue(diagnosticId, out IEnumerable <CodeFixProvider> fixers2)) { Write(" CodeFixProviders: ", ConsoleColors.DarkGray, Verbosity.Diagnostic); WriteTypes(fixers2.Select(f => f.GetType())); } } } void WriteTypes(IEnumerable <Type> types) { using (IEnumerator <Type> en = types.OrderBy(f => f, TypeComparer.NamespaceThenName).GetEnumerator()) { if (en.MoveNext()) { while (true) { string name = (useAssemblyQualifiedName) ? en.Current.AssemblyQualifiedName : en.Current.FullName; WriteLine(name, ConsoleColors.DarkGray, Verbosity.Diagnostic); if (en.MoveNext()) { Write(" ", ConsoleColors.DarkGray, Verbosity.Diagnostic); } else { break; } } } } } }
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); }
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); } }