Skip to content

Commit

Permalink
Add unit test for code style fixer formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeRobich committed Dec 9, 2020
1 parent 766c177 commit b65cd06
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 38 deletions.
14 changes: 14 additions & 0 deletions src/Analyzers/AnalyzerFormatter.cs
Expand Up @@ -16,6 +16,20 @@ namespace Microsoft.CodeAnalysis.Tools.Analyzers
{
internal class AnalyzerFormatter : ICodeFormatter
{
public static AnalyzerFormatter CodeStyleFormatter => new AnalyzerFormatter(
Resources.Code_Style,
FixCategory.CodeStyle,
new CodeStyleInformationProvider(),
new AnalyzerRunner(),
new SolutionCodeFixApplier());

public static AnalyzerFormatter ThirdPartyFormatter => new AnalyzerFormatter(
Resources.Analyzer_Reference,
FixCategory.Analyzers,
new AnalyzerReferenceInformationProvider(),
new AnalyzerRunner(),
new SolutionCodeFixApplier());

private readonly string _name;
private readonly IAnalyzerInformationProvider _informationProvider;
private readonly IAnalyzerRunner _runner;
Expand Down
4 changes: 2 additions & 2 deletions src/CodeFormatter.cs
Expand Up @@ -25,8 +25,8 @@ internal static class CodeFormatter
new CharsetFormatter(),
new OrganizeImportsFormatter(),
new UnnecessaryImportsFormatter(),
new AnalyzerFormatter(Resources.Code_Style, FixCategory.CodeStyle, new CodeStyleInformationProvider(), new AnalyzerRunner(), new SolutionCodeFixApplier()),
new AnalyzerFormatter(Resources.Analyzer_Reference, FixCategory.Analyzers, new AnalyzerReferenceInformationProvider(), new AnalyzerRunner(), new SolutionCodeFixApplier()));
AnalyzerFormatter.CodeStyleFormatter,
AnalyzerFormatter.ThirdPartyFormatter);

public static async Task<WorkspaceFormatResult> FormatWorkspaceAsync(
FormatOptions formatOptions,
Expand Down
57 changes: 57 additions & 0 deletions tests/Analyzers/CodeStyleAnalyzerFormatterTests.cs
@@ -0,0 +1,57 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Tools.Analyzers;
using Microsoft.CodeAnalysis.Tools.Formatters;
using Microsoft.CodeAnalysis.Tools.Tests.Formatters;
using Xunit;

namespace Microsoft.CodeAnalysis.Tools.Tests.Analyzers
{
public class CodeStyleAnalyzerFormatterTests : CSharpFormatterTests
{
private protected override ICodeFormatter Formatter => AnalyzerFormatter.CodeStyleFormatter;

[Fact]
public async Task TestUseVarCodeStyle_AppliesWhenNotUsingVar()
{
var testCode = @"
using System.Collections.Generic;
class C
{
void M()
{
object obj = new object();
List<string> list = new List<string>();
int count = 5;
}
}";

var expectedCode = @"
using System.Collections.Generic;
class C
{
void M()
{
var obj = new object();
var list = new List<string>();
var count = 5;
}
}";

var editorConfig = new Dictionary<string, string>()
{
/// Prefer "var" everywhere
["dotnet_diagnostic.IDE0007.severity"] = "error",
["csharp_style_var_for_built_in_types"] = "true:error",
["csharp_style_var_when_type_is_apparent"] = "true:error",
["csharp_style_var_elsewhere"] = "true:error",
};

await AssertCodeChangedAsync(testCode, expectedCode, editorConfig, fixCategory: FixCategory.CodeStyle);
}
}
}
64 changes: 28 additions & 36 deletions tests/Formatters/AbstractFormatterTests.cs
Expand Up @@ -9,7 +9,6 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Tools.Formatters;
Expand All @@ -23,12 +22,6 @@ namespace Microsoft.CodeAnalysis.Tools.Tests.Formatters
{
public abstract class AbstractFormatterTest
{
private static MetadataReference CorlibReference => MetadataReference.CreateFromFile(typeof(object).Assembly.Location).WithAliases(ImmutableArray.Create("global", "corlib"));
private static MetadataReference SystemReference => MetadataReference.CreateFromFile(typeof(System.Diagnostics.Debug).Assembly.Location).WithAliases(ImmutableArray.Create("global", "system"));
private static MetadataReference SystemCoreReference => MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location);
private static MetadataReference CodeAnalysisReference => MetadataReference.CreateFromFile(typeof(Compilation).Assembly.Location);

private static MetadataReference SystemCollectionsImmutableReference => MetadataReference.CreateFromFile(typeof(ImmutableArray).Assembly.Location);
private static MetadataReference MicrosoftVisualBasicReference => MetadataReference.CreateFromFile(typeof(Microsoft.VisualBasic.Strings).Assembly.Location);

private static Lazy<IExportProviderFactory> ExportProviderFactory { get; }
Expand All @@ -49,6 +42,8 @@ static AbstractFormatterTest()
LazyThreadSafetyMode.ExecutionAndPublication);
}

