Created
July 25, 2015 09:57
-
-
Save Novakov/bf6e521506a4511e3401 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading.Tasks; | |
using Microsoft.CodeAnalysis; | |
using Microsoft.CodeAnalysis.CSharp; | |
using Microsoft.CodeAnalysis.CSharp.Syntax; | |
using Microsoft.CodeAnalysis.CodeRefactorings; | |
using Microsoft.CodeAnalysis.Formatting; | |
namespace RefactoringEssentials.CSharp.CodeRefactorings | |
{ | |
[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = "Initialize field from constructor parameter")] | |
public class InitializeFieldFromConstructorParameterCodeRefactoringProvider : CodeRefactoringProvider | |
{ | |
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) | |
{ | |
var document = context.Document; | |
if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) | |
return; | |
var span = context.Span; | |
if (!span.IsEmpty) | |
return; | |
var cancellationToken = context.CancellationToken; | |
if (cancellationToken.IsCancellationRequested) | |
return; | |
var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); | |
if (model.IsFromGeneratedCode(cancellationToken)) | |
return; | |
var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); | |
var token = root.FindToken(span.Start); | |
var parameter = token.Parent as ParameterSyntax; | |
if (parameter != null) | |
{ | |
var ctor = parameter.Parent.Parent as ConstructorDeclarationSyntax; | |
if (ctor == null) | |
return; | |
context.RegisterRefactoring( | |
CodeActionFactory.Create( | |
parameter.Span, | |
DiagnosticSeverity.Info, | |
GettextCatalog.GetString("Initialize field from parameter"), | |
document.WithSyntaxRoot(Refactor(root, parameter, ctor)) | |
)); | |
} | |
} | |
private static SyntaxNode Refactor(SyntaxNode root, ParameterSyntax parameter, ConstructorDeclarationSyntax ctor) | |
{ | |
var newField = SyntaxFactory.FieldDeclaration( | |
SyntaxFactory.VariableDeclaration( | |
parameter.Type, | |
SyntaxFactory.SingletonSeparatedList<VariableDeclaratorSyntax>(SyntaxFactory.VariableDeclarator(parameter.Identifier))) | |
).WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword))) | |
.WithAdditionalAnnotations(Formatter.Annotation); | |
var assignmentStatement = SyntaxFactory.ExpressionStatement( | |
SyntaxFactory.AssignmentExpression( | |
SyntaxKind.SimpleAssignmentExpression, | |
SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(parameter.Identifier)), | |
SyntaxFactory.IdentifierName(parameter.Identifier) | |
) | |
).WithAdditionalAnnotations(Formatter.Annotation); | |
var trackedRoot = root.TrackNodes(ctor); | |
var newRoot = trackedRoot.InsertNodesBefore(trackedRoot.GetCurrentNode(ctor), new List<SyntaxNode>() { | |
newField | |
}); | |
newRoot = newRoot.ReplaceNode(newRoot.GetCurrentNode(ctor), ctor.WithBody( | |
ctor.Body.WithStatements(SyntaxFactory.List<StatementSyntax>(new[] { assignmentStatement }.Concat(ctor.Body.Statements))) | |
)); | |
return newRoot; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment