private async Task <Document> CreateFieldAsync(CodeRefactoringContext context, ParameterSyntax parameter, string paramName, string fieldName, CancellationToken cancellationToken) { var oldConstructor = parameter.Ancestors().OfType <ConstructorDeclarationSyntax>().First(); var newConstructor = oldConstructor.WithBody(oldConstructor.Body.AddStatements( SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(fieldName), SyntaxFactory.IdentifierName(paramName))))); var oldClass = parameter.FirstAncestorOrSelf <ClassDeclarationSyntax>(); var oldClassWithNewCtor = oldClass.ReplaceNode(oldConstructor, newConstructor); var fieldDeclaration = RoslynHelpers.CreateFieldDeclaration(RoslynHelpers.GetParameterType(parameter), fieldName); var newClass = oldClassWithNewCtor .WithMembers(oldClassWithNewCtor.Members.Insert(0, fieldDeclaration)) .WithAdditionalAnnotations(Formatter.Annotation); var oldRoot = await context.Document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newRoot = oldRoot.ReplaceNode(oldClass, newClass); return(context.Document.WithSyntaxRoot(newRoot)); }
private async Task <Document> CreateFieldAsync(CodeRefactoringContext context, ParameterSyntax parameter, string paramName, CancellationToken cancellationToken, bool useUnderscore = false) { var guard = CreateGuard(context, paramName, useUnderscore); var oldConstructor = parameter.Ancestors().OfType <ConstructorDeclarationSyntax>().First(); var newConstructor = oldConstructor.WithBody(oldConstructor.Body.AddStatements( guard)); var oldClass = parameter.FirstAncestorOrSelf <ClassDeclarationSyntax>(); var oldClassWithNewCtor = oldClass.ReplaceNode(oldConstructor, newConstructor); var fieldDeclaration = CreateFieldDeclaration(GetParameterType(parameter), paramName, useUnderscore); var lastFieldDeclaration = oldClassWithNewCtor.Members.OfType <FieldDeclarationSyntax>().LastOrDefault(); var newClassMembers = oldClassWithNewCtor.Members; if (lastFieldDeclaration == null) { newClassMembers = oldClassWithNewCtor.Members.Insert(0, fieldDeclaration); } else { newClassMembers = oldClassWithNewCtor.Members.Insert(oldClassWithNewCtor.Members.IndexOf(lastFieldDeclaration) + 1, fieldDeclaration); } var newClass = oldClassWithNewCtor .WithMembers(newClassMembers) .WithAdditionalAnnotations(Formatter.Annotation); var oldRoot = await context.Document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newRoot = oldRoot.ReplaceNode(oldClass, newClass); return(context.Document.WithSyntaxRoot(newRoot)); }
private static int CountArgumentSyntaxes(ParameterSyntax parameter) { var count = 0; foreach (var ancestor in parameter.Ancestors()) { switch (ancestor) { case ArgumentSyntax a: { if (a.ChildNodes().OfType <SimpleLambdaExpressionSyntax>().Any()) { count++; } break; } case ExpressionStatementSyntax _: case MethodDeclarationSyntax _: { // we do not need to look up further, so we can speed up search when done project- or solution-wide break; } } } return(count); }
private async Task <bool> ParameterIsUsedInNonInFriendlyManner(ParameterSyntax parameter, Document document, CancellationToken token) { if (!document.SupportsSemanticModel) { // Don't have a semantic model. Not sure what to do in this case. return(false); } var semanticModel = await document.GetSemanticModelAsync(token); var paramSymbol = semanticModel.GetDeclaredSymbol(parameter); var references = await SymbolFinder.FindReferencesAsync(paramSymbol, document.Project.Solution, token).ConfigureAwait(false); var syntaxRoot = await document.GetSyntaxRootAsync(token).ConfigureAwait(false); var method = parameter.Ancestors().OfType <MethodDeclarationSyntax>().FirstOrDefault(); if (method == null) { Debug.Assert(false, "Can'tfind method for the parameter"); return(false); } foreach (var reference in references) { var location = reference.Locations.FirstOrDefault(); if (location.Location != null) { var node = syntaxRoot.FindNode(location.Location.SourceSpan); if (node.Parent is ArgumentSyntax arg && (arg.RefKindKeyword.Kind() == SyntaxKind.OutKeyword || arg.RefKindKeyword.Kind() == SyntaxKind.RefKeyword)) { // Parameter used as out/ref argument and can not be changed to 'in'. return(true); } foreach (var parent in node.Ancestors()) { if (parent.Equals(method)) { break; } var kind = parent.Kind(); if (kind == SyntaxKind.ParenthesizedLambdaExpression || kind == SyntaxKind.SimpleLambdaExpression || kind == SyntaxKind.AnonymousMethodExpression) { return(true); } } } } return(false); }
private async Task <Document> CreateInitilizeFieldAsync(Document document, ParameterSyntax parameter, string underscoreName, CancellationToken cancellationToken) { var oldClass = parameter.Ancestors() .OfType <ClassDeclarationSyntax>() .First(); var oldConstructor = parameter.Ancestors() .OfType <ConstructorDeclarationSyntax>() .First(); StatementSyntax initilizationStatement = SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(underscoreName), SyntaxFactory.IdentifierName(parameter.Identifier))); var newConstructor = oldConstructor.WithBody( oldConstructor.Body.AddStatements(initilizationStatement)); var classWithNewConstructor = oldClass.ReplaceNode(oldConstructor, newConstructor); var newFieldDeclaration = SyntaxFactory.FieldDeclaration(SyntaxFactory.VariableDeclaration(parameter.Type)) .WithModifiers(SyntaxFactory.TokenList( SyntaxFactory.Token(SyntaxKind.PrivateKeyword), SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword))) .WithAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.VariableDeclarator(underscoreName))); var fieldDeclaration = classWithNewConstructor.Members .OfType <FieldDeclarationSyntax>() .ToList(); fieldDeclaration.Add(newFieldDeclaration); var classWithNewConstructorAndField = classWithNewConstructor.AddMembers(newFieldDeclaration); var oldRoot = await document.GetSyntaxRootAsync(cancellationToken) .ConfigureAwait(false); var newRoot = oldRoot.ReplaceNode(oldClass, classWithNewConstructorAndField); return(document.WithSyntaxRoot(newRoot)); }
private async Task <Document> CreateFieldAsync( CodeRefactoringContext context, ParameterSyntax parameter, string paramName, string fieldName, CancellationToken cancellationToken) { var oldConstructor = parameter .Ancestors() .OfType <ConstructorBlockSyntax>() .First(); ExpressionSyntax expression = CreateAssignmentExpression(paramName); var constructorBody = SyntaxFactory.AssignmentStatement( SyntaxKind.SimpleAssignmentStatement, SyntaxFactory.IdentifierName(fieldName), SyntaxFactory.Token(SyntaxKind.EqualsToken), expression); var newConstructor = oldConstructor.AddStatements(constructorBody); var oldClass = parameter.FirstAncestorOrSelf <ClassBlockSyntax>(); var oldClassWithNewCtor = oldClass.ReplaceNode(oldConstructor, newConstructor); var fieldDeclaration = CreateFieldDeclaration(RoslynHelpers.GetParameterType(parameter), fieldName); fieldDeclaration = fieldDeclaration.WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed); var members = oldClassWithNewCtor.Members.Insert(0, fieldDeclaration); var newClass = oldClassWithNewCtor .WithMembers(members) .WithAdditionalAnnotations(Formatter.Annotation); var oldRoot = await context.Document .GetSyntaxRootAsync(cancellationToken) .ConfigureAwait(false); var newRoot = oldRoot.ReplaceNode(oldClass, newClass); return(context.Document.WithSyntaxRoot(newRoot)); }
public static SyntaxNode GetParentMethodBody(this ParameterSyntax parameter) { var parentMethod = parameter.Ancestors().FirstOrDefault(n => n is SimpleLambdaExpressionSyntax || n is BaseMethodDeclarationSyntax || n is ParenthesizedLambdaExpressionSyntax); if (parentMethod is BaseMethodDeclarationSyntax) { return(((BaseMethodDeclarationSyntax)parentMethod).Body); } else if (parentMethod is SimpleLambdaExpressionSyntax) { return(((SimpleLambdaExpressionSyntax)parentMethod).Body); } else if (parentMethod is ParenthesizedLambdaExpressionSyntax) { return(((ParenthesizedLambdaExpressionSyntax)parentMethod).Body); } else { throw new InvalidOperationException("Unhandled expression syntax."); } }
private static async Task <bool> ParameterIsUsedInNonInFriendlyMannerAsync(ParameterSyntax parameter, Document document, CancellationToken token) { if (!document.SupportsSemanticModel) { // Don't have a semantic model. Not sure what to do in this case, so avoid showing the code fix. return(true); } var semanticModel = await document.GetSemanticModelAsync(token).ConfigureAwait(false); var paramSymbol = semanticModel.GetDeclaredSymbol(parameter); var references = await SymbolFinder.FindReferencesAsync(paramSymbol, document.Project.Solution, token).ConfigureAwait(false); var syntaxRoot = await document.GetSyntaxRootAsync(token).ConfigureAwait(false); var method = parameter.Ancestors().OfType <MethodDeclarationSyntax>().FirstOrDefault(); if (syntaxRoot == null || method == null) { // Don't have a method (could be an indexer). This is not yet supported, so avoid showing the code fix. return(true); } foreach (var reference in references) { var location = reference.Locations.FirstOrDefault(); if (location.Location != null) { // The reference could be easily outside of the current syntax tree. // For instance, it may be in a partial class? if (!syntaxRoot.FullSpan.Contains(location.Location.SourceSpan)) { continue; } var node = syntaxRoot.FindNode(location.Location.SourceSpan); if (node.Parent is ArgumentSyntax arg && (arg.RefKindKeyword.Kind() == SyntaxKind.OutKeyword || arg.RefKindKeyword.Kind() == SyntaxKind.RefKeyword)) { // Parameter used as out/ref argument and can not be changed to 'in'. return(true); } foreach (var parent in node.Ancestors()) { if (parent.Equals(method)) { break; } var kind = parent.Kind(); if (kind == SyntaxKind.ParenthesizedLambdaExpression || kind == SyntaxKind.SimpleLambdaExpression || kind == SyntaxKind.AnonymousMethodExpression) { return(true); } } } } return(false); }