コード例 #1
0
        public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node)
        {
            var containingTypeSyntax = node.FirstAncestorOrSelf <TypeDeclarationSyntax>();

            if (node.ExpressionBody != null)
            {
                var propertySymbol = this.SemanticModel.GetDeclaredSymbol(node);
                var methodSymbol   = propertySymbol.GetMethod;

                this.ProcessArrowExpressionDecl(node.ExpressionBody, containingTypeSyntax, methodSymbol);
            }
            else if (node.AccessorList != null)
            {
                foreach (var accessor in node.AccessorList.Accessors)
                {
                    var methodSymbol = this.SemanticModel.GetDeclaredSymbol(accessor);
                    this.ProcessPropertyAccessorDecl(accessor, containingTypeSyntax, methodSymbol);
                }
            }
            else
            {
                throw new NotImplementedException("Unknown PropertyDeclaration syntax.");
            }

            base.VisitPropertyDeclaration(node);
        }
コード例 #2
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            foreach (var diagnostic in context.Diagnostics)
            {
                if (!string.Equals(diagnostic.Id, ImplementBuilderPatternAnalyzer.DiagnosticId, StringComparison.Ordinal))
                {
                    continue;
                }

                var documentRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

                SyntaxNode syntax = documentRoot.FindNode(diagnostic.Location.SourceSpan);
                if (syntax == null)
                {
                    continue;
                }

                PropertyDeclarationSyntax propertyDeclaration = syntax.FirstAncestorOrSelf <PropertyDeclarationSyntax>();
                if (propertyDeclaration == null)
                {
                    continue;
                }

                ClassDeclarationSyntax classDeclarationSyntax = propertyDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>();
                if (classDeclarationSyntax == null)
                {
                    continue;
                }

                string description = string.Format("Implement builder method 'With{0}'", propertyDeclaration.Identifier.ValueText);
                context.RegisterCodeFix(CodeAction.Create(description, cancellationToken => CreateChangedSolution(context, classDeclarationSyntax, propertyDeclaration, cancellationToken)), diagnostic);
            }
        }
コード例 #3
0
        public static int GetMaxOrderNumber(this PropertyDeclarationSyntax property)
        {
            var orderNumber = 0;

            var type = property.FirstAncestorOrSelf <TypeDeclarationSyntax>();

            var properties = type.Members.OfType <PropertyDeclarationSyntax>();

            foreach (var item in properties)
            {
                foreach (var attribute in item.AttributeLists.SelectMany(p => p.Attributes))
                {
                    if (_dataMemberNames.Contains(attribute.Name.GetIdentifierName()) && attribute.ArgumentList != null)
                    {
                        foreach (var argument in attribute.ArgumentList.Arguments)
                        {
                            if (argument.NameEquals.Name.Identifier.Text == Constants.OrderPropertyName)
                            {
                                var currentNumber = (int)((LiteralExpressionSyntax)argument.Expression).Token.Value;

                                if (currentNumber > orderNumber)
                                {
                                    orderNumber = currentNumber;
                                }
                            }
                        }
                    }
                }
            }

            return(orderNumber);
        }
コード例 #4
0
        internal static bool TryGetBackingField(PropertyDeclarationSyntax property, out IdentifierNameSyntax field, out FieldDeclarationSyntax fieldDeclaration)
        {
            field            = null;
            fieldDeclaration = null;
            if (property == null)
            {
                return(false);
            }

            AccessorDeclarationSyntax setter;

            if (property.TryGetSetAccessorDeclaration(out setter) &&
                setter.Body != null)
            {
                using (var pooled = AssignmentWalker.Create(setter))
                {
                    if (pooled.Item.Assignments.Count != 1)
                    {
                        return(false);
                    }

                    var left = pooled.Item.Assignments[0].Left;
                    field = left as IdentifierNameSyntax;
                    if (field == null)
                    {
                        var memberAccess = left as MemberAccessExpressionSyntax;
                        if (!(memberAccess?.Expression is ThisExpressionSyntax))
                        {
                            return(false);
                        }

                        field = memberAccess.Name as IdentifierNameSyntax;
                    }

                    if (field == null)
                    {
                        return(false);
                    }

                    foreach (var member in property.FirstAncestorOrSelf <TypeDeclarationSyntax>().Members)
                    {
                        fieldDeclaration = member as FieldDeclarationSyntax;
                        if (fieldDeclaration != null)
                        {
                            foreach (var variable in fieldDeclaration.Declaration.Variables)
                            {
                                if (variable.Identifier.ValueText == field.Identifier.ValueText)
                                {
                                    return(true);
                                }
                            }
                        }
                    }
                }
            }

            return(false);
        }