protected virtual ReferenceAssemblies ReferenceAssemblies => ReferenceAssemblies.Default;

protected virtual string DefaultFilePathPrefix => "Test";

protected virtual string DefaultTestProjectName => "TestProject";
Expand All @@ -59,7 +54,7 @@ static AbstractFormatterTest()

protected virtual string DefaultTestProjectPath => Path.Combine(DefaultFolderPath, $"{DefaultTestProjectName}.{DefaultFileExt}proj");

protected virtual string DefaultEditorConfigPath => Path.Combine(DefaultFolderPath + ".editorconfig");
protected virtual string DefaultEditorConfigPath => Path.Combine(DefaultFolderPath, ".editorconfig");

protected virtual string DefaultFilePath => Path.Combine(DefaultFolderPath, $"{DefaultFilePathPrefix}0.{DefaultFileExt}");

Expand All @@ -77,7 +72,7 @@ protected AbstractFormatterTest()
/// </summary>
public abstract string Language { get; }

private static ILogger Logger => new TestLogger();
private static TestLogger Logger => new TestLogger();

public SolutionState TestState { get; }

Expand Down Expand Up @@ -129,7 +124,7 @@ protected AbstractFormatterTest()
var fileMatcher = SourceFileMatcher.CreateMatcher(new[] { document.FilePath }, exclude: Array.Empty<string>());
var formatOptions = new FormatOptions(
workspaceFilePath: project.FilePath,
workspaceType: WorkspaceType.Folder,
workspaceType: WorkspaceType.Solution,
logLevel: LogLevel.Trace,
fixCategory,
codeStyleSeverity,
Expand Down Expand Up @@ -174,12 +169,6 @@ protected AbstractFormatterTest()
/// </remarks>
public Dictionary<string, string> XmlReferences { get; } = new Dictionary<string, string>();

/// <summary>
/// Gets a collection of transformation functions to apply to <see cref="Workspace.Options"/> during diagnostic
/// or code fix test setup.
/// </summary>
public List<Func<OptionSet, OptionSet>> OptionsTransforms { get; } = new List<Func<OptionSet, OptionSet>>();

/// <summary>
/// Given an array of strings as sources and a language, turn them into a <see cref="Project"/> and return the
/// solution.
Expand Down Expand Up @@ -252,7 +241,7 @@ protected virtual Project CreateProjectImpl((string filename, SourceText content
{
(var newFileName, var source) = sources[i];
var documentId = DocumentId.CreateNewId(projectId, debugName: newFileName);
solution = solution.AddDocument(documentId, newFileName, source, filePath: Path.Combine(DefaultTestProjectPath, newFileName));
solution = solution.AddDocument(documentId, newFileName, source, filePath: Path.Combine(DefaultFolderPath, newFileName));
}

for (var i = 0; i < additionalFiles.Length; i++)
Expand All @@ -274,48 +263,49 @@ protected virtual Project CreateProjectImpl((string filename, SourceText content
/// <returns>The created solution.</returns>
protected virtual Solution CreateSolution(ProjectId projectId, string language, SourceText editorConfigText)
{
var compilationOptions = CreateCompilationOptions();

var xmlReferenceResolver = new TestXmlReferenceResolver();
foreach (var xmlReference in XmlReferences)
{
xmlReferenceResolver.XmlReferences.Add(xmlReference.Key, xmlReference.Value);
}

compilationOptions = compilationOptions.WithXmlReferenceResolver(xmlReferenceResolver);
var compilationOptions = CreateCompilationOptions()
.WithXmlReferenceResolver(xmlReferenceResolver)
.WithAssemblyIdentityComparer(ReferenceAssemblies.AssemblyIdentityComparer);

var parseOptions = CreateParseOptions();
var referenceAssemblies = ReferenceAssemblies.ResolveAsync(language, CancellationToken.None).GetAwaiter().GetResult();

var editorConfigDocument = DocumentInfo.Create(
DocumentId.CreateNewId(projectId, DefaultEditorConfigPath),
name: DefaultEditorConfigPath,
loader: TextLoader.From(TextAndVersion.Create(editorConfigText, VersionStamp.Create())),
filePath: DefaultEditorConfigPath);

var projectInfo = ProjectInfo.Create(projectId, VersionStamp.Create(), DefaultTestProjectName, DefaultTestProjectName, language, filePath: DefaultTestProjectPath)
var projectInfo = ProjectInfo.Create(
projectId,
VersionStamp.Create(),
name: DefaultTestProjectName,
assemblyName: DefaultTestProjectName,
language,
filePath: DefaultTestProjectPath,
outputFilePath: Path.ChangeExtension(DefaultTestProjectPath, "dll"),
compilationOptions: compilationOptions,
parseOptions: parseOptions,
metadataReferences: referenceAssemblies,
isSubmission: false)
.WithDefaultNamespace(DefaultTestProjectName)
.WithAnalyzerConfigDocuments(ImmutableArray.Create(editorConfigDocument));

var solution = CreateWorkspace()
.CurrentSolution
.AddProject(projectInfo)
.WithProjectCompilationOptions(projectId, compilationOptions)
.AddMetadataReference(projectId, CorlibReference)
.AddMetadataReference(projectId, SystemReference)
.AddMetadataReference(projectId, SystemCoreReference)
.AddMetadataReference(projectId, CodeAnalysisReference)
.AddMetadataReference(projectId, SystemCollectionsImmutableReference);
.AddProject(projectInfo);

if (language == LanguageNames.VisualBasic)
{
solution = solution.AddMetadataReference(projectId, MicrosoftVisualBasicReference);
}

foreach (var transform in OptionsTransforms)
{
solution.Workspace.TryApplyChanges(solution.WithOptions(transform(solution.Workspace.Options)));
}

var parseOptions = solution.GetProject(projectId).ParseOptions;
solution = solution.WithProjectParseOptions(projectId, parseOptions.WithDocumentationMode(DocumentationMode.Diagnose));

return solution;
}

Expand All @@ -327,5 +317,7 @@ public virtual AdhocWorkspace CreateWorkspace()
}

protected abstract CompilationOptions CreateCompilationOptions();

protected abstract ParseOptions CreateParseOptions();
}
}
3 changes: 3 additions & 0 deletions tests/Formatters/CSharpFormatterTests.cs
Expand Up @@ -12,5 +12,8 @@ public abstract class CSharpFormatterTests : AbstractFormatterTest

protected override CompilationOptions CreateCompilationOptions()
=> new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true);

protected override ParseOptions CreateParseOptions()
=> new CSharpParseOptions(LanguageVersion.Default, DocumentationMode.Diagnose);
}
}

0 comments on commit b65cd06

Please sign in to comment.