public static SyntaxNode IntroduceFieldFromConstructorAsync(SyntaxNode root, ConstructorDeclarationSyntax constructorStatement, ParameterSyntax parameter)
        {
            var oldClass     = constructorStatement.FirstAncestorOrSelf <ClassDeclarationSyntax>();
            var newClass     = oldClass;
            var fieldMembers = oldClass.Members.OfType <FieldDeclarationSyntax>();
            var fieldName    = parameter.Identifier.ValueText;

            if (!fieldMembers.Any(p => p.Declaration.Variables.First().Identifier.Text == fieldName && p.Declaration.Type.ToString() == parameter.Type.ToString()))
            {
                var identifierPostFix = 0;
                while (fieldMembers.Any(p => p.Declaration.Variables.Any(d => d.Identifier.Text == fieldName)))
                {
                    fieldName = parameter.Identifier.ValueText + ++identifierPostFix;
                }
                var newField = SyntaxFactory.FieldDeclaration(SyntaxFactory.VariableDeclaration(parameter.Type)
                                                              .WithVariables(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(fieldName)))))
                               .WithModifiers(SyntaxFactory.TokenList(new[] { SyntaxFactory.Token(SyntaxKind.PrivateKeyword), SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword) }))
                               .WithAdditionalAnnotations(Formatter.Annotation);
                newClass = newClass.WithMembers(newClass.Members.Insert(0, newField)).WithoutAnnotations(Formatter.Annotation);
            }
            var assignmentField = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                                                                       SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(),
                                                                                                                                            SyntaxFactory.IdentifierName(fieldName)), SyntaxFactory.IdentifierName(parameter.Identifier.ValueText)));
            var newConstructor = constructorStatement.WithBody(constructorStatement.Body.AddStatements(assignmentField));

            newClass = newClass.ReplaceNode(newClass.DescendantNodes().OfType <ConstructorDeclarationSyntax>().First(), newConstructor);
            var newRoot = root.ReplaceNode(oldClass, newClass);

            return(newRoot);
        }
        public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node)
        {
            var containingTypeSyntax = node.FirstAncestorOrSelf <TypeDeclarationSyntax>();
            var methodSymbol         = this.SemanticModel.GetDeclaredSymbol(node);

            this.ProcessMethodDecl(node, containingTypeSyntax, methodSymbol);
            base.VisitConstructorDeclaration(node);
        }
        public CodeRefactoring GetRefactoring(IDocument document, TextSpan textSpan, CancellationToken cancellationToken)
        {
            SyntaxNode  root  = (SyntaxNode)document.GetSyntaxRoot(cancellationToken);
            SyntaxToken token = root.FindToken(textSpan.Start, findInsideTrivia: true);

            // Verify is the selected token an identifier
            if (token.Kind == SyntaxKind.IdentifierToken && token.Span.Start <= textSpan.End && textSpan.End <= token.Span.End)
            {
                ISemanticModel   model      = document.GetSemanticModel(cancellationToken);
                CommonSyntaxNode parentNode = token.Parent;

                // Verify that the selected node is an identifier of constructor
                if (!(parentNode is ConstructorDeclarationSyntax))
                {
                    return(null);
                }

                ConstructorDeclarationSyntax ctorDeclaration = (ConstructorDeclarationSyntax)parentNode;

                if (ctorDeclaration.HasDiagnostics)
                {
                    return(null);
                }

                // This refactoring does not apply to static constructors
                if (ctorDeclaration.Modifiers.Any(m => m.Kind == SyntaxKind.StaticKeyword))
                {
                    return(null);
                }

                // Get the containing type
                ClassDeclarationSyntax typeDeclaration = ctorDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>();

                if (typeDeclaration == null)
                {
                    return(null);
                }

                return(new CodeRefactoring(
                           new[] { new ReplaceConstructorWithFactoryMethodAction(document, ctorDeclaration, typeDeclaration) },
                           token.Span));
            }

            return(null);
        }
