提交 8a88bc97 编写于 作者: S Sam Harwell

Add test for formatting code fix relying on .editorconfig

上级 45877d34
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Options;
using Microsoft.VisualStudio.CodingConventions;
namespace Microsoft.CodeAnalysis.CodeStyle
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.FixFormatting)]
[Shared]
internal class CSharpFormattingCodeFixProvider : AbstractFormattingCodeFixProvider
{
private readonly EditorConfigOptionsApplier _editorConfigOptionsApplier = new EditorConfigOptionsApplier();
protected override OptionSet ApplyFormattingOptions(OptionSet optionSet, ICodingConventionContext codingConventionContext)
{
return _editorConfigOptionsApplier.ApplyConventions(optionSet, codingConventionContext.CurrentConventions, LanguageNames.CSharp);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Testing;
using Microsoft.CodeAnalysis.Testing.Verifiers;
......@@ -7,7 +8,7 @@
namespace Microsoft.CodeAnalysis.CodeStyle
{
using Verify = CSharpCodeFixVerifier<CSharpFormattingAnalyzer, FormattingCodeFixProvider, XUnitVerifier>;
using Verify = CSharpCodeFixVerifier<CSharpFormattingAnalyzer, CSharpFormattingCodeFixProvider, XUnitVerifier>;
public class FormattingAnalyzerTests
{
......@@ -184,7 +185,7 @@ class MyClass
}
";
await new CSharpCodeFixTest<CSharpFormattingAnalyzer, FormattingCodeFixProvider, XUnitVerifier>
await new CSharpCodeFixTest<CSharpFormattingAnalyzer, CSharpFormattingCodeFixProvider, XUnitVerifier>
{
TestCode = testCode,
FixedCode = fixedCode,
......@@ -194,5 +195,50 @@ class MyClass
NumberOfIncrementalIterations = 2,
}.RunAsync();
}
[Fact]
public async Task TestEditorConfigUsed()
{
var testCode = @"
class MyClass {
void MyMethod()[| |]{
}
}
";
var fixedCode = @"
class MyClass {
void MyMethod()
{
}
}
";
var editorConfig = @"
root = true
[*.cs]
csharp_new_line_before_open_brace = methods
";
var testDirectoryName = Path.GetRandomFileName();
Directory.CreateDirectory(testDirectoryName);
try
{
File.WriteAllText(Path.Combine(testDirectoryName, ".editorconfig"), editorConfig);
// The contents of this file are ignored, but the coding conventions library checks for existence before
// .editorconfig is used.
File.WriteAllText(Path.Combine(testDirectoryName, "Test0.cs"), string.Empty);
await new CSharpCodeFixTest<CSharpFormattingAnalyzer, CSharpFormattingCodeFixProvider, XUnitVerifier>
{
TestState = { Sources = { (Path.GetFullPath(Path.Combine(testDirectoryName, "Test0.cs")), testCode) } },
FixedState = { Sources = { (Path.GetFullPath(Path.Combine(testDirectoryName, "Test0.cs")), fixedCode) } },
}.RunAsync();
}
finally
{
Directory.Delete(testDirectoryName, true);
}
}
}
}
......@@ -3,13 +3,14 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis
{
internal static class FormattingCodeFixHelper
{
internal static async Task<Document> FixOneAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
internal static async Task<Document> FixOneAsync(Document document, OptionSet options, Diagnostic diagnostic, CancellationToken cancellationToken)
{
var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
......@@ -21,7 +22,6 @@ internal static async Task<Document> FixOneAsync(Document document, Diagnostic d
text.Lines[diagnosticLinePositionSpan.Start.Line].Start,
text.Lines[diagnosticLinePositionSpan.End.Line].End);
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
return await Formatter.FormatAsync(document, spanToFormat, options, cancellationToken).ConfigureAwait(false);
}
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using System.Composition;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
using Microsoft.VisualStudio.CodingConventions;
namespace Microsoft.CodeAnalysis.CodeStyle
{
[ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic, Name = PredefinedCodeFixProviderNames.FixFormatting)]
[Shared]
internal class FormattingCodeFixProvider : CodeFixProvider
internal abstract class AbstractFormattingCodeFixProvider : CodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds
public sealed override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.FormattingDiagnosticId);
public override FixAllProvider GetFixAllProvider()
public sealed override FixAllProvider GetFixAllProvider()
{
return new FixAll();
return new FixAll(this);
}
public override Task RegisterCodeFixesAsync(CodeFixContext context)
public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
{
foreach (var diagnostic in context.Diagnostics)
{
context.RegisterCodeFix(
CodeAction.Create(
CodeStyleResources.Fix_formatting,
c => FormattingCodeFixHelper.FixOneAsync(context.Document, diagnostic, c),
nameof(FormattingCodeFixProvider)),
c => FixOneAsync(context, diagnostic, c),
nameof(AbstractFormattingCodeFixProvider)),
diagnostic);
}
return Task.CompletedTask;
}
protected abstract OptionSet ApplyFormattingOptions(OptionSet optionSet, ICodingConventionContext codingConventionContext);
private async Task<Document> FixOneAsync(CodeFixContext context, Diagnostic diagnostic, CancellationToken cancellationToken)
{
var options = await GetOptionsAsync(context.Document, cancellationToken).ConfigureAwait(false);
return await FormattingCodeFixHelper.FixOneAsync(context.Document, options, diagnostic, cancellationToken).ConfigureAwait(false);
}
private async Task<OptionSet> GetOptionsAsync(Document document, CancellationToken cancellationToken)
{
OptionSet options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
// The in-IDE workspace supports .editorconfig without special handling. However, the AdhocWorkspace used
// in testing requires manual handling of .editorconfig.
if (document.Project.Solution.Workspace is AdhocWorkspace && File.Exists(document.FilePath ?? document.Name))
{
var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager();
var codingConventionContext = await codingConventionsManager.GetConventionContextAsync(document.FilePath ?? document.Name, cancellationToken).ConfigureAwait(false);
options = ApplyFormattingOptions(options, codingConventionContext);
}
return options;
}
/// <summary>
/// Provide an optimized Fix All implementation that runs
/// <see cref="Formatter.FormatAsync(Document, Options.OptionSet, CancellationToken)"/> on the document(s)
......@@ -45,11 +69,18 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
/// </summary>
private class FixAll : DocumentBasedFixAllProvider
{
private readonly AbstractFormattingCodeFixProvider _formattingCodeFixProvider;
public FixAll(AbstractFormattingCodeFixProvider formattingCodeFixProvider)
{
_formattingCodeFixProvider = formattingCodeFixProvider;
}
protected override string CodeActionTitle => CodeStyleResources.Fix_formatting;
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document, ImmutableArray<Diagnostic> diagnostics)
{
var options = await document.GetOptionsAsync(fixAllContext.CancellationToken).ConfigureAwait(false);
var options = await _formattingCodeFixProvider.GetOptionsAsync(document, fixAllContext.CancellationToken).ConfigureAwait(false);
var updatedDocument = await Formatter.FormatAsync(document, options, fixAllContext.CancellationToken).ConfigureAwait(false);
return await updatedDocument.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false);
}
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Composition
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.VisualStudio.CodingConventions
Namespace Microsoft.CodeAnalysis.CodeStyle
<ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=PredefinedCodeFixProviderNames.FixFormatting)>
<[Shared]>
Friend Class VisualBasicFormattingCodeFixProvider
Inherits AbstractFormattingCodeFixProvider
Protected Overrides Function ApplyFormattingOptions(optionSet As OptionSet, codingConventionContext As ICodingConventionContext) As OptionSet
Return optionSet
End Function
End Class
End Namespace
......@@ -3,7 +3,7 @@
Imports Xunit
Imports VerifyVB = Microsoft.CodeAnalysis.VisualBasic.Testing.VisualBasicCodeFixVerifier(
Of Microsoft.CodeAnalysis.CodeStyle.VisualBasicFormattingAnalyzer,
Microsoft.CodeAnalysis.CodeStyle.FormattingCodeFixProvider,
Microsoft.CodeAnalysis.CodeStyle.VisualBasicFormattingCodeFixProvider,
Microsoft.CodeAnalysis.Testing.Verifiers.XUnitVerifier)
Namespace Microsoft.CodeAnalysis.CodeStyle
......
......@@ -24,13 +24,19 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
foreach (var diagnostic in context.Diagnostics)
{
context.RegisterCodeFix(
new MyCodeAction(c => FormattingCodeFixHelper.FixOneAsync(context.Document, diagnostic, c)),
new MyCodeAction(c => FixOneAsync(context, diagnostic, c)),
diagnostic);
}
return Task.CompletedTask;
}
private static async Task<Document> FixOneAsync(CodeFixContext context, Diagnostic diagnostic, CancellationToken cancellationToken)
{
var options = await context.Document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
return await FormattingCodeFixHelper.FixOneAsync(context.Document, options, diagnostic, cancellationToken).ConfigureAwait(false);
}
protected override async Task FixAllAsync(Document document, ImmutableArray<Diagnostic> diagnostics, SyntaxEditor editor, CancellationToken cancellationToken)
{
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册