Example #1
0
        public ClassComposer AddProperty(PropertyOptions options)
        {
            if (!IsAtRoot())
            {
                throw new Exception("A class must be selected (which is also a root to the composer) to add a field to it.");
            }

            PropertyDeclarationSyntax @property = SyntaxFactory
                                                  .PropertyDeclaration(SyntaxFactory.ParseTypeName(options.PropertyType), options.PropertyName)
                                                  .WithModifiers(options.ModifiersToTokenList());

            @property = @property.AddAccessorListAccessors(
                SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)
                                    ));
            @property = @property.AddAccessorListAccessors(
                SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)
                                    ));

            var newNode = (CurrentNode as ClassDeclarationSyntax).AddMembers(@property);

            Replace(CurrentNode, newNode, null);

            return(this);
        }
        private async Task <Document> AddBackingFieldAsync(Document document, SyntaxNode equalsSyntax, CancellationToken cancellationToken)
        {
            var pds = equalsSyntax as PropertyDeclarationSyntax;

            var propName = pds.Identifier.ToString();

            var fieldName = "_" + char.ToLowerInvariant(propName[0]) + propName.Substring(1);

            var fieldType = pds.GetTypeName();

            var backingField = SyntaxFactory.FieldDeclaration(
                SyntaxFactory.VariableDeclaration(
                    SyntaxFactory.ParseTypeName(fieldType),
                    SyntaxFactory.SeparatedList(
                        new[]
            {
                SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(fieldName)),
            })))
                               .AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword));

            PropertyDeclarationSyntax newProperty =
                SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(fieldType), propName)
                .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword));

            newProperty = newProperty.AddAccessorListAccessors(
                SyntaxFactory.AccessorDeclaration(
                    SyntaxKind.GetAccessorDeclaration,
                    SyntaxFactory.Block(
                        SyntaxFactory.List(new[]
            {
                SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(fieldName)),
            }))));

            var setCall = SyntaxFactory.ExpressionStatement(
                SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName("SetProperty"))
                .AddArgumentListArguments(
                    SyntaxFactory.Argument(SyntaxFactory.IdentifierName(fieldName))
                    .WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.RefKeyword)),
                    SyntaxFactory.Argument(SyntaxFactory.IdentifierName("value"))));

            newProperty = newProperty.AddAccessorListAccessors(
                SyntaxFactory.AccessorDeclaration(
                    SyntaxKind.SetAccessorDeclaration,
                    SyntaxFactory.Block(SyntaxFactory.List(new[] { setCall }))));

            var oldRoot = await document.GetSyntaxRootAsync(cancellationToken);

            var newNodes = new List <SyntaxNode>
            {
                backingField,
                newProperty,
            };

            var newRoot = oldRoot.ReplaceNode(pds, newNodes);

            return(document.WithSyntaxRoot(newRoot));
        }
Example #3
0
        public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
        {
            if (node.ExplicitInterfaceSpecifier?.Name?.ToString() == nameof(IProxy))
            {
                node = node.WithExpressionBody(ArrowExpressionClause(
                                                   MemberAccessExpression(
                                                       SyntaxKind.SimpleMemberAccessExpression,
                                                       IdentifierName("pipeline"),
                                                       IdentifierName("Behaviors"))));
            }
            else
            {
                (var canRead, var canWrite) = generator.InspectProperty(node);
                canRead = canRead || node.ExpressionBody != null;

                if (node.ExpressionBody != null)
                {
                    node = node.RemoveNode(node.ExpressionBody, SyntaxRemoveOptions.KeepNoTrivia);
                }
                if (node.AccessorList?.Accessors.Any() == true)
                {
                    node = node.RemoveNodes(node.AccessorList.Accessors, SyntaxRemoveOptions.KeepNoTrivia);
                }

                if (canRead && !canWrite)
                {
                    node = node.WithExpressionBody(
                        ArrowExpressionClause(ExecutePipeline(node.Type, Enumerable.Empty <ParameterSyntax>())));
                }
                else
                {
                    if (canRead)
                    {
                        node = node.AddAccessorListAccessors(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                                                             .WithExpressionBody(ArrowExpressionClause(ExecutePipeline(node.Type, Enumerable.Empty <ParameterSyntax>())))
                                                             .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
                    }
                    if (canWrite)
                    {
                        node = node.AddAccessorListAccessors(AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                                                             .WithExpressionBody(ArrowExpressionClause(
                                                                                     // NOTE: we always append the implicit "value" parameter for setters.
                                                                                     ExecutePipeline(null, new[] { Parameter(Identifier("value")).WithType(node.Type) })))
                                                             .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
                    }
                }
            }

            return(base.VisitPropertyDeclaration(node));
        }
Example #4
0
 public static PropertyDeclarationSyntax WithGetterAndInit(
     this PropertyDeclarationSyntax property) =>
 property.AddAccessorListAccessors(
     AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
     .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
     AccessorDeclaration(SyntaxKind.InitAccessorDeclaration)
     .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
Example #5
0
        private static PropertyDeclarationSyntax PropertyBody(PropertyDeclarationSyntax prop, SyntaxKind accessorKind, object[] code)
        {
            var statements = ToStatements(code).ToList();

            if (accessorKind == SyntaxKind.GetAccessorDeclaration && !(prop.AccessorList?.Accessors.Any() ?? false) && statements.Count == 1 && statements[0] is ExpressionStatementSyntax expr)
            {
                // If this is a getter with no setter, containing a single expression, then use an expression-bodied property.
                return(prop.WithExpressionBody(ArrowExpressionClause(expr.Expression)).WithSemicolonToken(s_semicolonToken));
            }
            if (accessorKind == SyntaxKind.SetAccessorDeclaration && prop.ExpressionBody != null)
            {
                prop = prop.AddAccessorListAccessors(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithExpressionBody(prop.ExpressionBody).WithSemicolonToken(s_semicolonToken))
                       .WithExpressionBody(null);
            }
            return(WithBody(code,
                            x => prop.AddAccessorListAccessors(AccessorDeclaration(accessorKind).WithExpressionBody(x).WithSemicolonToken(s_semicolonToken)),
                            x => prop.AddAccessorListAccessors(AccessorDeclaration(accessorKind, x))));
        }
Example #6
0
            public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
            {
                if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated"))
                {
                    return(base.VisitPropertyDeclaration(node));
                }

                (var canRead, var canWrite) = generator.InspectProperty(node);
                canRead = canRead || node.ExpressionBody != null;

                if (node.ExpressionBody != null)
                {
                    node = node.RemoveNode(node.ExpressionBody, SyntaxRemoveOptions.KeepNoTrivia);
                }

                node = node.WithAccessorList(null);

                if (canRead && !canWrite)
                {
                    node = node
                           .WithExpressionBody(ArrowExpressionClause(ExecutePipeline(node.Type, Enumerable.Empty <ParameterSyntax>())))
                           .WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
                }
                else
                {
                    if (canRead)
                    {
                        node = node.AddAccessorListAccessors(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                                                             .WithExpressionBody(ArrowExpressionClause(ExecutePipeline(node.Type, Enumerable.Empty <ParameterSyntax>())))
                                                             .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
                    }
                    if (canWrite)
                    {
                        node = node.AddAccessorListAccessors(AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                                                             .WithExpressionBody(ArrowExpressionClause(
                                                                                     // NOTE: we always append the implicit "value" parameter for setters.
                                                                                     ExecutePipeline(null, new[] { Parameter(Identifier("value")).WithType(node.Type) })))
                                                             .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
                    }
                }

                return(base.VisitPropertyDeclaration(node));
            }
Example #7
0
        private CSharpSyntaxNode ToGetSet(PropertyDeclaration node)
        {
            List <Node> modifiers = node.Modifiers.FindAll(n => n.Kind != NodeKind.ReadonlyKeyword);

            PropertyDeclarationSyntax csProperty = SyntaxFactory
                                                   .PropertyDeclaration(node.Type.ToCsNode <TypeSyntax>(), node.Name.Text)
                                                   .AddModifiers(modifiers.ToCsNodes <SyntaxToken>());

            if (node.JsDoc.Count > 0)
            {
                csProperty = csProperty.WithLeadingTrivia(SyntaxFactory.Trivia(node.JsDoc[0].ToCsNode <DocumentationCommentTriviaSyntax>()));
            }

            //GetAccess
            AccessorDeclarationSyntax csGetAccess = SyntaxFactory
                                                    .AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                                                    .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken));

            //    if (node.Initializer != null)
            //    {
            //        csGetAccess = csGetAccess.WithBody(SyntaxFactory.Block(SyntaxFactory.ReturnStatement(node.Initializer.ToCsNode<ExpressionSyntax>())));
            //    }
            csProperty = csProperty.AddAccessorListAccessors(csGetAccess);

            //SetsAccess
            if ((node.IsReadonly && !node.IsAbstract) || (!node.IsReadonly))
            {
                AccessorDeclarationSyntax csSetAccess = SyntaxFactory
                                                        .AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                                                        .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken));

                if (node.IsReadonly)
                {
                    csSetAccess = csSetAccess.AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword));
                }
                csProperty = csProperty.AddAccessorListAccessors(csSetAccess);
            }

            return(csProperty);
        }
        public CSharpSyntaxNode Convert(PropertySignature node)
        {
            PropertyDeclarationSyntax csProperty = SyntaxFactory.PropertyDeclaration(node.Type.ToCsNode <TypeSyntax>(), node.Name.Text);

            if (node.Parent != null && node.Parent.Kind == NodeKind.InterfaceDeclaration)
            {
                csProperty = csProperty.AddAccessorListAccessors(SyntaxFactory
                                                                 .AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                                                                 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)));

                if (!node.HasModify(NodeKind.ReadonlyKeyword))
                {
                    csProperty = csProperty.AddAccessorListAccessors(SyntaxFactory
                                                                     .AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                                                                     .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)));
                }
            }
            if (node.JsDoc.Count > 0)
            {
                csProperty = csProperty.WithLeadingTrivia(SyntaxFactory.Trivia(node.JsDoc[0].ToCsNode <DocumentationCommentTriviaSyntax>()));
            }

            return(csProperty);
        }
