예제 #1
0
        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));
        }
예제 #2
0
        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));
        }
예제 #3
0
        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);
        }
예제 #4
0
        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));
        }
예제 #6
0
        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));
        }
예제 #7
0
        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);
        }