Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for .editorconfig documents #734

Merged
merged 1 commit into from
Feb 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1137,6 +1137,12 @@ protected virtual async Task<Project> CreateProjectImplAsync(EvaluatedProjectSta
var documentId = DocumentId.CreateNewId(additionalProjectId, debugName: newFileName);
solution = solution.AddAdditionalDocument(documentId, newFileName, source, filePath: newFileName);
}

foreach (var (newFileName, source) in projectState.AnalyzerConfigFiles)
{
var documentId = DocumentId.CreateNewId(additionalProjectId, debugName: newFileName);
solution = solution.AddAnalyzerConfigDocument(documentId, newFileName, source, filePath: newFileName);
}
}

solution = solution.AddMetadataReferences(projectId, primaryProject.AdditionalReferences);
Expand All @@ -1153,6 +1159,12 @@ protected virtual async Task<Project> CreateProjectImplAsync(EvaluatedProjectSta
solution = solution.AddAdditionalDocument(documentId, newFileName, source, filePath: newFileName);
}

foreach (var (newFileName, source) in primaryProject.AnalyzerConfigFiles)
{
var documentId = DocumentId.CreateNewId(projectId, debugName: newFileName);
solution = solution.AddAnalyzerConfigDocument(documentId, newFileName, source, filePath: newFileName);
}

solution = AddProjectReferences(solution, projectId, primaryProject.AdditionalProjectReferences.Select(name => projectIdMap[name]));
foreach (var projectState in additionalProjects)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@ protected static bool CodeActionExpected(SolutionState state)
|| state.MarkupHandling != null
|| state.Sources.Any()
|| state.AdditionalFiles.Any()
|| state.AnalyzerConfigFiles.Any()
|| state.AdditionalFilesFactories.Any();
}

protected static bool HasAnyChange(SolutionState oldState, SolutionState newState)
{
return !oldState.Sources.SequenceEqual(newState.Sources, SourceFileEqualityComparer.Instance)
|| !oldState.AdditionalFiles.SequenceEqual(newState.AdditionalFiles, SourceFileEqualityComparer.Instance);
|| !oldState.AdditionalFiles.SequenceEqual(newState.AdditionalFiles, SourceFileEqualityComparer.Instance)
|| !oldState.AnalyzerConfigFiles.SequenceEqual(newState.AnalyzerConfigFiles, SourceFileEqualityComparer.Instance);
}

