/// <summary> /// Applies the <see cref="InheritanceMode"/> using a specified base state. /// </summary> /// <remarks> /// <para>This method evaluates <see cref="ProjectState.AdditionalFilesFactories"/>, and places the resulting /// additional files in the <see cref="ProjectState.AdditionalFiles"/> collection of the result before /// returning.</para> /// </remarks> /// <param name="baseState">The base state to inherit from, or <see langword="null"/> if the current state is /// the root state.</param> /// <param name="fixableDiagnostics">The set of diagnostic IDs to treat as fixable. Fixable diagnostics present /// in the <see cref="ExpectedDiagnostics"/> collection of the base state are only inherited for /// <see cref="StateInheritanceMode.AutoInheritAll"/>.</param> /// <returns>A new <see cref="SolutionState"/> representing the current state with inherited values applied /// where appropriate. The <see cref="InheritanceMode"/> of the result is /// <see cref="StateInheritanceMode.Explicit"/>.</returns> public SolutionState WithInheritedValuesApplied(SolutionState?baseState, ImmutableArray <string> fixableDiagnostics) { var inheritanceMode = InheritanceMode; var markupHandling = MarkupHandling; if (inheritanceMode == null || markupHandling == null) { if (baseState == null) { inheritanceMode = inheritanceMode ?? StateInheritanceMode.Explicit; markupHandling = markupHandling ?? MarkupMode.Allow; } else if (HasAnyContentChanges(willInherit: inheritanceMode != StateInheritanceMode.Explicit, this, baseState)) { inheritanceMode = inheritanceMode ?? StateInheritanceMode.AutoInherit; markupHandling = markupHandling ?? MarkupMode.IgnoreFixable; } else { inheritanceMode = inheritanceMode ?? StateInheritanceMode.AutoInheritAll; markupHandling = markupHandling ?? baseState.MarkupHandling ?? MarkupMode.Allow; } } if (inheritanceMode != StateInheritanceMode.AutoInherit && inheritanceMode != StateInheritanceMode.Explicit && inheritanceMode != StateInheritanceMode.AutoInheritAll) { throw new InvalidOperationException($"Unexpected inheritance mode: {inheritanceMode}"); } if (baseState?.AdditionalFilesFactories.Count > 0) { throw new InvalidOperationException("The base state should already have its inheritance state evaluated prior to its use as a base state."); } var result = new SolutionState(Name, Language, DefaultPrefix, DefaultExtension); result.ReferenceAssemblies = ReferenceAssemblies; result.OutputKind = OutputKind; result.DocumentationMode = DocumentationMode; if (inheritanceMode != StateInheritanceMode.Explicit && baseState != null) { result.ReferenceAssemblies ??= baseState.ReferenceAssemblies; result.OutputKind ??= baseState.OutputKind; result.DocumentationMode ??= baseState.DocumentationMode; if (Sources.Count == 0) { result.Sources.AddRange(baseState.Sources); } if (AdditionalFiles.Count == 0) { result.AdditionalFiles.AddRange(baseState.AdditionalFiles); } if (AnalyzerConfigFiles.Count == 0) { result.AnalyzerConfigFiles.AddRange(baseState.AnalyzerConfigFiles); } if (AdditionalProjects.Count == 0) { result.AdditionalProjects.AddRange(baseState.AdditionalProjects); } if (AdditionalProjectReferences.Count == 0) { result.AdditionalProjectReferences.AddRange(baseState.AdditionalProjectReferences); } if (AdditionalReferences.Count == 0) { result.AdditionalReferences.AddRange(baseState.AdditionalReferences); } if (ExpectedDiagnostics.Count == 0) { if (inheritanceMode == StateInheritanceMode.AutoInherit) { result.ExpectedDiagnostics.AddRange(baseState.ExpectedDiagnostics.Where(diagnostic => !fixableDiagnostics.Contains(diagnostic.Id))); } else { result.ExpectedDiagnostics.AddRange(baseState.ExpectedDiagnostics); } } } result.MarkupHandling = markupHandling; result.InheritanceMode = StateInheritanceMode.Explicit; result.Sources.AddRange(Sources); result.AdditionalFiles.AddRange(AdditionalFiles); result.AnalyzerConfigFiles.AddRange(AnalyzerConfigFiles); result.AdditionalProjects.AddRange(AdditionalProjects); result.AdditionalProjectReferences.AddRange(AdditionalProjectReferences); result.AdditionalReferences.AddRange(AdditionalReferences); result.ExpectedDiagnostics.AddRange(ExpectedDiagnostics); result.AdditionalFiles.AddRange(AdditionalFilesFactories.SelectMany(factory => factory())); return(result); }
/// <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.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(additionalExpected1, additionalFiles) = ProcessMarkupSources(AdditionalFiles.Concat(AdditionalFilesFactories.SelectMany(factory => factory())), expected, 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.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(correctedDiagnostics1, additionalProjectAdditionalFiles) = ProcessMarkupSources(projectState.AdditionalFiles.Concat(projectState.AdditionalFilesFactories.SelectMany(factory => factory())), correctedIntermediateDiagnostics, 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.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); }