コード例 #5
0
 public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node)
 {
     if (!node.FirstAncestorOrSelf <ClassDeclarationSyntax>().Identifier.Text.Contains("Mapper"))
     {
         // check if node is automatically generated (not wrapped inside custom comments)
         if (!this._finder.IsNodeWithinCustomCode(node))
         {
             this.GeneratedProperties.Add(node.Identifier.Text);
         }
     }
 }
コード例 #6
0
        private static void MakeAutoPropertySet(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, IMethodSymbol setAndRaise, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var classDeclaration = propertyDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>();

            if (classDeclaration == null)
            {
                return;
            }

            if (Property.IsMutableAutoProperty(propertyDeclaration, out var getter, out var setter))
            {
                if (getter.Body != null ||
                    getter.ContainsSkippedText ||
                    setter.Body != null ||
                    setter.ContainsSkippedText)
                {
                    return;
                }

                var underscoreFields = CodeStyle.UnderscoreFields(semanticModel);
                var backingField     = editor.AddBackingField(propertyDeclaration, underscoreFields, cancellationToken);
                var fieldAccess      = underscoreFields
                    ? backingField.Name()
                    : $"this.{backingField.Name()}";
                var code = StringBuilderPool.Borrow()
                           .AppendLine($"public Type PropertyName")
                           .AppendLine("{")
                           .AppendLine($"    get => {fieldAccess};")
                           .AppendLine($"    set => {(underscoreFields ? string.Empty : "this.")}{setAndRaise.Name}(ref {fieldAccess}, value);")
                           .AppendLine("}")
                           .Return();
                var template = ParseProperty(code);
                editor.ReplaceNode(
                    getter,
                    x => x.WithExpressionBody(template.Getter().ExpressionBody)
                    .WithLeadingLineFeed());

                editor.ReplaceNode(
                    setter,
                    x => x.WithExpressionBody(template.Setter().ExpressionBody)
                    .WithLeadingLineFeed()
                    .WithTrailingLineFeed());

                if (propertyDeclaration.Initializer != null)
                {
                    editor.ReplaceNode(
                        propertyDeclaration,
                        (node, g) => ((PropertyDeclarationSyntax)node).WithoutInitializer());
                }

                editor.ReplaceNode(propertyDeclaration, x => x.WithAdditionalAnnotations(Formatter.Annotation));
            }
        }
コード例 #7
0
        public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
        {
            if (!node.FirstAncestorOrSelf <ClassDeclarationSyntax>().Identifier.Text.Contains("Mapper"))
            {
                // check if node is automatically generated (not wrapped inside custom comments)
                if (!this._finder.IsNodeWithinCustomCode(node))
                {
                    return(null);
                }
            }

            return(base.VisitPropertyDeclaration(node));
        }
コード例 #8
0
        private static bool IsValidConstructorArgumentName(AttributeData attribute,
                                                           PropertyDeclarationSyntax propertyDeclaration)
        {
            var allConstructorArguments = propertyDeclaration
                                          .FirstAncestorOrSelf <ClassDeclarationSyntax>()
                                          .Members
                                          .OfType <ConstructorDeclarationSyntax>()
                                          .SelectMany(x => x.ParameterList.Parameters)
                                          .Select(x => x.Identifier.ValueText)
                                          .ToHashSet();

            return(allConstructorArguments.Contains(attribute.ConstructorArguments[0].Value));
        }