예제 #4
0
        private async Task <ConstructorDeclarationSyntax> DocumentConstructorAsync(CodeFixContext context, ConstructorDeclarationSyntax constructor, CancellationToken cancellationToken)
        {
            if (constructor == null)
            {
                return(null);
            }

            SemanticModel semanticModel = await context.Document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            INamedTypeSymbol apiCallClass  = semanticModel.GetDeclaredSymbol(constructor.FirstAncestorOrSelf <ClassDeclarationSyntax>(), cancellationToken);
            string           parameterName = constructor.ParameterList.Parameters[0].Identifier.ValueText;

            DocumentationCommentTriviaSyntax documentationComment = XmlSyntaxFactory.DocumentationComment(
                XmlSyntaxFactory.SummaryElement(
                    XmlSyntaxFactory.Text("Initializes a new instance of the "),
                    XmlSyntaxFactory.SeeElement(SyntaxFactory.TypeCref(SyntaxFactory.ParseTypeName(apiCallClass.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)))),
                    XmlSyntaxFactory.Text(" class"),
                    XmlSyntaxFactory.NewLine(),
                    XmlSyntaxFactory.Text("with the behavior provided by another "),
                    XmlSyntaxFactory.SeeElement(SyntaxFactory.TypeCref(SyntaxFactory.ParseTypeName("global::OpenStack.Net.IHttpApiCall<T>"))),
                    XmlSyntaxFactory.Text(" instance.")),
                XmlSyntaxFactory.NewLine(),
                XmlSyntaxFactory.ParamElement(
                    parameterName,
                    XmlSyntaxFactory.List(
                        XmlSyntaxFactory.Text("The "),
                        XmlSyntaxFactory.SeeElement(SyntaxFactory.TypeCref(SyntaxFactory.ParseTypeName("global::OpenStack.Net.IHttpApiCall<T>"))),
                        XmlSyntaxFactory.Text(" providing the behavior for the API call."))),
                XmlSyntaxFactory.NewLine(),
                XmlSyntaxFactory.ExceptionElement(
                    SyntaxFactory.TypeCref(SyntaxFactory.ParseTypeName("global::System.ArgumentNullException")),
                    XmlSyntaxFactory.List(
                        XmlSyntaxFactory.Text("If "),
                        XmlSyntaxFactory.ParamRefElement(parameterName),
                        XmlSyntaxFactory.Text(" is "),
                        XmlSyntaxFactory.NullKeywordElement(),
                        XmlSyntaxFactory.Text("."))))
                                                                    .WithAdditionalAnnotations(Simplifier.Annotation);

            SyntaxTrivia documentationTrivia = SyntaxFactory.Trivia(documentationComment);

            return(constructor.WithLeadingTrivia(constructor.GetLeadingTrivia().Add(documentationTrivia)));
        }
        public static SyntaxNode IntroduceFieldFromConstructor(SyntaxNode root, ConstructorDeclarationSyntax constructorStatement, ParameterSyntax parameter)
        {
            // There are no constructors in interfaces, therefore all types remaining type (class and struct) are fine.
            var oldType   = constructorStatement.FirstAncestorOrSelf <TypeDeclarationSyntax>();
            var newType   = oldType;
            var fieldName = parameter.Identifier.ValueText;
            var fieldType = parameter.Type;
            var members   = ExtractMembersFromClass(oldType.Members);

            var addMember = false;

            if (!members.Any(p => p.Key == fieldName && p.Value == fieldType.ToString()))
            {
                var identifierPostFix = 0;
                while (members.Any(p => p.Key == fieldName))
                {
                    fieldName = parameter.Identifier.ValueText + ++identifierPostFix;
                }

                addMember = true;
            }

            var assignmentField = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                                                                       SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(),
                                                                                                                                            SyntaxFactory.IdentifierName(fieldName)), SyntaxFactory.IdentifierName(parameter.Identifier.ValueText)));
            var newConstructor = constructorStatement.WithBody(constructorStatement.Body.AddStatements(assignmentField));

            newType = newType.ReplaceNode(constructorStatement, newConstructor);

            if (addMember)
            {
                var newField = SyntaxFactory.FieldDeclaration(SyntaxFactory.VariableDeclaration(parameter.Type)
                                                              .WithVariables(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(fieldName)))))
                               .WithModifiers(SyntaxFactory.TokenList(new[] { SyntaxFactory.Token(SyntaxKind.PrivateKeyword), SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword) }))
                               .WithAdditionalAnnotations(Formatter.Annotation);
                newType = newType.WithMembers(newType.Members.Insert(0, newField)).WithoutAnnotations(Formatter.Annotation);
            }
            var newRoot = root.ReplaceNode(oldType, newType);

            return(newRoot);
        }