Document PerformAction(Document document, SemanticModel model, SyntaxNode root, PropertyDeclarationSyntax propertyDeclaration, bool needsSetter) { AccessorDeclarationSyntax accessor = null; PropertyDeclarationSyntax newProp = null; if (needsSetter) { accessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration); var getter = propertyDeclaration.AccessorList.Accessors.FirstOrDefault(m => m.IsKind(SyntaxKind.GetAccessorDeclaration)); if (getter == null) { //get; accessor = accessor.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); } else { var getField = ReplacePropertyWithBackingFieldWithAutoPropertyCodeRefactoringProvider.ScanGetter(model, getter); if (getField == null && getter.Body == null) { //get; accessor = accessor.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)).WithTrailingTrivia(getter.GetTrailingTrivia()); } else if (getField == null || getField.IsReadOnly) { //readonly or no field can be found accessor = accessor.WithBody(GetNotImplementedBlock()); } else { //now we add a 'field = value'. accessor = accessor.WithBody(SyntaxFactory.Block( SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(getField.Name), SyntaxFactory.IdentifierName("value"))))); } } newProp = propertyDeclaration.WithAccessorList(propertyDeclaration.AccessorList.AddAccessors(accessor)); } else { accessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration); var setter = propertyDeclaration.AccessorList.Accessors.FirstOrDefault(m => m.IsKind(SyntaxKind.SetAccessorDeclaration)); var accessorDeclList = new SyntaxList <AccessorDeclarationSyntax>(); if (setter == null) { //set; accessor = accessor.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); } else { var setField = ReplacePropertyWithBackingFieldWithAutoPropertyCodeRefactoringProvider.ScanSetter(model, setter); if (setField == null && setter.Body == null) { //set; accessor = accessor.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)).WithTrailingTrivia(setter.GetTrailingTrivia()); } else if (setField == null) { //no field can be found accessor = accessor.WithBody(GetNotImplementedBlock()); } else { //now we add a 'return field;'. accessor = accessor.WithBody(SyntaxFactory.Block( SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(setField.Name)))); } accessorDeclList = accessorDeclList.Add(propertyDeclaration.AccessorList.Accessors.First(m => m.IsKind(SyntaxKind.SetAccessorDeclaration))); } accessorDeclList = accessorDeclList.Insert(0, accessor); var accessorList = SyntaxFactory.AccessorList(accessorDeclList); newProp = propertyDeclaration.WithAccessorList(accessorList); } var newRoot = root.ReplaceNode((SyntaxNode)propertyDeclaration, newProp).WithAdditionalAnnotations(Formatter.Annotation); return(document.WithSyntaxRoot(newRoot)); }
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 property = root.FindNode(span) as PropertyDeclarationSyntax; if (property == null || !property.Identifier.Span.Contains(span)) { return; } var field = ReplacePropertyWithBackingFieldWithAutoPropertyCodeRefactoringProvider.GetBackingField(model, property); if (field == null) { return; } var type = property.Parent as TypeDeclarationSyntax; if (type == null) { return; } var resolvedType = model.Compilation.GetTypeSymbol("System", "EventHandler", 0, cancellationToken); if (resolvedType == null) { return; } context.RegisterRefactoring( CodeActionFactory.Create( span, DiagnosticSeverity.Info, GettextCatalog.GetString("Create changed event"), t2 => { var eventDeclaration = CreateChangedEventDeclaration(property); var methodDeclaration = CreateEventInvocatorCodeRefactoringProvider.CreateEventInvocator( document, type.Identifier.ToString(), type.Modifiers.Any(m => m.IsKind(SyntaxKind.SealedKeyword)), eventDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword)), eventDeclaration.Declaration.Variables.First().Identifier.ToString(), resolvedType.GetDelegateInvokeMethod(), false ); var invocation = SyntaxFactory.ExpressionStatement(SyntaxFactory.InvocationExpression( SyntaxFactory.IdentifierName(methodDeclaration.Identifier.ToString()), SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList <ArgumentSyntax>(new[] { SyntaxFactory.Argument(SyntaxFactory.ParseExpression("System.EventArgs.Empty")) })) )); var marker = new SyntaxAnnotation(); var newRoot = root.ReplaceNode(property, property.WithAdditionalAnnotations(marker)); newRoot = newRoot.InsertNodesAfter(newRoot.GetAnnotatedNodes(marker).First(), new SyntaxNode[] { methodDeclaration.WithAdditionalAnnotations(Formatter.Annotation), eventDeclaration.WithAdditionalAnnotations(Formatter.Annotation) }); newRoot = newRoot.InsertNodesAfter(newRoot.GetAnnotatedNodes(marker).OfType <PropertyDeclarationSyntax>().First().AccessorList.Accessors.First(a => a.IsKind(SyntaxKind.SetAccessorDeclaration)).Body.Statements.Last(), new[] { invocation.WithAdditionalAnnotations(Formatter.Annotation, Simplifier.Annotation) } ); return(Task.FromResult(document.WithSyntaxRoot(newRoot))); }) ); }