Skip to content

Commit

Permalink
Fixed issue code-cracker#537 by creating multiple variable declaratio…
Browse files Browse the repository at this point in the history
…ns rather than a single declaration.
  • Loading branch information
Shiney authored and jwooley committed Nov 3, 2015
1 parent 5abc1f0 commit 09ff785
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 9 deletions.
51 changes: 43 additions & 8 deletions src/CSharp/CodeCracker/Style/AlwaysUseVarCodeFixProvider.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.CodeAnalysis;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
Expand Down Expand Up @@ -30,15 +31,49 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
private async static Task<Document> UseVarAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

var diagnosticSpan = diagnostic.Location.SourceSpan;
var localDeclaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<LocalDeclarationStatementSyntax>().First();
var variableDeclaration = localDeclaration.ChildNodes()
.OfType<VariableDeclarationSyntax>()
.FirstOrDefault();
var @var = SyntaxFactory.IdentifierName("var")
.WithLeadingTrivia(variableDeclaration.Type.GetLeadingTrivia())
.WithTrailingTrivia(variableDeclaration.Type.GetTrailingTrivia());
var newRoot = root.ReplaceNode(variableDeclaration.Type, @var);
var variableDeclaration = localDeclaration.Declaration;
var numVariables = variableDeclaration.Variables.Count;

var newVariableDeclarations = new VariableDeclarationSyntax[numVariables];

var varSyntax = SyntaxFactory.IdentifierName("var");

//Create a new var declaration for each variable.
for (var i = 0; i < numVariables; i++)
{
var originalVariable = variableDeclaration.Variables[i];
var newLeadingTrivia = originalVariable.GetLeadingTrivia();

//Get the trivia from the separator as well
if (i != 0)
{
newLeadingTrivia = newLeadingTrivia.InsertRange(0,
variableDeclaration.Variables.GetSeparator(i-1).GetAllTrivia());
}

newVariableDeclarations[i] = SyntaxFactory.VariableDeclaration(varSyntax)
.AddVariables(originalVariable.WithLeadingTrivia(newLeadingTrivia));
}

//ensure trivia for leading type node is preserved
var originalTypeSyntax = variableDeclaration.Type;
newVariableDeclarations[0] = newVariableDeclarations[0]
.WithType((TypeSyntax) varSyntax.WithSameTriviaAs(originalTypeSyntax));

var newLocalDeclarationStatements = newVariableDeclarations.Select(SyntaxFactory.LocalDeclarationStatement).ToList();


//Preserve the trivia for the entire statement at the start and at the end
newLocalDeclarationStatements[0] =
newLocalDeclarationStatements[0].WithLeadingTrivia(variableDeclaration.GetLeadingTrivia());
var lastIndex = numVariables -1;
newLocalDeclarationStatements[lastIndex] =
newLocalDeclarationStatements[lastIndex].WithTrailingTrivia(localDeclaration.GetTrailingTrivia());

var newRoot = root.ReplaceNode(localDeclaration, newLocalDeclarationStatements);
var newDocument = document.WithSyntaxRoot(newRoot);
return newDocument;
}
Expand Down
80 changes: 79 additions & 1 deletion test/CSharp/CodeCracker.Test/Style/AlwaysUseVarTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,5 +215,83 @@ public void Foo()
}";
await VerifyCSharpFixAllAsync(new[] { source1, source2 }, new[] { fixtest1, fixtest2 });
}


[Fact]
public async Task FixReplacesMultipleDeclarationWithMultipleVars()
{
const string test = @"
using System;
namespace ConsoleApplication1
{
class TypeName
{
public async Task Foo()
{
int a = 10, b = 12;
}
}
}";

const string expected = @"
using System;
namespace ConsoleApplication1
{
class TypeName
{
public async Task Foo()
{
var a = 10;
var b = 12;
}
}
}";
await VerifyCSharpFixAsync(test, expected);
}



[Fact]
public async Task FixPreservesTriviaSensibly()
{
const string test = @"
using System;
namespace ConsoleApplication1
{
class TypeName
{
public async Task Foo()
{
int a = 10; //Blue
/*variables for use*/ string /*desc of b*/b = /* why not*/ ""12"", /*Formatter does this My next variable*/ c /* is quite nice and it */ = ""23"";
}
}
}";

const string expected = @"
using System;
namespace ConsoleApplication1
{
class TypeName
{
public async Task Foo()
{
var a = 10; //Blue
/*variables for use*/ var /*desc of b*/b = /* why not*/ ""12"";
var
/*Formatter does this My next variable*/ c /* is quite nice and it */ = ""23"";
}
}
}";
await VerifyCSharpFixAllAsync(test, expected);
}
}
}
}


0 comments on commit 09ff785

Please sign in to comment.