private static bool DiagnosticMatchesLanguage(Type type, string language) { DiagnosticAnalyzerAttribute analyzerAttribute = (DiagnosticAnalyzerAttribute)Attribute.GetCustomAttribute(type, typeof(DiagnosticAnalyzerAttribute)); return(analyzerAttribute.Languages.Any(l => String.Equals(l, language, StringComparison.OrdinalIgnoreCase))); }
/// <summary> /// Return a value indicating whether the specified analyzer supports the specified language. /// </summary> /// <param name="analyzer"> /// The analyzer to be examined. /// </param> /// <param name="language"> /// The name of the language. /// </param> /// <returns> /// <code>true</code> if <paramref name="analyzer"/> supports <paramref name="language"/>; /// otherwise <code>false</code>. /// </returns> internal static bool SupportsLanguage(this DiagnosticAnalyzer analyzer, string language) { DiagnosticAnalyzerAttribute attribute = analyzer.GetType().GetCustomAttribute <DiagnosticAnalyzerAttribute>(inherit: true); // Every analyzer should have this attribute, but behave reasonably if it does not. if (attribute == null) { return(false); } return(attribute.Languages.Contains(language)); }
private static bool DiagnosticMatchesLanguage(Type type, string language) { DiagnosticAnalyzerAttribute analyzerAttribute = (DiagnosticAnalyzerAttribute)Attribute.GetCustomAttribute(type, typeof(DiagnosticAnalyzerAttribute)); // Analyzer must have a [DiagnosticAnalyzerAttribute] to be recognized as a valid analyzer if (analyzerAttribute == null) { return(false); } return(analyzerAttribute.Languages.Any(l => String.Equals(l, language, StringComparison.OrdinalIgnoreCase))); }
private static void WriteDiagnosticAnalyzers(IEnumerable <DiagnosticAnalyzer> analyzers) { WriteLine(" DiagnosticAnalyzers:", Verbosity.Detailed); foreach (DiagnosticAnalyzer analyzer in analyzers.OrderBy(f => f.GetType(), TypeComparer.NamespaceThenName)) { Type type = analyzer.GetType(); DiagnosticAnalyzerAttribute attribute = type.GetCustomAttribute <DiagnosticAnalyzerAttribute>(); 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($" SupportedDiagnostics: {string.Join(", ", analyzer.SupportedDiagnostics.Select(f => f.Id).Distinct().OrderBy(f => f))}", ConsoleColors.DarkGray, Verbosity.Diagnostic); } } }
public static AnalyzerAssembly Load( Assembly analyzerAssembly, bool loadAnalyzers = true, bool loadFixers = true, string language = null) { Debug.Assert(loadAnalyzers || loadFixers); Dictionary <string, ImmutableArray <DiagnosticAnalyzer> .Builder> analyzers = null; Dictionary <string, ImmutableArray <CodeFixProvider> .Builder> fixers = null; try { foreach (TypeInfo typeInfo in analyzerAssembly.DefinedTypes) { if (loadAnalyzers && !typeInfo.IsAbstract && typeInfo.IsSubclassOf(typeof(DiagnosticAnalyzer))) { DiagnosticAnalyzerAttribute attribute = typeInfo.GetCustomAttribute <DiagnosticAnalyzerAttribute>(); if (attribute != null) { DiagnosticAnalyzer analyzer = CreateInstanceAndCatchIfThrows <DiagnosticAnalyzer>(typeInfo); if (analyzer != null) { if (analyzers == null) { analyzers = new Dictionary <string, ImmutableArray <DiagnosticAnalyzer> .Builder>(); } foreach (string language2 in attribute.Languages) { if (language == null || language == language2) { if (!analyzers.TryGetValue(language2, out ImmutableArray <DiagnosticAnalyzer> .Builder value)) { analyzers[language2] = ImmutableArray.CreateBuilder <DiagnosticAnalyzer>(); } analyzers[language2].Add(analyzer); } } } } } else if (loadFixers && !typeInfo.IsAbstract && typeInfo.IsSubclassOf(typeof(CodeFixProvider))) { ExportCodeFixProviderAttribute attribute = typeInfo.GetCustomAttribute <ExportCodeFixProviderAttribute>(); if (attribute != null) { CodeFixProvider fixer = CreateInstanceAndCatchIfThrows <CodeFixProvider>(typeInfo); if (fixer != null) { if (fixers == null) { fixers = new Dictionary <string, ImmutableArray <CodeFixProvider> .Builder>(); } foreach (string language2 in attribute.Languages) { if (language == null || language == language2) { if (!fixers.TryGetValue(language2, out ImmutableArray <CodeFixProvider> .Builder value)) { fixers[language2] = ImmutableArray.CreateBuilder <CodeFixProvider>(); } fixers[language2].Add(fixer); } } } } } } } catch (ReflectionTypeLoadException) { WriteLine($"Cannot load types from assembly '{analyzerAssembly.FullName}'", ConsoleColors.DarkGray, Verbosity.Diagnostic); } return(new AnalyzerAssembly( analyzerAssembly, analyzers?.ToImmutableDictionary(f => f.Key, f => f.Value.ToImmutableArray()) ?? ImmutableDictionary <string, ImmutableArray <DiagnosticAnalyzer> > .Empty, fixers?.ToImmutableDictionary(f => f.Key, f => f.Value.ToImmutableArray()) ?? ImmutableDictionary <string, ImmutableArray <CodeFixProvider> > .Empty)); }
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 AnalyzerFile Create(Assembly analyzerAssembly) { Dictionary <string, ImmutableArray <DiagnosticAnalyzer> .Builder> analyzers = null; Dictionary <string, ImmutableArray <CodeFixProvider> .Builder> fixers = null; try { foreach (TypeInfo typeInfo in analyzerAssembly.DefinedTypes) { if (typeInfo.IsSubclassOf(typeof(DiagnosticAnalyzer))) { DiagnosticAnalyzerAttribute attribute = typeInfo.GetCustomAttribute <DiagnosticAnalyzerAttribute>(); if (attribute != null) { var analyzer = (DiagnosticAnalyzer)Activator.CreateInstance(typeInfo.AsType()); if (analyzers == null) { analyzers = new Dictionary <string, ImmutableArray <DiagnosticAnalyzer> .Builder>(); } foreach (string language in attribute.Languages) { if (!analyzers.TryGetValue(language, out ImmutableArray <DiagnosticAnalyzer> .Builder value)) { analyzers[language] = ImmutableArray.CreateBuilder <DiagnosticAnalyzer>(); } analyzers[language].Add(analyzer); } } } else if (typeInfo.IsSubclassOf(typeof(CodeFixProvider))) { ExportCodeFixProviderAttribute attribute = typeInfo.GetCustomAttribute <ExportCodeFixProviderAttribute>(); if (attribute != null) { var fixer = (CodeFixProvider)Activator.CreateInstance(typeInfo.AsType()); if (fixers == null) { fixers = new Dictionary <string, ImmutableArray <CodeFixProvider> .Builder>(); } foreach (string language in attribute.Languages) { if (!fixers.TryGetValue(language, out ImmutableArray <CodeFixProvider> .Builder value)) { fixers[language] = ImmutableArray.CreateBuilder <CodeFixProvider>(); } fixers[language].Add(fixer); } } } } } catch (ReflectionTypeLoadException) { #if DEBUG WriteLine($"Cannot load types from assembly '{analyzerAssembly.Location}'", ConsoleColor.Yellow); #endif } return(new AnalyzerFile( analyzerAssembly, analyzers?.ToImmutableDictionary(f => f.Key, f => f.Value.ToImmutableArray()) ?? ImmutableDictionary <string, ImmutableArray <DiagnosticAnalyzer> > .Empty, fixers?.ToImmutableDictionary(f => f.Key, f => f.Value.ToImmutableArray()) ?? ImmutableDictionary <string, ImmutableArray <CodeFixProvider> > .Empty)); }
public static AnalyzerAssembly Load( Assembly analyzerAssembly, bool loadAnalyzers = true, bool loadFixers = true, string language = null) { Debug.Assert(loadAnalyzers || loadFixers); Dictionary <string, ImmutableArray <DiagnosticAnalyzer> .Builder> analyzers = null; Dictionary <string, ImmutableArray <CodeFixProvider> .Builder> fixers = null; TypeInfo[] types = null; try { types = analyzerAssembly.DefinedTypes.ToArray(); } catch (ReflectionTypeLoadException ex) { types = ex.Types.OfType <TypeInfo>().ToArray(); int count = ex.Types.Count(f => f == null); string message = $"Cannot load {count} type{((count == 1) ? "" : "s")} from assembly '{analyzerAssembly.FullName}'"; if (!string.IsNullOrEmpty(analyzerAssembly.Location)) { message += $" at '{analyzerAssembly.Location}'"; } WriteLine(message, ConsoleColors.DarkGray, Verbosity.Diagnostic); foreach (Exception loadeException in ex.LoaderExceptions) { WriteLine($" {loadeException.Message}", ConsoleColors.DarkGray, Verbosity.Diagnostic); } } foreach (TypeInfo typeInfo in types) { if (loadAnalyzers && !typeInfo.IsAbstract && typeInfo.IsSubclassOf(typeof(DiagnosticAnalyzer))) { DiagnosticAnalyzerAttribute attribute = typeInfo.GetCustomAttribute <DiagnosticAnalyzerAttribute>(); if (attribute != null) { DiagnosticAnalyzer analyzer = CreateInstanceAndCatchIfThrows <DiagnosticAnalyzer>(typeInfo); if (analyzer != null) { if (analyzers == null) { analyzers = new Dictionary <string, ImmutableArray <DiagnosticAnalyzer> .Builder>(); } foreach (string language2 in attribute.Languages) { if (language == null || language == language2) { if (!analyzers.TryGetValue(language2, out ImmutableArray <DiagnosticAnalyzer> .Builder value)) { analyzers[language2] = ImmutableArray.CreateBuilder <DiagnosticAnalyzer>(); } analyzers[language2].Add(analyzer); } } } } } else if (loadFixers && !typeInfo.IsAbstract && typeInfo.IsSubclassOf(typeof(CodeFixProvider))) { ExportCodeFixProviderAttribute attribute = typeInfo.GetCustomAttribute <ExportCodeFixProviderAttribute>(); if (attribute != null) { CodeFixProvider fixer = CreateInstanceAndCatchIfThrows <CodeFixProvider>(typeInfo); if (fixer != null) { if (fixers == null) { fixers = new Dictionary <string, ImmutableArray <CodeFixProvider> .Builder>(); } foreach (string language2 in attribute.Languages) { if (language == null || language == language2) { if (!fixers.TryGetValue(language2, out ImmutableArray <CodeFixProvider> .Builder value)) { fixers[language2] = ImmutableArray.CreateBuilder <CodeFixProvider>(); } fixers[language2].Add(fixer); } } } } } } return(new AnalyzerAssembly( analyzerAssembly, analyzers?.ToImmutableDictionary(f => f.Key, f => f.Value.ToImmutableArray()) ?? ImmutableDictionary <string, ImmutableArray <DiagnosticAnalyzer> > .Empty, fixers?.ToImmutableDictionary(f => f.Key, f => f.Value.ToImmutableArray()) ?? ImmutableDictionary <string, ImmutableArray <CodeFixProvider> > .Empty)); }