/// <summary> /// Gets the default diagnostic to use during markup processing. By default, the <em>single</em> diagnostic of /// the first analyzer is used, and no default diagonostic is available if multiple diagnostics are provided by /// the analyzer. If <see cref="MarkupOptions.UseFirstDescriptor"/> is used, the first available diagnostic /// is used. /// </summary> /// <param name="analyzers">The analyzers to consider.</param> /// <returns>The default diagnostic to use during markup processing.</returns> protected internal virtual DiagnosticDescriptor GetDefaultDiagnostic(DiagnosticAnalyzer[] analyzers) { if (analyzers.Length == 0) { return(null); } if (MarkupOptions.HasFlag(MarkupOptions.UseFirstDescriptor)) { foreach (var analyzer in analyzers) { if (analyzer.SupportedDiagnostics.Any()) { return(analyzer.SupportedDiagnostics[0]); } } return(null); } else if (analyzers[0].SupportedDiagnostics.Length == 1) { return(analyzers[0].SupportedDiagnostics[0]); } else { return(null); } }
/// <summary> /// Processes the markup syntax for this <see cref="SolutionState"/> according to the current /// <see cref="MarkupHandling"/>, and returns a new <see cref="SolutionState"/> with the /// <see cref="ProjectState.Sources"/>, <see cref="ProjectState.GeneratedSources"/>, /// <see cref="ProjectState.AdditionalFiles"/>, <see cref="ProjectState.AnalyzerConfigFiles"/>, and /// <see cref="ExpectedDiagnostics"/> updated accordingly. /// </summary> /// <param name="markupOptions">Additional options to apply during markup processing.</param> /// <param name="defaultDiagnostic">The diagnostic descriptor to use for markup spans without an explicit name, /// or <see langword="null"/> if no such default exists.</param> /// <param name="supportedDiagnostics">The diagnostics supported by analyzers used by the test.</param> /// <param name="fixableDiagnostics">The set of diagnostic IDs to treat as fixable. This value is only used when /// <see cref="MarkupHandling"/> is <see cref="MarkupMode.IgnoreFixable"/>.</param> /// <param name="defaultPath">The default file path for diagnostics reported in source code.</param> /// <returns>A new <see cref="SolutionState"/> with all markup processing completed according to the current /// <see cref="MarkupHandling"/>. The <see cref="MarkupHandling"/> of the returned instance is /// <see cref="MarkupMode.None"/>.</returns> /// <exception cref="InvalidOperationException">If <see cref="InheritanceMode"/> is not /// <see cref="StateInheritanceMode.Explicit"/>.</exception> public SolutionState WithProcessedMarkup(MarkupOptions markupOptions, DiagnosticDescriptor?defaultDiagnostic, ImmutableArray <DiagnosticDescriptor> supportedDiagnostics, ImmutableArray <string> fixableDiagnostics, string defaultPath) { if (InheritanceMode != StateInheritanceMode.Explicit) { throw new InvalidOperationException("Inheritance processing must complete before markup processing."); } var markupLocations = ImmutableDictionary <string, FileLinePositionSpan> .Empty; (var expected, var testSources) = ProcessMarkupSources(Sources, ExpectedDiagnostics, ref markupLocations, markupOptions, defaultDiagnostic, supportedDiagnostics, fixableDiagnostics, defaultPath); var(additionalExpected2, testGeneratedSources) = ProcessMarkupSources(GeneratedSources, expected, ref markupLocations, markupOptions, defaultDiagnostic, supportedDiagnostics, fixableDiagnostics, defaultPath); var(additionalExpected1, additionalFiles) = ProcessMarkupSources(AdditionalFiles.Concat(AdditionalFilesFactories.SelectMany(factory => factory())), additionalExpected2, ref markupLocations, markupOptions, defaultDiagnostic, supportedDiagnostics, fixableDiagnostics, defaultPath); var(additionalExpected, analyzerConfigFiles) = ProcessMarkupSources(AnalyzerConfigFiles, additionalExpected1, ref markupLocations, markupOptions, defaultDiagnostic, supportedDiagnostics, fixableDiagnostics, defaultPath); var result = new SolutionState(Name, Language, DefaultPrefix, DefaultExtension); result.MarkupHandling = MarkupMode.None; result.InheritanceMode = StateInheritanceMode.Explicit; result.ReferenceAssemblies = ReferenceAssemblies; result.OutputKind = OutputKind; result.DocumentationMode = DocumentationMode; result.Sources.AddRange(testSources); result.GeneratedSources.AddRange(testGeneratedSources); result.AdditionalFiles.AddRange(additionalFiles); result.AnalyzerConfigFiles.AddRange(analyzerConfigFiles); foreach (var(projectName, projectState) in AdditionalProjects) { var(correctedIntermediateDiagnostics, additionalProjectSources) = ProcessMarkupSources(projectState.Sources, additionalExpected, ref markupLocations, markupOptions, defaultDiagnostic, supportedDiagnostics, fixableDiagnostics, defaultPath); var(correctedDiagnostics2, additionalProjectGeneratedSources) = ProcessMarkupSources(projectState.GeneratedSources, correctedIntermediateDiagnostics, ref markupLocations, markupOptions, defaultDiagnostic, supportedDiagnostics, fixableDiagnostics, defaultPath); var(correctedDiagnostics1, additionalProjectAdditionalFiles) = ProcessMarkupSources(projectState.AdditionalFiles.Concat(projectState.AdditionalFilesFactories.SelectMany(factory => factory())), correctedDiagnostics2, ref markupLocations, markupOptions, defaultDiagnostic, supportedDiagnostics, fixableDiagnostics, defaultPath); var(correctedDiagnostics, additionalProjectAnalyzerConfigFiles) = ProcessMarkupSources(projectState.AnalyzerConfigFiles, correctedDiagnostics1, ref markupLocations, markupOptions, defaultDiagnostic, supportedDiagnostics, fixableDiagnostics, defaultPath); var processedProjectState = new ProjectState(projectState); processedProjectState.Sources.Clear(); processedProjectState.Sources.AddRange(additionalProjectSources); processedProjectState.GeneratedSources.Clear(); processedProjectState.GeneratedSources.AddRange(additionalProjectGeneratedSources); processedProjectState.AdditionalFiles.Clear(); processedProjectState.AdditionalFilesFactories.Clear(); processedProjectState.AdditionalFiles.AddRange(additionalProjectAdditionalFiles); processedProjectState.AnalyzerConfigFiles.Clear(); processedProjectState.AnalyzerConfigFiles.AddRange(additionalProjectAnalyzerConfigFiles); result.AdditionalProjects.Add(projectName, processedProjectState); additionalExpected = correctedDiagnostics; } for (var i = 0; i < additionalExpected.Length; i++) { additionalExpected[i] = additionalExpected[i].WithAppliedMarkupLocations(markupLocations); } result.AdditionalProjectReferences.AddRange(AdditionalProjectReferences); result.AdditionalReferences.AddRange(AdditionalReferences); result.ExpectedDiagnostics.AddRange(additionalExpected); return(result); }