private async Task <Document> AddDateMemberAttributesAndFixOrder(Document document, PropertyDeclarationSyntax[] publicProperties, PropertyDeclarationSyntax[] propertiesWithDataMemberAttributeWithoutOrder, PropertyDeclarationSyntax[] propertiesWithDataMemberAttributeWithOrder, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken);

            int max = 0;

            if (propertiesWithDataMemberAttributeWithOrder.Any())
            {
                max = propertiesWithDataMemberAttributeWithOrder.Max(p => GetOrder(GetDataMemberAttribute(p)) ?? 0);
            }

            var updateNodes = new Dictionary <SyntaxNode, SyntaxNode>();

            foreach (var property in propertiesWithDataMemberAttributeWithoutOrder)
            {
                var attribute = GetDataMemberAttribute(property); //DataMember
                AttributeArgumentListSyntax arguments = CreateOrderArgument(++max);
                var args = attribute.ArgumentList?.Arguments.ToArray();
                AttributeArgumentListSyntax allArgs = arguments;
                if (args != null)
                {
                    allArgs = arguments.AddArguments(args);
                }
                var newAttribute = attribute.WithArgumentList(allArgs); //DataMember(Order = #)
                updateNodes.Add(attribute, newAttribute);
            }
            foreach (var property in publicProperties.Except(propertiesWithDataMemberAttributeWithoutOrder.Union(propertiesWithDataMemberAttributeWithOrder)))
            {
                var name = SyntaxFactory.ParseName(DataMember);
                AttributeArgumentListSyntax arguments = CreateOrderArgument(++max);
                var attribute = SyntaxFactory.Attribute(name, arguments); //DataMember(Order = #)

                var attributeList = new SeparatedSyntaxList <AttributeSyntax>();
                attributeList = attributeList.Add(attribute);
                var list     = SyntaxFactory.AttributeList(attributeList); //[DataMember(Order = #)]
                var modifier = property.Modifiers.FirstOrDefault();

                if (modifier != null)
                {
                    var commentsT = modifier.LeadingTrivia;

                    list = list.WithLeadingTrivia(commentsT);
                }


                var newModifiers = SyntaxFactory.TokenList(property.Modifiers.Skip(1).Concat(new[] { SyntaxFactory.Token(SyntaxKind.PublicKeyword) }));;
                var newProperty  = property.AddAttributeLists(list).WithModifiers(newModifiers);

                updateNodes.Add(property, newProperty);
            }
            root = root.ReplaceNodes(updateNodes.Keys, (n1, n2) =>
            {
                return(updateNodes[n1]);
            });
            return(document.WithSyntaxRoot(root));
        }
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            foreach (var diagnostic in context.Diagnostics)
            {
                if (!string.Equals(diagnostic.Id, JsonObjectOptInAnalyzer.DiagnosticId, StringComparison.Ordinal))
                {
                    continue;
                }

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

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

                ExpressionSyntax expression =
                    SyntaxFactory.ParseExpression("global::Newtonsoft.Json.MemberSerialization.OptIn")
                    .WithAdditionalAnnotations(Simplifier.Annotation);

                AttributeSyntax             newAttribute = null;
                AttributeArgumentListSyntax argumentList = syntax.ArgumentList;
                if (argumentList != null)
                {
                    AttributeArgumentSyntax existingArgument = null;
                    foreach (var attributeArgument in argumentList.Arguments)
                    {
                        if (string.Equals("MemberSerialization", attributeArgument.NameEquals?.Name?.Identifier.ValueText, StringComparison.Ordinal))
                        {
                            existingArgument = attributeArgument;
                            break;
                        }
                    }

                    if (existingArgument == null)
                    {
                        SemanticModel semanticModel = null;
                        foreach (var attributeArgument in argumentList.Arguments)
                        {
                            // this time only interested in arguments (no NameEquals clause)
                            if (attributeArgument.NameEquals != null)
                            {
                                continue;
                            }

                            if (string.Equals("memberSerialization", attributeArgument.NameColon?.Name?.Identifier.ValueText, StringComparison.Ordinal))
                            {
                                existingArgument = attributeArgument;
                                break;
                            }

                            if (attributeArgument.NameColon != null)
                            {
                                continue;
                            }

                            if (semanticModel == null)
                            {
                                semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
                            }

                            if (IsMemberSerializationArgument(semanticModel, attributeArgument.Expression, context.CancellationToken))
                            {
                                existingArgument = attributeArgument;
                                break;
                            }
                        }
                    }

                    if (existingArgument != null)
                    {
                        var newArgument =
                            existingArgument
                            .WithExpression(expression)
                            .WithTriviaFrom(existingArgument)
                            .WithoutFormatting();

                        newAttribute = syntax.ReplaceNode(existingArgument, newArgument);
                    }
                }

                if (newAttribute == null)
                {
                    if (argumentList == null)
                    {
                        argumentList = SyntaxFactory.AttributeArgumentList();
                    }

                    NameEqualsSyntax nameEquals;
                    if (argumentList.Arguments.Any(argument => argument.NameEquals == null))
                    {
                        nameEquals = SyntaxFactory.NameEquals("MemberSerialization");
                    }
                    else
                    {
                        nameEquals = null;
                    }

                    AttributeArgumentSyntax defaultValueArgument = SyntaxFactory.AttributeArgument(nameEquals, null, expression);

                    argumentList = argumentList.AddArguments(defaultValueArgument);
                    newAttribute = syntax.WithArgumentList(argumentList);
                }

                SyntaxNode newRoot     = documentRoot.ReplaceNode(syntax, newAttribute);
                Document   newDocument = context.Document.WithSyntaxRoot(newRoot);
                context.RegisterCodeFix(CodeAction.Create("Add MemberSerialization.OptIn", _ => Task.FromResult(newDocument)), diagnostic);
            }
        }