コード例 #9
0
        internal static string BackingFieldNameForAutoProperty(PropertyDeclarationSyntax property)
        {
            var typeDeclaration     = property.FirstAncestorOrSelf <TypeDeclarationSyntax>();
            var usesUnderscoreNames = typeDeclaration.UsesUnderscoreNames();
            var fieldName           = usesUnderscoreNames
                              ? $"_{property.Identifier.ValueText.ToFirstCharLower()}"
                              : property.Identifier.ValueText.ToFirstCharLower();

            while (typeDeclaration.HasMember(fieldName))
            {
                fieldName += "_";
            }

            return(fieldName);
        }
コード例 #10
0
        internal static CompilationUnitSyntax ImplementFullProperty(CompilationUnitSyntax root, SemanticModel model, PropertyDeclarationSyntax propertyDecl, Workspace workspace)
        {
            TypeDeclarationSyntax typeDecl = propertyDecl.FirstAncestorOrSelf <TypeDeclarationSyntax>();
            string      propertyName       = propertyDecl.Identifier.ValueText;
            string      backingFieldName   = $"_{char.ToLower(propertyName[0])}{propertyName.Substring(1)}";
            ITypeSymbol propertyTypeSymbol = model.GetDeclaredSymbol(propertyDecl).Type;

            root = root.ReplaceNodes(new SyntaxNode[] { propertyDecl, typeDecl },
                                     (original, updated) =>
                                     original.IsKind(SyntaxKind.PropertyDeclaration)
                ? ExpandProperty((PropertyDeclarationSyntax)original, (PropertyDeclarationSyntax)updated, backingFieldName) as SyntaxNode
                : ExpandType((TypeDeclarationSyntax)original, (TypeDeclarationSyntax)updated, propertyTypeSymbol, backingFieldName, model, workspace) as SyntaxNode
                                     );

            return(root);
        }
コード例 #11
0
        private static void MakeWithBackingFieldSet(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, IMethodSymbol setAndRaise, SemanticModel semanticModel)
        {
            var classDeclaration = propertyDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>();

            if (classDeclaration == null)
            {
                return;
            }

            if (IsSimpleAssignmentOnly(propertyDeclaration, out _, out _, out var assignment, out var fieldAccess))
            {
                var underscoreFields = CodeStyle.UnderscoreFields(semanticModel);
                var setExpression    = SyntaxFactory.ParseExpression($"{(underscoreFields ? string.Empty : "this.")}{setAndRaise.Name}(ref {fieldAccess}, value);")
                                       .WithTrailingTrivia(SyntaxFactory.ElasticMarker)
                                       .WithSimplifiedNames()
                                       .WithAdditionalAnnotations(Formatter.Annotation);
                editor.ReplaceNode(assignment, setExpression);
            }
        }
        private static (SyntaxNode newRoot, PropertyDeclarationSyntax newNode) ConvertToFullProperty(SyntaxNode root, PropertyDeclarationSyntax node)
        {
            string nodeType  = (node.Type as TypeSyntax).GetText().ToString();
            string fieldName = node.Identifier.Text;

            fieldName = fieldName.First().ToString().ToLower() + new String(fieldName.Skip(1).ToArray());
            if (fieldName == node.Identifier.Text)
            {
                fieldName = "_" + fieldName;
            }



            var getArrow  = SyntaxFactory.ArrowExpressionClause(SyntaxFactory.IdentifierName(fieldName));
            var newGetter = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration);

            newGetter = newGetter.WithExpressionBody(getArrow);
            newGetter = newGetter.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken));

            var assignment = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                                SyntaxFactory.IdentifierName(fieldName),
                                                                SyntaxFactory.IdentifierName("value"));

            var newSetter = SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration,
                                                              SyntaxFactory.Block(SyntaxFactory.ExpressionStatement(assignment)));

            var annotation = new SyntaxAnnotation("prop_with_new_setter", "");

            var accessorList    = SyntaxFactory.AccessorList();
            var newaccessorList = accessorList.AddAccessors(newGetter, newSetter);
            var newNode         = node.WithAccessorList(newaccessorList)
                                  .WithAdditionalAnnotations(annotation);

            var cls    = node.FirstAncestorOrSelf <ClassDeclarationSyntax>();
            var newCls = cls.ReplaceNode(node, newNode);

            newCls = newCls.AddField(nodeType, fieldName);

            var newRoot = root.ReplaceNode(cls, newCls);

            newNode = newRoot.GetAnnotatedNodes(annotation).First() as PropertyDeclarationSyntax;
            return(newRoot, newNode);
        }