protected static CodeAction? TryGetCodeActionToApply(ImmutableArray<CodeAction> actions, int? codeActionIndex, string? codeActionEquivalenceKey, Action<CodeAction, IVerifier>? codeActionVerifier, IVerifier verifier)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Microsoft.CodeAnalysis.Testing
{
internal static class ProjectExtensions
{
private static readonly Func<Project, IEnumerable<TextDocument>> s_analyzerConfigDocuments;

static ProjectExtensions()
{
var analyzerConfigDocumentType = typeof(Project).GetTypeInfo().Assembly.GetType("Microsoft.CodeAnalysis.AnalyzerConfigDocument");
if (analyzerConfigDocumentType is { })
{
var analyzerConfigDocumentsProperty = typeof(Project).GetProperty(nameof(AnalyzerConfigDocuments), typeof(IEnumerable<>).MakeGenericType(analyzerConfigDocumentType));
if (analyzerConfigDocumentsProperty is { GetMethod: { } getMethod })
{
s_analyzerConfigDocuments = (Func<Project, IEnumerable<TextDocument>>)getMethod.CreateDelegate(typeof(Func<Project, IEnumerable<TextDocument>>), target: null);
}
else
{
s_analyzerConfigDocuments = project => Enumerable.Empty<TextDocument>();
}
}
else
{
s_analyzerConfigDocuments = project => Enumerable.Empty<TextDocument>();
}
}

public static IEnumerable<TextDocument> AnalyzerConfigDocuments(this Project project)
=> s_analyzerConfigDocuments(project);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.Testing
{
internal static class SolutionExtensions
{
private static readonly Func<Solution, DocumentId, string, SourceText, IEnumerable<string>?, string?, Solution> s_addAnalyzerConfigDocument;

static SolutionExtensions()
{
var methodInfo = typeof(Solution).GetMethod(nameof(AddAnalyzerConfigDocument), new[] { typeof(DocumentId), typeof(string), typeof(SourceText), typeof(IEnumerable<string>), typeof(string) });
if (methodInfo is { })
{
s_addAnalyzerConfigDocument = (Func<Solution, DocumentId, string, SourceText, IEnumerable<string>?, string?, Solution>)methodInfo.CreateDelegate(typeof(Func<Solution, DocumentId, string, SourceText, IEnumerable<string>, string, Solution>), target: null);
}
else
{
s_addAnalyzerConfigDocument = (solution, documentId, name, text, folders, filePath) => throw new NotSupportedException();
}
}

public static Solution AddAnalyzerConfigDocument(this Solution solution, DocumentId documentId, string name, SourceText text, IEnumerable<string>? folders = null, string? filePath = null)
{
return s_addAnalyzerConfigDocument(solution, documentId, name, text, folders, filePath);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
</Choose>

<ItemGroup>
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CodeFix.Testing" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Testing.Verifiers.MSTest" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Testing.Verifiers.NUnit" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Testing.Verifiers.XUnit" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public EvaluatedProjectState(ProjectState state, ReferenceAssemblies defaultRefe
state.DocumentationMode ?? DocumentationMode.Diagnose,
state.Sources.ToImmutableArray(),
state.AdditionalFiles.ToImmutableArray(),
state.AnalyzerConfigFiles.ToImmutableArray(),
state.AdditionalProjectReferences.ToImmutableArray(),
state.AdditionalReferences.ToImmutableArray())
{
Expand All @@ -36,6 +37,7 @@ private EvaluatedProjectState(
DocumentationMode documentationMode,
ImmutableArray<(string filename, SourceText content)> sources,
ImmutableArray<(string filename, SourceText content)> additionalFiles,
ImmutableArray<(string filename, SourceText content)> analyzerConfigFiles,
ImmutableArray<string> additionalProjectReferences,
ImmutableArray<MetadataReference> additionalReferences)
{
Expand All @@ -47,6 +49,7 @@ private EvaluatedProjectState(
DocumentationMode = documentationMode;
Sources = sources;
AdditionalFiles = additionalFiles;
AnalyzerConfigFiles = analyzerConfigFiles;
AdditionalProjectReferences = additionalProjectReferences;
AdditionalReferences = additionalReferences;
}
Expand All @@ -67,6 +70,8 @@ private EvaluatedProjectState(

public ImmutableArray<(string filename, SourceText content)> AdditionalFiles { get; }

public ImmutableArray<(string filename, SourceText content)> AnalyzerConfigFiles { get; }

public ImmutableArray<string> AdditionalProjectReferences { get; }

public ImmutableArray<MetadataReference> AdditionalReferences { get; }
Expand All @@ -90,6 +95,7 @@ private EvaluatedProjectState With(
Optional<DocumentationMode> documentationMode = default,
Optional<ImmutableArray<(string filename, SourceText content)>> sources = default,
Optional<ImmutableArray<(string filename, SourceText content)>> additionalFiles = default,
Optional<ImmutableArray<(string filename, SourceText content)>> analyzerConfigFiles = default,
Optional<ImmutableArray<string>> additionalProjectReferences = default,
Optional<ImmutableArray<MetadataReference>> additionalReferences = default)
{
Expand All @@ -102,6 +108,7 @@ private EvaluatedProjectState With(
GetValueOrDefault(documentationMode, DocumentationMode),
GetValueOrDefault(sources, Sources),
GetValueOrDefault(additionalFiles, AdditionalFiles),
GetValueOrDefault(analyzerConfigFiles, AnalyzerConfigFiles),
GetValueOrDefault(additionalProjectReferences, AdditionalProjectReferences),
GetValueOrDefault(additionalReferences, AdditionalReferences));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ internal ProjectState(ProjectState sourceState)

Sources.AddRange(sourceState.Sources);
AdditionalFiles.AddRange(sourceState.AdditionalFiles);
AnalyzerConfigFiles.AddRange(sourceState.AnalyzerConfigFiles);
AdditionalFilesFactories.AddRange(sourceState.AdditionalFilesFactories);
AdditionalProjectReferences.AddRange(sourceState.AdditionalProjectReferences);
}
Expand Down Expand Up @@ -65,6 +66,8 @@ internal ProjectState(ProjectState sourceState)

public SourceFileCollection AdditionalFiles { get; } = new SourceFileCollection();

public SourceFileCollection AnalyzerConfigFiles { get; } = new SourceFileCollection();

public List<Func<IEnumerable<(string filename, SourceText content)>>> AdditionalFilesFactories { get; } = new List<Func<IEnumerable<(string filename, SourceText content)>>>();

public List<string> AdditionalProjectReferences { get; } = new List<string>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState
Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState.AdditionalFiles.get -> System.Collections.Immutable.ImmutableArray<(string filename, Microsoft.CodeAnalysis.Text.SourceText content)>
Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState.AdditionalProjectReferences.get -> System.Collections.Immutable.ImmutableArray<string>
Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState.AdditionalReferences.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.MetadataReference>
Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState.AnalyzerConfigFiles.get -> System.Collections.Immutable.ImmutableArray<(string filename, Microsoft.CodeAnalysis.Text.SourceText content)>
Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState.AssemblyName.get -> string
Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState.DocumentationMode.get -> Microsoft.CodeAnalysis.DocumentationMode
Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState.EvaluatedProjectState(Microsoft.CodeAnalysis.Testing.ProjectState state, Microsoft.CodeAnalysis.Testing.ReferenceAssemblies defaultReferenceAssemblies) -> void
Expand All @@ -144,6 +145,7 @@ Microsoft.CodeAnalysis.Testing.ProjectState.AdditionalFiles.get -> Microsoft.Cod
Microsoft.CodeAnalysis.Testing.ProjectState.AdditionalFilesFactories.get -> System.Collections.Generic.List<System.Func<System.Collections.Generic.IEnumerable<(string filename, Microsoft.CodeAnalysis.Text.SourceText content)>>>
Microsoft.CodeAnalysis.Testing.ProjectState.AdditionalProjectReferences.get -> System.Collections.Generic.List<string>
Microsoft.CodeAnalysis.Testing.ProjectState.AdditionalReferences.get -> Microsoft.CodeAnalysis.Testing.MetadataReferenceCollection
Microsoft.CodeAnalysis.Testing.ProjectState.AnalyzerConfigFiles.get -> Microsoft.CodeAnalysis.Testing.SourceFileCollection
Microsoft.CodeAnalysis.Testing.ProjectState.AssemblyName.get -> string
Microsoft.CodeAnalysis.Testing.ProjectState.DocumentationMode.get -> Microsoft.CodeAnalysis.DocumentationMode?
Microsoft.CodeAnalysis.Testing.ProjectState.DocumentationMode.set -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ public SolutionState WithInheritedValuesApplied(SolutionState? baseState, Immuta
result.AdditionalFiles.AddRange(baseState.AdditionalFiles);
}

if (AnalyzerConfigFiles.Count == 0)
{
result.AnalyzerConfigFiles.AddRange(baseState.AnalyzerConfigFiles);
}

if (AdditionalProjects.Count == 0)
{
result.AdditionalProjects.AddRange(baseState.AdditionalProjects);
Expand Down Expand Up @@ -172,6 +177,7 @@ public SolutionState WithInheritedValuesApplied(SolutionState? baseState, Immuta
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);
Expand Down Expand Up @@ -202,6 +208,11 @@ private static bool HasAnyContentChanges(bool willInherit, SolutionState state,
return true;
}

if ((!willInherit || state.AnalyzerConfigFiles.Any()) && !ContentEqual(state.AnalyzerConfigFiles, baseState.AnalyzerConfigFiles))
{
return true;
}

if ((!willInherit || state.AdditionalReferences.Any()) && !state.AdditionalReferences.SequenceEqual(baseState.AdditionalReferences))
{
return true;
Expand Down Expand Up @@ -241,8 +252,8 @@ private static bool ContentEqual(SourceFileCollection x, SourceFileCollection y)
/// <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"/>, and
/// <see cref="ExpectedDiagnostics"/> updated accordingly.
/// <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,
Expand All @@ -265,7 +276,8 @@ public SolutionState WithProcessedMarkup(MarkupOptions markupOptions, Diagnostic

var markupLocations = ImmutableDictionary<string, FileLinePositionSpan>.Empty;
(var expected, var testSources) = ProcessMarkupSources(Sources, ExpectedDiagnostics, ref markupLocations, markupOptions, defaultDiagnostic, supportedDiagnostics, fixableDiagnostics, defaultPath);
var (additionalExpected, additionalFiles) = ProcessMarkupSources(AdditionalFiles.Concat(AdditionalFilesFactories.SelectMany(factory => factory())), expected, 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;
Expand All @@ -275,18 +287,22 @@ public SolutionState WithProcessedMarkup(MarkupOptions markupOptions, Diagnostic
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 (correctedDiagnostics, additionalProjectAdditionalFiles) = ProcessMarkupSources(projectState.AdditionalFiles.Concat(projectState.AdditionalFilesFactories.SelectMany(factory => factory())), correctedIntermediateDiagnostics, 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;
Expand Down
Loading