Example #9
0
        public CSharpSyntaxNode Convert(SetAccessor node)
        {
            PropertyDeclarationSyntax csProperty = SyntaxFactory
                                                   .PropertyDeclaration(node.Parameters[0].Type.ToCsNode <TypeSyntax>(), node.Name.Text)
                                                   .AddModifiers(node.Modifiers.ToCsNodes <SyntaxToken>());

            if (node.JsDoc.Count > 0)
            {
                csProperty = csProperty.WithLeadingTrivia(SyntaxFactory.Trivia(node.JsDoc[0].ToCsNode <DocumentationCommentTriviaSyntax>()));
            }

            AccessorDeclarationSyntax csSetAccess = SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration);

            if (node.Body != null)
            {
                csSetAccess = csSetAccess.WithBody(node.Body.ToCsNode <BlockSyntax>());
            }

            return(csProperty.AddAccessorListAccessors(csSetAccess));
        }
Example #10
0
        private async Task <Document> ToBindablePropertyAsync(Document document, SyntaxNode equalsSyntax, CancellationToken cancellationToken)
        {
            var pds = equalsSyntax as PropertyDeclarationSyntax;

            var propName = pds.Identifier.ToString();
            var propType = pds.GetTypeName();

            var className = ((ClassDeclarationSyntax)pds.Parent).Identifier.Text;

            var bindPropName   = $"{propName}Property";
            var callbackName   = $"On{propName}Changed";
            var validationName = $"IsValid{propName}Value";

            PropertyDeclarationSyntax backingProperty =
                SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(propType), propName)
                .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword));

            var getCall =
                SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName("GetValue"))
                .AddArgumentListArguments(
                    SyntaxFactory.Argument(SyntaxFactory.IdentifierName(bindPropName)));

            var getCast = SyntaxFactory.CastExpression(
                SyntaxFactory.ParseTypeName(propType),
                SyntaxFactory.ParenthesizedExpression(getCall));

            var returnStatement = SyntaxFactory.ReturnStatement(getCast);

            backingProperty = backingProperty.AddAccessorListAccessors(
                SyntaxFactory.AccessorDeclaration(
                    SyntaxKind.GetAccessorDeclaration,
                    SyntaxFactory.Block(SyntaxFactory.List(new[] { returnStatement }))));

            var setCall = SyntaxFactory.ExpressionStatement(
                SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName("SetValue"))
                .AddArgumentListArguments(
                    SyntaxFactory.Argument(SyntaxFactory.IdentifierName(bindPropName)),
                    SyntaxFactory.Argument(SyntaxFactory.IdentifierName("value"))));

            backingProperty = backingProperty.AddAccessorListAccessors(
                SyntaxFactory.AccessorDeclaration(
                    SyntaxKind.SetAccessorDeclaration,
                    SyntaxFactory.Block(SyntaxFactory.List(new[] { setCall }))));

            var bindProperty = SyntaxFactory.FieldDeclaration(
                SyntaxFactory.VariableDeclaration(
                    SyntaxFactory.ParseTypeName("BindableProperty"),
                    SyntaxFactory.SeparatedList(
                        new[]
            {
                SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(bindPropName))
                .WithInitializer(SyntaxFactory.EqualsValueClause(
                                     SyntaxFactory.InvocationExpression(
                                         SyntaxFactory.MemberAccessExpression(
                                             SyntaxKind.SimpleMemberAccessExpression,
                                             SyntaxFactory.IdentifierName("BindableProperty"),
                                             SyntaxFactory.IdentifierName("Create")),
                                         SyntaxFactory.ArgumentList(
                                             default(SeparatedSyntaxList <ArgumentSyntax>)
                                             .Add(
                                                 SyntaxFactory.Argument(
                                                     SyntaxFactory.InvocationExpression(
                                                         SyntaxFactory.IdentifierName("nameof"))
                                                     .AddArgumentListArguments(
                                                         SyntaxFactory.Argument(SyntaxFactory.IdentifierName(propName)))))
                                             .Add(
                                                 SyntaxFactory.Argument(
                                                     SyntaxFactory.InvocationExpression(
                                                         SyntaxFactory.IdentifierName("typeof"))
                                                     .AddArgumentListArguments(
                                                         SyntaxFactory.Argument(SyntaxFactory.IdentifierName(propType)))))
                                             .Add(
                                                 SyntaxFactory.Argument(
                                                     SyntaxFactory.InvocationExpression(
                                                         SyntaxFactory.IdentifierName("typeof"))
                                                     .AddArgumentListArguments(
                                                         SyntaxFactory.Argument(SyntaxFactory.IdentifierName(className)))))
                                             .Add(
                                                 SyntaxFactory.Argument(
                                                     SyntaxFactory.DefaultExpression(SyntaxFactory.ParseTypeName(propType)))
                                                 .WithNameColon(SyntaxFactory.NameColon(SyntaxFactory.IdentifierName("defaultValue"))))
                                             .Add(
                                                 SyntaxFactory.Argument(
                                                     SyntaxFactory.MemberAccessExpression(
                                                         SyntaxKind.SimpleMemberAccessExpression,
                                                         SyntaxFactory.IdentifierName("BindingMode"),
                                                         SyntaxFactory.IdentifierName("Default")))
                                                 .WithNameColon(SyntaxFactory.NameColon(SyntaxFactory.IdentifierName("defaultBindingMode"))))
                                             .Add(
                                                 SyntaxFactory.Argument(
                                                     SyntaxFactory.IdentifierName(validationName))
                                                 .WithNameColon(SyntaxFactory.NameColon(SyntaxFactory.IdentifierName("validateValue"))))
                                             .Add(
                                                 SyntaxFactory.Argument(
                                                     SyntaxFactory.IdentifierName(callbackName))
                                                 .WithNameColon(SyntaxFactory.NameColon(SyntaxFactory.IdentifierName("propertyChanged")))))))),
            })))
                               .AddModifiers(
                SyntaxFactory.Token(SyntaxKind.PublicKeyword),
                SyntaxFactory.Token(SyntaxKind.StaticKeyword),
                SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword));

            var callbackMethod = SyntaxFactory.MethodDeclaration(
                SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword)),
                SyntaxFactory.Identifier(callbackName))
                                 .AddParameterListParameters(
                SyntaxFactory.Parameter(
                    SyntaxFactory.Identifier("bindable"))
                .WithType(SyntaxFactory.IdentifierName("BindableObject")),
                SyntaxFactory.Parameter(
                    SyntaxFactory.Identifier("oldValue"))
                .WithType(SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.ObjectKeyword))),
                SyntaxFactory.Parameter(
                    SyntaxFactory.Identifier("newValue"))
                .WithType(SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.ObjectKeyword))))
                                 .WithBody(
                SyntaxFactory.Block().WithCloseBraceToken(
                    SyntaxFactory.Token(
                        SyntaxFactory.TriviaList(
                            SyntaxFactory.Comment($"// TODO: Property changed implementation goes here{System.Environment.NewLine}")),
                        SyntaxKind.CloseBraceToken,
                        SyntaxFactory.TriviaList())))
                                 .AddModifiers(
                SyntaxFactory.Token(SyntaxKind.PrivateKeyword),
                SyntaxFactory.Token(SyntaxKind.StaticKeyword));

            var validationMethod = SyntaxFactory.MethodDeclaration(
                SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.BoolKeyword)),
                SyntaxFactory.Identifier(validationName))
                                   .AddParameterListParameters(
                SyntaxFactory.Parameter(
                    SyntaxFactory.Identifier("view"))
                .WithType(SyntaxFactory.IdentifierName("BindableObject")),
                SyntaxFactory.Parameter(
                    SyntaxFactory.Identifier("value"))
                .WithType(SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.ObjectKeyword))))
                                   .AddBodyStatements(
                SyntaxFactory.ReturnStatement(SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression))
                .WithLeadingTrivia(SyntaxFactory.Comment($"// Add logic for validating value as necessary{System.Environment.NewLine}")))
                                   .AddModifiers(
                SyntaxFactory.Token(SyntaxKind.PrivateKeyword),
                SyntaxFactory.Token(SyntaxKind.StaticKeyword));

            var newNodes = new List <SyntaxNode>
            {
                backingProperty,
                bindProperty,
                callbackMethod,
                validationMethod,
            };

            var oldRoot = await document.GetSyntaxRootAsync(cancellationToken);

            var newRoot = oldRoot.ReplaceNode(pds, newNodes);

            return(document.WithSyntaxRoot(newRoot));
        }
        private async Task <Document> ToDependencyPropertyAsync(Document document, SyntaxNode equalsSyntax, CancellationToken cancellationToken)
        {
            var pds = equalsSyntax as PropertyDeclarationSyntax;

            var propName = pds.Identifier.ToString();
            var propType = pds.GetTypeName();

            var className = ((ClassDeclarationSyntax)pds.Parent).Identifier.Text;

            var depPropName  = $"{propName}Property";
            var callbackName = $"On{propName}Changed";

            PropertyDeclarationSyntax backingProperty =
                SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(propType), propName)
                .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword));

            var getCall =
                SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName("GetValue"))
                .AddArgumentListArguments(
                    SyntaxFactory.Argument(SyntaxFactory.IdentifierName(depPropName)));

            var getCast = SyntaxFactory.CastExpression(
                SyntaxFactory.ParseTypeName(propType),
                SyntaxFactory.ParenthesizedExpression(getCall));

            var returnStatement = SyntaxFactory.ReturnStatement(getCast);

            backingProperty = backingProperty.AddAccessorListAccessors(
                SyntaxFactory.AccessorDeclaration(
                    SyntaxKind.GetAccessorDeclaration,
                    SyntaxFactory.Block(SyntaxFactory.List(new[] { returnStatement }))));

            var setCall = SyntaxFactory.ExpressionStatement(
                SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName("SetValue"))
                .AddArgumentListArguments(
                    SyntaxFactory.Argument(SyntaxFactory.IdentifierName(depPropName)),
                    SyntaxFactory.Argument(SyntaxFactory.IdentifierName("value"))));

            backingProperty = backingProperty.AddAccessorListAccessors(
                SyntaxFactory.AccessorDeclaration(
                    SyntaxKind.SetAccessorDeclaration,
                    SyntaxFactory.Block(SyntaxFactory.List(new[] { setCall }))));

            var depProperty = SyntaxFactory.FieldDeclaration(
                SyntaxFactory.VariableDeclaration(
                    SyntaxFactory.ParseTypeName("DependencyProperty"),
                    SyntaxFactory.SeparatedList(
                        new[]
            {
                SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(depPropName))
                .WithInitializer(SyntaxFactory.EqualsValueClause(
                                     SyntaxFactory.InvocationExpression(
                                         SyntaxFactory.MemberAccessExpression(
                                             SyntaxKind.SimpleMemberAccessExpression,
                                             SyntaxFactory.IdentifierName("DependencyProperty"),
                                             SyntaxFactory.IdentifierName("Register")),
                                         SyntaxFactory.ArgumentList(
                                             default(SeparatedSyntaxList <ArgumentSyntax>)
                                             .Add(
                                                 SyntaxFactory.Argument(
                                                     SyntaxFactory.LiteralExpression(
                                                         SyntaxKind.StringLiteralExpression,
                                                         SyntaxFactory.Literal(propName))))
                                             .Add(
                                                 SyntaxFactory.Argument(
                                                     SyntaxFactory.InvocationExpression(
                                                         SyntaxFactory.IdentifierName("typeof"))
                                                     .AddArgumentListArguments(
                                                         SyntaxFactory.Argument(SyntaxFactory.IdentifierName(propType)))))
                                             .Add(
                                                 SyntaxFactory.Argument(
                                                     SyntaxFactory.InvocationExpression(
                                                         SyntaxFactory.IdentifierName("typeof"))
                                                     .AddArgumentListArguments(
                                                         SyntaxFactory.Argument(SyntaxFactory.IdentifierName(className)))))
                                             .Add(
                                                 SyntaxFactory.Argument(
                                                     SyntaxFactory.ObjectCreationExpression(
                                                         SyntaxFactory.IdentifierName("PropertyMetadata"))
                                                     .AddArgumentListArguments(
                                                         SyntaxFactory.Argument(SyntaxFactory.DefaultExpression(SyntaxFactory.ParseTypeName(propType))),
                                                         SyntaxFactory.Argument(
                                                             SyntaxFactory.ObjectCreationExpression(
                                                                 SyntaxFactory.IdentifierName("PropertyChangedCallback"))
                                                             .AddArgumentListArguments(
                                                                 SyntaxFactory.Argument(SyntaxFactory.IdentifierName(callbackName))))))))))),
            })))
                              .AddModifiers(
                SyntaxFactory.Token(SyntaxKind.PublicKeyword),
                SyntaxFactory.Token(SyntaxKind.StaticKeyword),
                SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword));

            var callbackMethod = SyntaxFactory.MethodDeclaration(
                SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword)),
                SyntaxFactory.Identifier(callbackName))
                                 .AddParameterListParameters(
                SyntaxFactory.Parameter(
                    SyntaxFactory.Identifier("d"))
                .WithType(SyntaxFactory.IdentifierName("DependencyObject")),
                SyntaxFactory.Parameter(
                    SyntaxFactory.Identifier("e"))
                .WithType(SyntaxFactory.IdentifierName("DependencyPropertyChangedEventArgs")))
                                 .AddBodyStatements(
                SyntaxFactory.ThrowStatement(
                    SyntaxFactory.ObjectCreationExpression(
                        SyntaxFactory.IdentifierName("NotImplementedException"))
                    .AddArgumentListArguments()))
                                 .AddModifiers(
                SyntaxFactory.Token(SyntaxKind.PrivateKeyword),
                SyntaxFactory.Token(SyntaxKind.StaticKeyword));

            var newNodes = new List <SyntaxNode>
            {
                backingProperty,
                depProperty,
                callbackMethod,
            };

            var oldRoot = await document.GetSyntaxRootAsync(cancellationToken);

            var newRoot = oldRoot.ReplaceNode(pds, newNodes);

            return(document.WithSyntaxRoot(newRoot));
        }