コード例 #13
0
        private static Task <Document> ApplyConvertAutoPropertyFixAsync(
            CodeFixContext context,
            SyntaxNode syntaxRoot,
            PropertyDeclarationSyntax propertyDeclaration,
            IPropertySymbol property,
            ExpressionStatementSyntax assignStatement,
            string fieldName,
            IMethodSymbol invoker)
        {
            var syntaxGenerator = SyntaxGenerator.GetGenerator(context.Document);
            var typeDeclaration = propertyDeclaration.FirstAncestorOrSelf <TypeDeclarationSyntax>();

            var newPropertyDeclaration = propertyDeclaration.WithGetterReturningBackingField(syntaxGenerator, fieldName)
                                         .WithNotifyingSetter(syntaxGenerator, property, assignStatement, fieldName, invoker);

            var newTypeDeclaration = typeDeclaration.ReplaceNode(propertyDeclaration, newPropertyDeclaration);

            return(Task.FromResult(context.Document.WithSyntaxRoot(syntaxRoot.ReplaceNode(typeDeclaration, newTypeDeclaration))));
        }
コード例 #14
0
        private static void MakeWithBackingFieldNotify(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, IMethodSymbol invoker, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var classDeclaration = propertyDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>();

            if (classDeclaration == null)
            {
                return;
            }

            if (IsSimpleAssignmentOnly(propertyDeclaration, out var setter, out var statement, out var assignment, out _))
            {
                var underscoreFields = CodeStyle.UnderscoreFields(semanticModel);
                var property         = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken);
                var notifyStatement  = SyntaxFactory
                                       .ParseStatement(Snippet.OnPropertyChanged(invoker, property.Name, underscoreFields))
                                       .WithLeadingTrivia(SyntaxFactory.ElasticMarker)
                                       .WithTrailingTrivia(SyntaxFactory.ElasticMarker)
                                       .WithSimplifiedNames()
                                       .WithAdditionalAnnotations(Formatter.Annotation);
                if (setter.ExpressionBody != null)
                {
                    editor.ReplaceNode(
                        setter,
                        (x, _) =>
                    {
                        var old = (AccessorDeclarationSyntax)x;
                        return(old.WithBody(
                                   SyntaxFactory.Block(
                                       SyntaxFactory.ExpressionStatement(assignment),
                                       notifyStatement))
                               .WithExpressionBody(null)
                               .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)));
                    });
                    editor.FormatNode(propertyDeclaration);
                }
                else if (setter.Body != null)
                {
                    editor.InsertAfter(statement, notifyStatement);
                    editor.FormatNode(propertyDeclaration);
                }
            }
        }
