public static async Task <Document> RefactorAsync( Document document, MemberDeclarationSyntax member, CancellationToken cancellationToken = default) { MemberDeclarationSyntax newMember = member; SyntaxToken identifier = GetIdentifier(member); if (identifier != default) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); string newName = NameGenerator.Default.EnsureUniqueName(identifier.ValueText, semanticModel, member.SpanStart); ISymbol symbol = semanticModel.GetDeclaredSymbol(member, cancellationToken); ImmutableArray <SyntaxNode> references = await SyntaxFinder.FindReferencesAsync(symbol, document.Solution(), documents : ImmutableHashSet.Create(document), cancellationToken : cancellationToken).ConfigureAwait(false); SyntaxToken newIdentifier = SyntaxFactory.Identifier(newName); newMember = member.ReplaceNodes( references.Where(n => member.Contains(n)), (n, _) => { if (n is IdentifierNameSyntax identifierName) { return(identifierName.WithIdentifier(newIdentifier.WithTriviaFrom(identifierName.Identifier))); } else { Debug.Fail(n.Kind().ToString()); return(n); } }); newMember = SetIdentifier(newMember, newIdentifier.WithRenameAnnotation()); } else { newMember = newMember.WithNavigationAnnotation(); } MemberDeclarationListInfo memberList = SyntaxInfo.MemberDeclarationListInfo(member.Parent); int index = memberList.IndexOf(member); if (index == 0) { SyntaxToken?openBrace = memberList.OpenBraceToken; if (openBrace != null && openBrace.Value.GetFullSpanEndLine() == member.GetFullSpanStartLine()) { newMember = newMember.WithLeadingTrivia(member.GetLeadingTrivia().Insert(0, NewLine())); } } return(await document.ReplaceMembersAsync(memberList, memberList.Members.Insert(index + 1, newMember), cancellationToken).ConfigureAwait(false)); }
public static async Task <Solution> RefactorAsync( Document document, PropertyDeclarationSyntax property, CancellationToken cancellationToken = default) { Solution solution = document.Solution(); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(property, cancellationToken); string methodName = GetMethodName(property); ImmutableArray <DocumentReferenceInfo> infos = await SyntaxFinder.FindReferencesByDocumentAsync(propertySymbol, solution, allowCandidate : false, cancellationToken : cancellationToken).ConfigureAwait(false); foreach (DocumentReferenceInfo info in infos) { var rewriter = new ReplacePropertyWithMethodSyntaxRewriter(info.References, methodName, property); SyntaxNode newRoot = rewriter.Visit(info.Root); solution = solution.WithDocumentSyntaxRoot(info.Document.Id, newRoot); } if (!infos.Any(f => f.Document.Id == document.Id)) { SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxNode newRoot = root.ReplaceNode(property, ToMethodDeclaration(property)); solution = solution.WithDocumentSyntaxRoot(document.Id, newRoot); } return(solution); }
private static async Task <bool> IsElementAccessAsync( RefactoringContext context, ForStatementSyntax forStatement, VariableDeclaratorSyntax variableDeclarator, ExpressionSyntax memberAccessExpression) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol symbol = semanticModel.GetSymbol(memberAccessExpression, context.CancellationToken); if (symbol != null) { ISymbol variableSymbol = semanticModel.GetDeclaredSymbol(variableDeclarator, context.CancellationToken); ImmutableArray <SyntaxNode> nodes = await SyntaxFinder.FindReferencesAsync(variableSymbol, context.Document, cancellationToken : context.CancellationToken).ConfigureAwait(false); StatementSyntax statement = forStatement.Statement; return(nodes .Where(f => statement.Span.Contains(f.Span)) .All(node => IsElementAccess(node, symbol, semanticModel, context.CancellationToken))); } return(true); }
public static async Task <Document> RefactorAsync( Document document, ForStatementSyntax forStatement, CancellationToken cancellationToken = default) { StatementSyntax statement = forStatement.Statement; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); string name = NameGenerator.Default.EnsureUniqueLocalName( DefaultNames.ForEachVariable, semanticModel, statement.SpanStart, cancellationToken: cancellationToken); IdentifierNameSyntax identifierName = IdentifierName(name); var condition = (BinaryExpressionSyntax)forStatement.Condition; var memberAccessExpression = (MemberAccessExpressionSyntax)condition.Right; ExpressionSyntax expression = memberAccessExpression.Expression; ISymbol symbol = semanticModel.GetDeclaredSymbol(forStatement.Declaration.Variables[0], cancellationToken); ImmutableArray <SyntaxNode> nodes = await SyntaxFinder.FindReferencesAsync(symbol, document, cancellationToken : cancellationToken).ConfigureAwait(false); StatementSyntax newStatement = statement.ReplaceNodes( nodes.Select(f => f.Parent.Parent.Parent), (f, _) => identifierName.WithTriviaFrom(f)); TypeSyntax type = VarType(); if (semanticModel.GetTypeSymbol(expression, cancellationToken) is INamedTypeSymbol namedType && !namedType.OriginalDefinition.Implements(SpecialType.System_Collections_Generic_IEnumerable_T, allInterfaces: true)) { IPropertySymbol member = namedType.FindMember <IPropertySymbol>( "this[]", f => f.Parameters.SingleOrDefault(shouldThrow: false)?.Type.SpecialType == SpecialType.System_Int32, includeBaseTypes: true); Debug.Assert(member != null, ""); if (member != null) { type = member.Type.ToTypeSyntax().WithSimplifierAnnotation(); } } ForEachStatementSyntax forEachStatement = ForEachStatement( type, Identifier(name).WithRenameAnnotation(), expression, newStatement); forEachStatement = forEachStatement .WithTriviaFrom(forStatement) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(forStatement, forEachStatement, cancellationToken).ConfigureAwait(false)); }
public static async Task <Document> RefactorAsync( Document document, PropertyDeclarationSyntax propertyDeclaration, bool prefixIdentifierWithUnderscore = true, CancellationToken cancellationToken = default(CancellationToken)) { string fieldName = StringUtility.ToCamelCase( propertyDeclaration.Identifier.ValueText, prefixWithUnderscore: prefixIdentifierWithUnderscore); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); fieldName = NameGenerator.Default.EnsureUniqueMemberName( fieldName, semanticModel, propertyDeclaration.SpanStart, cancellationToken: cancellationToken); FieldDeclarationSyntax fieldDeclaration = CreateBackingField(propertyDeclaration, fieldName) .WithFormatterAnnotation(); PropertyDeclarationSyntax newPropertyDeclaration = ExpandPropertyAndAddBackingField(propertyDeclaration, fieldName); newPropertyDeclaration = ExpandPropertyRefactoring.ReplaceAbstractWithVirtual(newPropertyDeclaration); newPropertyDeclaration = newPropertyDeclaration .WithTriviaFrom(propertyDeclaration) .WithFormatterAnnotation(); var parentMember = (MemberDeclarationSyntax)propertyDeclaration.Parent; SyntaxList <MemberDeclarationSyntax> members = parentMember.GetMembers(); int propertyIndex = members.IndexOf(propertyDeclaration); if (IsReadOnlyAutoProperty(propertyDeclaration)) { IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken); ImmutableArray <SyntaxNode> nodes = await SyntaxFinder.FindReferencesAsync(propertySymbol, document, cancellationToken : cancellationToken).ConfigureAwait(false); IdentifierNameSyntax newNode = IdentifierName(fieldName); MemberDeclarationSyntax newParentMember = parentMember.ReplaceNodes(nodes, (f, g) => newNode.WithTriviaFrom(f)); members = newParentMember.GetMembers(); } SyntaxList <MemberDeclarationSyntax> newMembers = members.ReplaceAt(propertyIndex, newPropertyDeclaration); newMembers = newMembers.InsertMember(fieldDeclaration, MemberDeclarationComparer.ByKind); return(await document.ReplaceNodeAsync(parentMember, parentMember.WithMembers(newMembers), cancellationToken).ConfigureAwait(false)); }
public static async Task <Document> RefactorAsync( Document document, PropertyDeclarationSyntax propertyDeclaration, bool prefixIdentifierWithUnderscore = true, CancellationToken cancellationToken = default(CancellationToken)) { string fieldName = StringUtility.ToCamelCase( propertyDeclaration.Identifier.ValueText, prefixWithUnderscore: prefixIdentifierWithUnderscore); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); fieldName = NameGenerator.Default.EnsureUniqueMemberName( fieldName, semanticModel, propertyDeclaration.SpanStart, cancellationToken: cancellationToken); FieldDeclarationSyntax fieldDeclaration = CreateBackingField(propertyDeclaration, fieldName) .WithFormatterAnnotation(); PropertyDeclarationSyntax newPropertyDeclaration = ExpandPropertyAndAddBackingField(propertyDeclaration, fieldName); newPropertyDeclaration = newPropertyDeclaration .WithModifiers(newPropertyDeclaration.Modifiers.Replace(SyntaxKind.AbstractKeyword, SyntaxKind.VirtualKeyword)) .WithTriviaFrom(propertyDeclaration) .WithFormatterAnnotation(); MemberDeclarationListInfo info = SyntaxInfo.MemberDeclarationListInfo(propertyDeclaration.Parent); SyntaxList <MemberDeclarationSyntax> members = info.Members; int propertyIndex = info.IndexOf(propertyDeclaration); if (IsReadOnlyAutoProperty(propertyDeclaration)) { IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken); ImmutableArray <SyntaxNode> nodes = await SyntaxFinder.FindReferencesAsync(propertySymbol, document, cancellationToken : cancellationToken).ConfigureAwait(false); IdentifierNameSyntax newNode = IdentifierName(fieldName); MemberDeclarationListInfo newInfo = SyntaxInfo.MemberDeclarationListInfo(info.Parent.ReplaceNodes(nodes, (f, _) => newNode.WithTriviaFrom(f))); members = newInfo.Members; } SyntaxList <MemberDeclarationSyntax> newMembers = members.ReplaceAt(propertyIndex, newPropertyDeclaration); newMembers = MemberDeclarationInserter.Default.Insert(newMembers, fieldDeclaration); return(await document.ReplaceMembersAsync(info, newMembers, cancellationToken).ConfigureAwait(false)); }
public static async Task <Document> RefactorAsync( Document document, ForStatementSyntax forStatement, CancellationToken cancellationToken = default(CancellationToken)) { StatementSyntax statement = forStatement.Statement; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); string name = NameGenerator.Default.EnsureUniqueLocalName( DefaultNames.ForEachVariable, semanticModel, statement.SpanStart, cancellationToken: cancellationToken); IdentifierNameSyntax identifierName = IdentifierName(name); var condition = (BinaryExpressionSyntax)forStatement.Condition; var memberAccessExpression = (MemberAccessExpressionSyntax)condition.Right; ExpressionSyntax expression = memberAccessExpression.Expression; ISymbol symbol = semanticModel.GetDeclaredSymbol(forStatement.Declaration.Variables.First(), cancellationToken); ImmutableArray <SyntaxNode> nodes = await SyntaxFinder.FindReferencesAsync(symbol, document, cancellationToken : cancellationToken).ConfigureAwait(false); StatementSyntax newStatement = statement.ReplaceNodes( nodes.Select(f => f.Parent.Parent.Parent), (f, _) => identifierName.WithTriviaFrom(f)); ForEachStatementSyntax forEachStatement = ForEachStatement( VarType(), name, expression, newStatement); forEachStatement = forEachStatement .WithTriviaFrom(forStatement) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(forStatement, forEachStatement, cancellationToken).ConfigureAwait(false)); }
public static async Task <bool> CanRefactorAsync(RefactoringContext context, ForStatementSyntax forStatement) { VariableDeclaratorSyntax variableDeclarator = forStatement .Declaration? .Variables .SingleOrDefault(shouldThrow: false); if (variableDeclarator == null) { return(false); } if (variableDeclarator.Initializer?.Value?.IsNumericLiteralExpression("0") != true) { return(false); } ExpressionSyntax condition = forStatement.Condition; if (condition?.IsKind(SyntaxKind.LessThanExpression) != true) { return(false); } ExpressionSyntax right = ((BinaryExpressionSyntax)condition).Right; if (right?.IsKind(SyntaxKind.SimpleMemberAccessExpression) != true) { return(false); } var memberAccessExpression = (MemberAccessExpressionSyntax)right; string memberName = memberAccessExpression.Name?.Identifier.ValueText; if (memberName != "Count" && memberName != "Length") { return(false); } ExpressionSyntax expression = memberAccessExpression.Expression; if (expression == null) { return(false); } if (forStatement.Incrementors.SingleOrDefault(shouldThrow: false)?.IsKind(SyntaxKind.PostIncrementExpression) != true) { return(false); } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol symbol = semanticModel.GetSymbol(expression, context.CancellationToken); if (symbol == null) { return(false); } ISymbol variableSymbol = semanticModel.GetDeclaredSymbol(variableDeclarator, context.CancellationToken); ImmutableArray <SyntaxNode> nodes = await SyntaxFinder.FindReferencesAsync(variableSymbol, context.Document, cancellationToken : context.CancellationToken).ConfigureAwait(false); TextSpan span = forStatement.Statement.Span; foreach (SyntaxNode node in nodes) { if (span.Contains(node.Span) && !IsElementAccess(node, symbol, semanticModel, context.CancellationToken)) { return(false); } } return(true); }
public static async Task <Document> RefactorAsync( Document document, PropertyDeclarationSyntax propertyDeclaration, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); SyntaxToken propertyIdentifier = propertyDeclaration.Identifier.WithoutTrivia(); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken); ISymbol fieldSymbol = GetFieldSymbol(propertyDeclaration, semanticModel, cancellationToken); var variableDeclarator = (VariableDeclaratorSyntax)await fieldSymbol.GetSyntaxAsync(cancellationToken).ConfigureAwait(false); var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent; var fieldDeclaration = (FieldDeclarationSyntax)variableDeclaration.Parent; bool isSingleDeclarator = variableDeclaration.Variables.Count == 1; ImmutableArray <SyntaxNode> nodes = await SyntaxFinder.FindReferencesAsync(fieldSymbol, document, allowCandidate : false, cancellationToken : cancellationToken).ConfigureAwait(false); nodes = nodes.Add(propertyDeclaration); if (isSingleDeclarator) { nodes = nodes.Add(fieldDeclaration); } else { nodes = nodes.Add(variableDeclarator); } SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxNode newRoot = root.ReplaceNodes(nodes, (node, _) => { switch (node.Kind()) { case SyntaxKind.IdentifierName: { SyntaxNode newNode = null; if (node.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) && ((MemberAccessExpressionSyntax)node.Parent).Name == node) { newNode = IdentifierName(propertyIdentifier); } else if (node.IsParentKind(SyntaxKind.NameMemberCref)) { newNode = IdentifierName(propertyIdentifier); } else if (propertySymbol.IsStatic) { newNode = SimpleMemberAccessExpression( propertySymbol.ContainingType.ToTypeSyntax(), (SimpleNameSyntax)ParseName(propertySymbol.ToDisplayString(SymbolDisplayFormats.Default))).WithSimplifierAnnotation(); } else { newNode = IdentifierName(propertyIdentifier).QualifyWithThis(); } return(newNode.WithTriviaFrom(node)); } case SyntaxKind.PropertyDeclaration: { return(CreateAutoProperty(propertyDeclaration, variableDeclarator.Initializer)); } case SyntaxKind.VariableDeclarator: case SyntaxKind.FieldDeclaration: { return(node.WithAdditionalAnnotations(_removeAnnotation)); } default: { Debug.Fail(node.ToString()); return(node); } } }); SyntaxNode nodeToRemove = newRoot.GetAnnotatedNodes(_removeAnnotation).FirstOrDefault(); if (nodeToRemove != null) { newRoot = newRoot.RemoveNode(nodeToRemove, SyntaxRemoveOptions.KeepUnbalancedDirectives); } return(document.WithSyntaxRoot(newRoot)); }
public static async Task <Solution> RefactorAsync( Document document, PropertyDeclarationSyntax propertyDeclaration, CancellationToken cancellationToken) { SyntaxToken propertyIdentifier = propertyDeclaration.Identifier.WithoutTrivia(); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken); ISymbol fieldSymbol = GetFieldSymbol(propertyDeclaration, semanticModel, cancellationToken); var variableDeclarator = (VariableDeclaratorSyntax)await fieldSymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false); var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent; var fieldDeclaration = (FieldDeclarationSyntax)variableDeclaration.Parent; bool isSingleDeclarator = variableDeclaration.Variables.Count == 1; Solution solution = document.Solution(); foreach (DocumentReferenceInfo info in await SyntaxFinder.FindReferencesByDocumentAsync(fieldSymbol, solution, allowCandidate: false, cancellationToken: cancellationToken).ConfigureAwait(false)) { ImmutableArray <SyntaxNode> nodes = info.References; if (propertyDeclaration.SyntaxTree == info.SyntaxTree) { nodes = nodes.Add(propertyDeclaration); if (isSingleDeclarator) { nodes = nodes.Add(fieldDeclaration); } else { nodes = nodes.Add(variableDeclarator); } } SyntaxNode newRoot = info.Root.ReplaceNodes(nodes, (node, rewrittenNode) => { switch (node.Kind()) { case SyntaxKind.IdentifierName: { return(CreateNewExpression(node, propertyIdentifier, propertySymbol) .WithTriviaFrom(node) .WithFormatterAnnotation()); } case SyntaxKind.PropertyDeclaration: { return(CreateAutoProperty(propertyDeclaration, variableDeclarator.Initializer)); } case SyntaxKind.VariableDeclarator: case SyntaxKind.FieldDeclaration: { return(node.WithAdditionalAnnotations(_removeAnnotation)); } default: { Debug.Fail(node.ToString()); return(node); } } }); SyntaxNode nodeToRemove = newRoot.GetAnnotatedNodes(_removeAnnotation).FirstOrDefault(); if (nodeToRemove != null) { newRoot = newRoot.RemoveNode(nodeToRemove, SyntaxRemoveOptions.KeepUnbalancedDirectives); } solution = solution.WithDocumentSyntaxRoot(info.Document.Id, newRoot); } return(solution); }
public static async Task <Document> RefactorAsync( Document document, PropertyDeclarationSyntax propertyDeclaration, bool prefixIdentifierWithUnderscore = true, CancellationToken cancellationToken = default) { string fieldName = StringUtility.ToCamelCase( propertyDeclaration.Identifier.ValueText, prefixWithUnderscore: prefixIdentifierWithUnderscore); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); fieldName = NameGenerator.Default.EnsureUniqueName( fieldName, semanticModel, propertyDeclaration.SpanStart); FieldDeclarationSyntax fieldDeclaration = FieldDeclaration( (propertyDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword)) ? Modifiers.Private_Static() : Modifiers.Private(), propertyDeclaration.Type, fieldName, propertyDeclaration.Initializer).WithFormatterAnnotation(); IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken); PropertyDeclarationSyntax newPropertyDeclaration = ExpandAccessors(document, propertyDeclaration, propertySymbol, fieldName, semanticModel) .WithModifiers(propertyDeclaration.Modifiers.Replace(SyntaxKind.AbstractKeyword, SyntaxKind.VirtualKeyword)) .WithTriviaFrom(propertyDeclaration) .WithFormatterAnnotation(); MemberDeclarationListInfo membersInfo = SyntaxInfo.MemberDeclarationListInfo(propertyDeclaration.Parent); SyntaxList <MemberDeclarationSyntax> members = membersInfo.Members; int propertyIndex = membersInfo.IndexOf(propertyDeclaration); AccessorListSyntax accessorList = propertyDeclaration.AccessorList; if (accessorList?.Getter()?.IsAutoImplemented() == true && accessorList.Setter() == null) { ImmutableArray <SyntaxNode> nodes = await SyntaxFinder.FindReferencesAsync(propertySymbol, document, cancellationToken : cancellationToken).ConfigureAwait(false); IdentifierNameSyntax newNode = IdentifierName(fieldName); SyntaxNode newParent = membersInfo.Parent.ReplaceNodes(nodes, (node, _) => { if (node.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) && ((MemberAccessExpressionSyntax)node.Parent).Expression.IsKind(SyntaxKind.BaseExpression)) { return(node); } return(newNode.WithTriviaFrom(node)); }); MemberDeclarationListInfo newMembersInfo = SyntaxInfo.MemberDeclarationListInfo(newParent); members = newMembersInfo.Members; } SyntaxList <MemberDeclarationSyntax> newMembers = members.ReplaceAt(propertyIndex, newPropertyDeclaration); newMembers = MemberDeclarationInserter.Default.Insert(newMembers, fieldDeclaration); return(await document.ReplaceMembersAsync(membersInfo, newMembers, cancellationToken).ConfigureAwait(false)); }