private static bool CheckTelemetry(DiagnosticAnalyzer analyzer, IDiagnosticAnalyzerService serviceOpt) { if (analyzer.IsCompilerAnalyzer()) { return(true); } if (analyzer is IBuiltInAnalyzer) { // if it is builtin analyzer, telemetry is always allowed return(true); } ImmutableArray <DiagnosticDescriptor> diagDescriptors; try { // SupportedDiagnostics is potentially user code and can throw an exception. diagDescriptors = serviceOpt != null?serviceOpt.GetDiagnosticDescriptors(analyzer) : analyzer.SupportedDiagnostics; } catch (Exception) { return(false); } if (diagDescriptors == null) { return(false); } // find if the first diagnostic in this analyzer allows telemetry DiagnosticDescriptor diagnostic = diagDescriptors.Length > 0 ? diagDescriptors[0] : null; return(diagnostic == null ? false : diagnostic.CustomTags.Any(t => t == WellKnownDiagnosticTags.Telemetry)); }
// *DO NOT DELETE* // This is used by Ruleset Editor from ManagedSourceCodeAnalysis.dll. public IReadOnlyDictionary <string, IEnumerable <DiagnosticDescriptor> > GetAllDiagnosticDescriptors(IVsHierarchy hierarchyOpt) { if (hierarchyOpt == null) { return(Transform(_diagnosticService.GetDiagnosticDescriptors(projectOpt: null))); } // Analyzers are only supported for C# and VB currently. var projectsWithHierarchy = _workspace.ProjectTracker.ImmutableProjects .Where(p => p.Language == LanguageNames.CSharp || p.Language == LanguageNames.VisualBasic) .Where(p => p.Hierarchy == hierarchyOpt) .Select(p => _workspace.CurrentSolution.GetProject(p.Id)); if (projectsWithHierarchy.Count() <= 1) { return(Transform(_diagnosticService.GetDiagnosticDescriptors(projectsWithHierarchy.FirstOrDefault()))); } else { // Multiple workspace projects map to the same hierarchy, return a union of descriptors for all projects. // For example, this can happen for web projects where we create on the fly projects for aspx files. var descriptorsMap = ImmutableDictionary.CreateBuilder <string, IEnumerable <DiagnosticDescriptor> >(); foreach (var project in projectsWithHierarchy) { var newDescriptorTuples = _diagnosticService.GetDiagnosticDescriptors(project); foreach (var kvp in newDescriptorTuples) { IEnumerable <DiagnosticDescriptor> existingDescriptors; if (descriptorsMap.TryGetValue(kvp.Key, out existingDescriptors)) { descriptorsMap[kvp.Key] = existingDescriptors.Concat(kvp.Value).Distinct(); } else { descriptorsMap[kvp.Key] = kvp.Value; } } } return(descriptorsMap.ToImmutable()); } }
private IEnumerable <BaseDiagnosticItem> GetDiagnosticItems(string language, CompilationOptions options, ImmutableDictionary <string, ReportDiagnostic> analyzerConfigSpecificDiagnosticOptions) { // Within an analyzer assembly, an individual analyzer may report multiple different diagnostics // with the same ID. Or, multiple analyzers may report diagnostics with the same ID. Or a // combination of the two may occur. // We only want to show one node in Solution Explorer for a given ID. So we pick one, but we need // to be consistent in which one we pick. Diagnostics with the same ID may have different // descriptions or messages, and it would be strange if the node's name changed from one run of // VS to another. So we group the diagnostics by ID, sort them within a group, and take the first // one. return(AnalyzerReference.GetAnalyzers(language) .SelectMany(a => _diagnosticAnalyzerService.GetDiagnosticDescriptors(a)) .GroupBy(d => d.Id) .OrderBy(g => g.Key, StringComparer.CurrentCulture) .Select(g => { var selectedDiagnostic = g.OrderBy(d => d, s_comparer).First(); var effectiveSeverity = selectedDiagnostic.GetEffectiveSeverity(options, analyzerConfigSpecificDiagnosticOptions); return CreateItem(selectedDiagnostic, effectiveSeverity); })); }
private IEnumerable <DiagnosticItem> GetDiagnosticItems(string language) { // Within an analyzer assembly, an individual analyzer may report multiple different diagnostics // with the same ID. Or, multiple analyzers may report diagnostics with the same ID. Or a // combination of the two may occur. // We only want to show one node in Solution Explorer for a given ID. So we pick one, but we need // to be consistent in which one we pick. Diagnostics with the same ID may have different // descriptions or messages, and it would be strange if the node's name changed from one run of // VS to another. So we group the diagnostics by ID, sort them within a group, and take the first // one. return(_item.AnalyzerReference.GetAnalyzers(language) .SelectMany(a => _diagnosticAnalyzerService.GetDiagnosticDescriptors(a)) .GroupBy(d => d.Id) .OrderBy(g => g.Key, StringComparer.CurrentCulture) .Select(g => { var selectedDiagnostic = g.OrderBy(d => d, s_comparer).First(); var effectiveSeverity = GetEffectiveSeverity(selectedDiagnostic.Id, _specificDiagnosticOptions, _generalDiagnosticOption, selectedDiagnostic.DefaultSeverity, selectedDiagnostic.IsEnabledByDefault); return new DiagnosticItem(_item, selectedDiagnostic, effectiveSeverity, _commandHandler.DiagnosticContextMenuController); })); }