コード例 #15
0
        private static void MakeWithBackingFieldNotifyWhenValueChanges(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, IMethodSymbol invoker, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var classDeclaration = propertyDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>();

            if (classDeclaration == null)
            {
                return;
            }

            if (propertyDeclaration.TryGetSetter(out var setter))
            {
                if (setter.ExpressionBody != null &&
                    IsSimpleAssignmentOnly(propertyDeclaration, out _, out _, out var assignment, out _))
                {
                    var property         = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken);
                    var underscoreFields = CodeStyle.UnderscoreFields(semanticModel);
                    var code             = StringBuilderPool.Borrow()
                                           .AppendLine($"public Type PropertyName")
                                           .AppendLine("{")
                                           .AppendLine($"    get => {assignment.Left};")
                                           .AppendLine()
                                           .AppendLine("    set")
                                           .AppendLine("    {")
                                           .AppendLine($"        if ({Snippet.EqualityCheck(property.Type, "value", assignment.Left.ToString(), semanticModel)})")
                                           .AppendLine("        {")
                                           .AppendLine($"           return;")
                                           .AppendLine("        }")
                                           .AppendLine()
                                           .AppendLine($"        {assignment};")
                                           .AppendLine($"        {Snippet.OnPropertyChanged(invoker, property.Name, underscoreFields)}")
                                           .AppendLine("    }")
                                           .AppendLine("}")
                                           .Return();
                    var template = ParseProperty(code);
                    editor.ReplaceNode(
                        setter,
                        (x, _) =>
                    {
                        var old = (AccessorDeclarationSyntax)x;
                        return(old.WithBody(template.Setter().Body)
                               .WithExpressionBody(null)
                               .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)));
                    });
                    editor.FormatNode(propertyDeclaration);
                }

                if (setter.Body?.Statements.Count == 1 &&
                    IsSimpleAssignmentOnly(propertyDeclaration, out _, out var statement, out assignment, out _))
                {
                    var property = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken);
                    var code     = StringBuilderPool.Borrow()
                                   .AppendLine($"        if ({Snippet.EqualityCheck(property.Type, "value", assignment.Left.ToString(), semanticModel)})")
                                   .AppendLine("        {")
                                   .AppendLine($"           return;")
                                   .AppendLine("        }")
                                   .AppendLine()
                                   .Return();
                    var ifStatement = SyntaxFactory.ParseStatement(code)
                                      .WithSimplifiedNames()
                                      .WithLeadingElasticLineFeed()
                                      .WithTrailingElasticLineFeed()
                                      .WithAdditionalAnnotations(Formatter.Annotation);
                    editor.InsertBefore(
                        statement,
                        ifStatement);
                    var underscoreFields = CodeStyle.UnderscoreFields(semanticModel);
                    var notifyStatement  = SyntaxFactory
                                           .ParseStatement(
                        Snippet.OnPropertyChanged(invoker, property.Name, underscoreFields))
                                           .WithSimplifiedNames()
                                           .WithLeadingElasticLineFeed()
                                           .WithTrailingElasticLineFeed()
                                           .WithAdditionalAnnotations(Formatter.Annotation);
                    editor.InsertAfter(statement, notifyStatement);
                    editor.FormatNode(propertyDeclaration);
                }
            }
        }
コード例 #16
0
        private async Task <Document> CreatePrismProperty(Document document, PropertyDeclarationSyntax propertyDeclaration, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var classDeclaration = propertyDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>();
            var fields           = classDeclaration?.DescendantNodes().OfType <FieldDeclarationSyntax>();

            var backingFieldName = propertyDeclaration.Identifier.ValueText;

            if (char.IsUpper(backingFieldName, 0))
            {
                backingFieldName = char.ToLower(backingFieldName[0]) + backingFieldName.Substring(1);
            }
            else
            {
                backingFieldName = "_" + backingFieldName;
            }

            if (fields != null)
            {
                int i = 1;
                while (fields.Any(f => f.Declaration.Variables.Any(v => v.Identifier.ValueText == backingFieldName)))
                {
                    i++;
                    backingFieldName = backingFieldName + i.ToString("D");
                }
            }

            var indentation = propertyDeclaration.GetLeadingTrivia().LastOrDefault(t => t.Kind() == SyntaxKind.WhitespaceTrivia);

            var newFieldDeclaration =
                SyntaxFactory.FieldDeclaration(
                    SyntaxFactory.VariableDeclaration(
                        propertyDeclaration.Type.WithTrailingTrivia(SyntaxFactory.Space),
                        SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(backingFieldName)))))
                .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxFactory.TriviaList(indentation), SyntaxKind.PrivateKeyword, SyntaxFactory.TriviaList(SyntaxFactory.Space))));

            var newPropertyDeclaration = propertyDeclaration
                                         .WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(new[] { CreateGetter(backingFieldName), CreateSetter(backingFieldName) })));

            var newRoot = root.ReplaceNode(propertyDeclaration, newPropertyDeclaration);

            classDeclaration = classDeclaration != null?newRoot.DescendantNodes().OfType <ClassDeclarationSyntax>().FirstOrDefault(c => c.Identifier.ValueText == classDeclaration.Identifier.ValueText) : null;

            if (classDeclaration != null)
            {
                var ctor = classDeclaration.DescendantNodes().OfType <ConstructorDeclarationSyntax>().FirstOrDefault();
                if (ctor != null)
                {
                    newRoot = newRoot.InsertNodesBefore(ctor, new[] { newFieldDeclaration });
                }
                else
                {
                    var lastFieldDeclaration = classDeclaration.DescendantNodes().OfType <FieldDeclarationSyntax>().LastOrDefault();
                    if (lastFieldDeclaration != null)
                    {
                        newRoot = newRoot.InsertNodesAfter(lastFieldDeclaration, new[] { newFieldDeclaration });
                    }
                    else
                    {
                        var newMembers = classDeclaration.Members.Insert(0, newFieldDeclaration);
                        newRoot = newRoot.ReplaceNode(classDeclaration, classDeclaration.WithMembers(newMembers));
                    }
                }
            }
            else
            {
                newRoot = newRoot.InsertNodesBefore(newRoot.DescendantNodes().OfType <PropertyDeclarationSyntax>().FirstOrDefault(), new[] { newFieldDeclaration });
            }

            return(document.WithSyntaxRoot(newRoot));
        }
