提交 ec8274b2 编写于 作者: I Ivan Shimko

Remove trivia handling, simplify approach

上级 c966953e
......@@ -28,8 +28,8 @@ public class RemoveNewModifierCodeFixProviderTests : AbstractCSharpDiagnosticPro
"public new int [|Test|] { get; set; }",
"public int [|Test|] { get; set; }")]
[InlineData(
"public const new int [|test|] = 1;",
"public const int [|test|] = 1;")]
"public new const int [|test|] = 1;",
"public const int test = 1;")]
[InlineData(
"public new event Action [|Test|];",
"public event Action Test;")]
......@@ -54,85 +54,36 @@ public class RemoveNewModifierCodeFixProviderTests : AbstractCSharpDiagnosticPro
[InlineData(
"new(int a, int b) [|test|];",
"(int a, int b) test;")]
public Task TestRemoveNewModifierFromMembersWithRegularFormatting(string original, string expected) =>
TestRemoveNewModifierCodeFixAsync(original, expected);
public Task TestRemoveNewModifierFromMembersWithRegularFormatting(string original, string expected)
=> TestRemoveNewModifierCodeFixAsync(original, expected);
[Theory]
[InlineData(
"/* start */ public /* middle */ new /* end */ int [|Test|];",
"/* start */ public /* middle */ /* end */ int Test;")]
"/* start */ public /* middle */ int Test;")]
[InlineData(
"/* start */ public /* middle */ new /* end */ int [|Test|];",
"/* start */ public /* middle */ /* end */ int Test;")]
"/* start */ public /* middle */ int Test;")]
[InlineData(
"/* start */ public /* middle */new /* end */ int [|Test|];",
"/* start */ public /* middle */ /* end */ int Test;")]
"/* start */ public /* middle */int Test;")]
[InlineData(
"/* start */ public /* middle */ new/* end */ int [|Test|];",
"/* start */ public /* middle */ /* end */ int Test;")]
"/* start */ public /* middle */ int Test;")]
[InlineData(
"/* start */ public /* middle */new/* end */ int [|Test|];",
"/* start */ public /* middle *//* end */ int Test;")]
"/* start */ public /* middle */int Test;")]
[InlineData(
"new /* end */ int [|Test|];",
"/* end */ int Test;")]
"int Test;")]
[InlineData(
"new int [|Test|];",
"int Test;")]
[InlineData(
"/* start */ new /* end */ int [|Test|];",
"/* start */ /* end */ int [|Test|];")]
public Task TestRemoveNewFromModifiersWithComplexTrivia(string original, string expected) =>
TestRemoveNewModifierCodeFixAsync(original, expected);
[Fact]
public Task TestRemoveNewFromModifiersFixAll() =>
TestInRegularAndScriptAsync(@"
using System;
class B
{
public int ValidNew;
}
class C : B
{
public new int ValidNew;
public new void {|FixAllInDocument:M|}() { }
public new int F;
public new event Action E;
public new int P { get; }
public new int this[int p] => p;
new class C2 { }
new struct S2 { }
new interface I2 { }
new delegate void D2();
new enum E2 { }
}",
@"
using System;
class B
{
public int ValidNew;
}
class C : B
{
public new int ValidNew;
public void M() { }
public int F;
public event Action E;
public int P { get; }
public int this[int p] => p;
class C2 { }
struct S2 { }
interface I2 { }
delegate void D2();
enum E2 { }
}");
"/* start */ int [|Test|];")]
public Task TestRemoveNewFromModifiersWithComplexTrivia(string original, string expected)
=> TestRemoveNewModifierCodeFixAsync(original, expected);
private Task TestRemoveNewModifierCodeFixAsync(string original, string expected)
{
......
......@@ -11,9 +11,8 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.LanguageServices;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Shared.Extensions;
namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.RemoveNewModifier
......@@ -47,75 +46,27 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
if (memberDeclarationSyntax == null)
return;
var newModifier = GetNewModifier(memberDeclarationSyntax, CSharpSyntaxFacts.Instance);
if (newModifier == default)
var generator = context.Document.GetRequiredLanguageService<SyntaxGenerator>();
if (!generator.GetModifiers(memberDeclarationSyntax).IsNew)
return;
context.RegisterCodeFix(
new MyCodeAction(ct => FixAsync(context.Document, memberDeclarationSyntax, ct)),
new MyCodeAction(ct => FixAsync(context.Document, generator, memberDeclarationSyntax, ct)),
context.Diagnostics);
}
private async Task<Document> FixAsync(Document document, MemberDeclarationSyntax node, CancellationToken cancellationToken)
private static async Task<Document> FixAsync(
Document document,
SyntaxGenerator generator,
MemberDeclarationSyntax memberDeclaration,
CancellationToken cancellationToken)
{
var syntaxFacts = CSharpSyntaxFacts.Instance;
var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var newModifier = GetNewModifier(node, syntaxFacts);
var newNode = node;
if (newModifier.HasTrailingTrivia || newModifier.HasLeadingTrivia)
{
var newModifierTrivia = newModifier.GetAllTrivia().ToSyntaxTriviaList();
var previousToken = newModifier.GetPreviousToken();
var nextToken = newModifier.GetNextToken();
var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
var isFirstTokenOnLine = newModifier.IsFirstTokenOnLine(sourceText);
var newTrivia = new SyntaxTriviaList();
if (!isFirstTokenOnLine)
newTrivia = newTrivia.AddRange(previousToken.TrailingTrivia);
newTrivia = newTrivia
.AddRange(newModifierTrivia)
.AddRange(nextToken.LeadingTrivia);
newTrivia = CollapseSequentialWhitespaceTrivia(newTrivia);
if (isFirstTokenOnLine)
{
var nextTokenWithMovedTrivia = nextToken.WithLeadingTrivia(newTrivia);
newNode = newNode.ReplaceToken(nextToken, nextTokenWithMovedTrivia);
}
else
{
var previousTokenWithMovedTrivia = previousToken.WithTrailingTrivia(newTrivia);
newNode = newNode.ReplaceToken(previousToken, previousTokenWithMovedTrivia);
}
}
newNode = newNode.ReplaceToken(GetNewModifier(newNode, syntaxFacts), SyntaxFactory.Token(SyntaxKind.None));
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var newRoot = root.ReplaceNode(node, newNode);
return document.WithSyntaxRoot(newRoot);
}
private static SyntaxToken GetNewModifier(SyntaxNode fromNode, CSharpSyntaxFacts syntaxFacts) =>
syntaxFacts.GetModifierTokens(fromNode).FirstOrDefault(m => m.IsKind(SyntaxKind.NewKeyword));
private static SyntaxTriviaList CollapseSequentialWhitespaceTrivia(SyntaxTriviaList triviaList)
{
var result = new SyntaxTriviaList();
var previous = default(SyntaxTrivia);
foreach (var current in triviaList)
{
if (!(previous.IsWhitespace() && current.IsWhitespace()))
result = result.Add(current);
previous = current;
}
return result;
return document.WithSyntaxRoot(root.ReplaceNode(
memberDeclaration,
generator.WithModifiers(
memberDeclaration, generator.GetModifiers(memberDeclaration).WithIsNew(false))));
}
private class MyCodeAction : CustomCodeActions.DocumentChangeAction
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册