public async static Task<Solution> MakeAutoPropertyAsync(Document document, SyntaxNode root, PropertyDeclarationSyntax property, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var getterReturn = (ReturnStatementSyntax)property.AccessorList.Accessors.First(a => a.Keyword.ValueText == "get").Body.Statements.First(); var returnIdentifier = (IdentifierNameSyntax)(getterReturn.Expression is MemberAccessExpressionSyntax ? ((MemberAccessExpressionSyntax)getterReturn.Expression).Name : getterReturn.Expression); var returnIdentifierSymbol = semanticModel.GetSymbolInfo(returnIdentifier).Symbol; var variableDeclarator = (VariableDeclaratorSyntax)returnIdentifierSymbol.DeclaringSyntaxReferences.First().GetSyntax(); var fieldDeclaration = variableDeclarator.FirstAncestorOfType<FieldDeclarationSyntax>(); root = root.TrackNodes(returnIdentifier, fieldDeclaration, property); document = document.WithSyntaxRoot(root); root = await document.GetSyntaxRootAsync(cancellationToken); semanticModel = await document.GetSemanticModelAsync(cancellationToken); returnIdentifier = root.GetCurrentNode(returnIdentifier); returnIdentifierSymbol = semanticModel.GetSymbolInfo(returnIdentifier).Symbol; var newProperty = GetSimpleProperty(property, variableDeclarator) .WithTriviaFrom(property) .WithAdditionalAnnotations(Formatter.Annotation); var newSolution = await Renamer.RenameSymbolAsync(document.Project.Solution, returnIdentifierSymbol, property.Identifier.ValueText, document.Project.Solution.Workspace.Options, cancellationToken); document = newSolution.GetDocument(document.Id); root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); root = root.InsertNodesAfter(root.GetCurrentNode(property), new[] { newProperty }); var multipleVariableDeclaration = fieldDeclaration.Declaration.Variables.Count > 1; if (multipleVariableDeclaration) { var newfieldDeclaration = fieldDeclaration.WithDeclaration(fieldDeclaration.Declaration.RemoveNode(variableDeclarator, SyntaxRemoveOptions.KeepNoTrivia)); root = root.RemoveNode(root.GetCurrentNode<SyntaxNode>(property), SyntaxRemoveOptions.KeepNoTrivia); root = root.ReplaceNode(root.GetCurrentNode(fieldDeclaration), newfieldDeclaration); } else { root = root.RemoveNodes(root.GetCurrentNodes<SyntaxNode>(new SyntaxNode[] { fieldDeclaration, property }), SyntaxRemoveOptions.KeepNoTrivia); } document = document.WithSyntaxRoot(root); return document.Project.Solution; }
private static SyntaxNode CreateRootAddingDisposeToEndOfMethod(SyntaxNode root, ExpressionStatementSyntax statement, ILocalSymbol identitySymbol) { var method = statement.FirstAncestorOrSelf<MethodDeclarationSyntax>(); var newDispose = ImplementsDisposableExplicitly(identitySymbol.Type) ? SyntaxFactory.ExpressionStatement(SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ParenthesizedExpression(SyntaxFactory.CastExpression(SyntaxFactory.ParseName("System.IDisposable").WithAdditionalAnnotations(Simplifier.Annotation), SyntaxFactory.IdentifierName(identitySymbol.Name))), SyntaxFactory.IdentifierName("Dispose")))) : SyntaxFactory.ParseStatement($"{identitySymbol.Name}.Dispose();"); newDispose = newDispose.WithAdditionalAnnotations(Formatter.Annotation); var last = method.Body.Statements.Last(); var newRoot = root.InsertNodesAfter(method.Body.Statements.Last(), new[] { newDispose }); return newRoot; }
private Task<Document> MakePropertiesAsync(Document document, SyntaxNode root, TextSpan span, CancellationToken cancellationToken) { var field = root.FindNode(span) as FieldDeclarationSyntax; var semicolon = SyntaxFactory.Token(SyntaxKind.SemicolonToken); // { get; } var getAccessor = SyntaxFactory.AccessorList(SyntaxFactory.List(new[] { SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(semicolon), })); // { get; set; } var getSetAccessor = getAccessor.AddAccessors(SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(semicolon)); var propertySyntaxes = field.Declaration.Variables.Select(v => { var isReadOnly = field.Modifiers.Any(SyntaxKind.ReadOnlyKeyword); var accessors = isReadOnly ? getAccessor : getSetAccessor; var initializer = v.ChildNodes().OfType<EqualsValueClauseSyntax>().FirstOrDefault(); var property = SyntaxFactory.PropertyDeclaration( attributeLists: field.AttributeLists, modifiers: isReadOnly ? field.Modifiers.Remove(field.Modifiers.Where(x => x.IsKind(SyntaxKind.ReadOnlyKeyword)).First()) : field.Modifiers, type: field.Declaration.Type, explicitInterfaceSpecifier: null, identifier: v.Identifier, accessorList: accessors, expressionBody: null, initializer: initializer ); // int Foo { get; set; }\n or int Bar { get; set; } = 1;\n return (initializer != null ? property.WithSemicolonToken(semicolon) : property) .WithTrailingTrivia(SyntaxFactory.SyntaxTrivia(SyntaxKind.EndOfLineTrivia, Environment.NewLine)) .WithAdditionalAnnotations(Formatter.Annotation); }); var inserted = root.InsertNodesAfter(field, propertySyntaxes); var removingNode = inserted.FindNode(span); var newRoot = inserted.RemoveNode(removingNode, SyntaxRemoveOptions.KeepNoTrivia); return Task.FromResult(document.WithSyntaxRoot(newRoot)); }
static CodeAction Handle(Document document, Microsoft.CodeAnalysis.Text.TextSpan span, SyntaxNode root, SyntaxNode node, ExpressionSyntax iterateOver, bool replaceNode) { return CodeActionFactory.Create( span, DiagnosticSeverity.Info, "Iterate via 'foreach'", ct => { ForEachStatementSyntax foreachStmt = BuildForeach(iterateOver); SyntaxNode newRoot; var ancestor = node.GetAncestor<StatementSyntax>(); if (replaceNode) { newRoot = root.ReplaceNode(ancestor, new[] { foreachStmt.WithTrailingTrivia(ancestor.GetTrailingTrivia()) }); } else { newRoot = root.InsertNodesAfter(ancestor, new[] { foreachStmt.WithTrailingTrivia(ancestor.GetTrailingTrivia()) }); } return Task.FromResult(document.WithSyntaxRoot(newRoot)); } ); }