コード例 #17
0
        protected override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
        {
            Boolean isDependencyProperty = node
                .Attributes
                .SelectMany(a => a.ChildNodes().OfType<AttributeSyntax>())
                .Any(a => a.Name.PlainName == "Dependency");

            if (!isDependencyProperty)
            {
                return base.VisitPropertyDeclaration(node);
            }

            AccessorDeclarationSyntax changeCallback = node
                .AccessorList
                .Accessors
                .FirstOrDefault(a => a.Kind == SyntaxKind.UnknownAccessorDeclaration && a.Keyword.ValueText == "change");
            Boolean hasChangeCallback = changeCallback != null;

            TypeSyntax dpType = Syntax.ParseTypeName("System.Windows.DependencyProperty");

            // add a DP field:
            // DependencyProperty XxxProperty = DependencyProperty.Register("Xxx", typeof(PropType), typeof(OwnerType),
            //   new FrameworkPropertyMetadata(OnXxxChanged);
            TypeSyntax ownerType = Syntax.ParseTypeName(node
                .FirstAncestorOrSelf<ClassDeclarationSyntax>()
                .Identifier
                .ValueText);
            String propertyName = node.Identifier.ValueText;
            ExpressionSyntax propertyNameExpression = Syntax.LiteralExpression(SyntaxKind.StringLiteralExpression, Syntax.Literal(text: '"' + propertyName + '"', value: propertyName));
            ExpressionSyntax typeofPropertyType = Syntax.TypeOfExpression(argumentList: Syntax.ArgumentList(arguments: Syntax.SeparatedList(Syntax.Argument(expression: node.Type))));
            ExpressionSyntax typeofOwnerType = Syntax.TypeOfExpression(argumentList: Syntax.ArgumentList(arguments: Syntax.SeparatedList(Syntax.Argument(expression: ownerType))));

            var registerArgs = new List<ArgumentSyntax> {
                                                            Syntax.Argument(expression: propertyNameExpression),
                                                            Syntax.Argument(expression: typeofPropertyType),
                                                            Syntax.Argument(expression: typeofOwnerType)
                                                        };

            if (hasChangeCallback)
            {
                ExpressionSyntax changeMethod = Syntax.ParseName("On" + propertyName + "Changed");

                ExpressionSyntax frameworkPropertyMetadata = Syntax.ObjectCreationExpression(
                  type: Syntax.ParseTypeName("System.Windows.FrameworkPropertyMetadata"),
                  argumentListOpt: Syntax.ArgumentList(arguments: Syntax.SeparatedList(Syntax.Argument(expression: changeMethod))));

                registerArgs.Add(Syntax.Argument(expression: frameworkPropertyMetadata)
                );
            }

            IEnumerable<SyntaxToken> argSeparators = Enumerable.Repeat(
                Syntax.Token(SyntaxKind.CommaToken),
                registerArgs.Count - 1)
                .ToList();

            ExpressionSyntax dpexpr = Syntax.InvocationExpression(
              expression: Syntax.ParseName("System.Windows.DependencyProperty.Register"),
              argumentList: Syntax.ArgumentList(arguments: Syntax.SeparatedList(registerArgs, argSeparators)));

            String fieldName = propertyName + "Property";
            VariableDeclaratorSyntax declarator = Syntax.VariableDeclarator(
              identifier: Syntax.Identifier(fieldName),
              initializerOpt: Syntax.EqualsValueClause(value: dpexpr));
            FieldDeclarationSyntax newField = Syntax.FieldDeclaration(
              modifiers: Syntax.TokenList(Syntax.Token(SyntaxKind.PublicKeyword), Syntax.Token(SyntaxKind.StaticKeyword)),
              declaration: Syntax.VariableDeclaration(
                type: dpType,
                variables: Syntax.SeparatedList(declarator)));
            _fields.Add(newField);

            // add a DP CLR wrapper:
            // public PropType Xxx
            // {
            //   get { return (PropType)GetValue(XxxProperty); }
            //   set { SetValue(XxxPropety, value); }
            // }
            ExpressionSyntax getval = Syntax.ParseExpression("GetValue(" + fieldName + ")");
            ExpressionSyntax cast = Syntax.CastExpression(type: node.Type, expression: getval);
            StatementSyntax getter = Syntax.ReturnStatement(expressionOpt: cast);

            StatementSyntax setter = Syntax.ParseStatement("SetValue(" + fieldName + ");");

            PropertyDeclarationSyntax newProperty = Syntax.PropertyDeclaration(
              modifiers: Syntax.TokenList(Syntax.Token(SyntaxKind.PublicKeyword)),
              type: node.Type,
              identifier: node.Identifier,
              accessorList: Syntax.AccessorList(
                accessors: Syntax.List(
                  Syntax.AccessorDeclaration(
                    kind: SyntaxKind.GetAccessorDeclaration,
                    bodyOpt: Syntax.Block(
                      statements: Syntax.List(
                        getter
                      )
                    )
                  ),
                  Syntax.AccessorDeclaration(
                    kind: SyntaxKind.SetAccessorDeclaration,
                    bodyOpt: Syntax.Block(
                      statements: Syntax.List(
                        setter
                      )
                    )
                  )
                )
              ));

            // add change callback if required
            // private static void OnXxxChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            // {
            //   /* body */
            // }
            if (hasChangeCallback)
            {
                List<ParameterSyntax> parameterList = new List<ParameterSyntax>
                            {
                                Syntax.Parameter(identifier: Syntax.Identifier("d"), typeOpt: Syntax.ParseTypeName("System.Windows.DependencyObject")),
                                Syntax.Parameter(identifier: Syntax.Identifier("e"), typeOpt: Syntax.ParseTypeName("System.Windows.DependencyPropertyChangedEventArgs")),
                            };
                var paramSeparators = Enumerable.Repeat(Syntax.Token(SyntaxKind.CommaToken), parameterList.Count - 1).ToList();
                ParameterListSyntax parameters = Syntax.ParameterList(
                  parameters: Syntax.SeparatedList(parameterList, paramSeparators)
                );
                MethodDeclarationSyntax changeMethod = Syntax.MethodDeclaration(
                  modifiers: Syntax.TokenList(Syntax.Token(SyntaxKind.PrivateKeyword), Syntax.Token(SyntaxKind.StaticKeyword)),
                  identifier: Syntax.Identifier("On" + propertyName + "Changed"),
                  returnType: Syntax.PredefinedType(Syntax.Token(SyntaxKind.VoidKeyword)),
                  parameterList: parameters,
                  bodyOpt: changeCallback.BodyOpt
                );
                _methods.Add(changeMethod);
            }

            return newProperty;
        }