Example #3
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            foreach (var diagnostic in context.Diagnostics)
            {
                if (!string.Equals(diagnostic.Id, JsonPropertyDefaultValueHandlingAnalyzer.DiagnosticId, StringComparison.Ordinal))
                {
                    continue;
                }

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

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

                ExpressionSyntax expression =
                    SyntaxFactory.ParseExpression("global::Newtonsoft.Json.DefaultValueHandling.Ignore")
                    .WithAdditionalAnnotations(Simplifier.Annotation);

                AttributeSyntax             newAttribute = null;
                AttributeArgumentListSyntax argumentList = syntax.ArgumentList;
                if (argumentList != null)
                {
                    AttributeArgumentSyntax existingArgument = null;
                    foreach (var attributeArgument in argumentList.Arguments)
                    {
                        if (string.Equals("DefaultValueHandling", attributeArgument.NameEquals?.Name?.Identifier.ValueText, StringComparison.Ordinal))
                        {
                            existingArgument = attributeArgument;
                            break;
                        }
                    }

                    if (existingArgument != null)
                    {
                        var newArgument =
                            existingArgument
                            .WithExpression(expression)
                            .WithTriviaFrom(existingArgument)
                            .WithoutFormatting();

                        newAttribute = syntax.ReplaceNode(existingArgument, newArgument);
                    }
                }

                if (newAttribute == null)
                {
                    NameEqualsSyntax nameEquals = SyntaxFactory.NameEquals("DefaultValueHandling");

                    AttributeArgumentSyntax defaultValueArgument = SyntaxFactory.AttributeArgument(nameEquals, null, expression);

                    if (argumentList == null)
                    {
                        argumentList = SyntaxFactory.AttributeArgumentList();
                    }

                    argumentList = argumentList.AddArguments(defaultValueArgument);

                    newAttribute = syntax.WithArgumentList(argumentList);
                }

                SyntaxNode newRoot     = documentRoot.ReplaceNode(syntax, newAttribute);
                Document   newDocument = context.Document.WithSyntaxRoot(newRoot);
                context.RegisterCodeFix(CodeAction.Create("Add DefaultValueHandling.Ignore", _ => Task.FromResult(newDocument)), diagnostic);
            }
        }
        private static AttributeArgumentListSyntax CreateArgumentList(string name, AttributeSyntax attribute, AttributeArgumentListSyntax other)
        {
            var argument   = attribute.ArgumentList?.Arguments.FirstOrDefault();
            var expression = argument?.Expression?.ChildTokens().FirstOrDefault();

            var value = expression ?? Literal("");

            var attributeArgument = AttributeArgument(
                AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(name),
                                     LiteralExpression(SyntaxKind.StringLiteralExpression, value)));

            return(other == null?AttributeArgumentList(SeparatedList(new[] { attributeArgument })) : other.AddArguments(attributeArgument));
        }