private async Task <Document> WithAttributeAsync([NotNull] INamedTypeSymbol attribute,
                                                         [NotNull] Document document, [NotNull] SyntaxNode syntaxNode, CancellationToken cancellationToken)
        {
            DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);

            // Add NotNull/CanBeNull/ItemNotNull/ItemCanBeNull attribute.
            SyntaxNode attributeSyntax =
                editor.Generator.Attribute(editor.Generator.TypeExpression(attribute))
                .WithAdditionalAnnotations(Simplifier.Annotation, Formatter.Annotation, NamespaceImportAnnotation);

            editor.AddAttribute(syntaxNode, attributeSyntax);
            Document documentWithAttribute = editor.GetChangedDocument();

            // Add namespace import.
            Document documentWithImport =
                await
                ImportAdder.AddImportsAsync(documentWithAttribute, NamespaceImportAnnotation, null,
                                            cancellationToken).ConfigureAwait(false);

            // Simplify and reformat all annotated nodes.
            Document simplified = await SimplifyAsync(documentWithImport, cancellationToken).ConfigureAwait(false);

            SyntaxNode formatted = await FormatAsync(simplified, cancellationToken).ConfigureAwait(false);

            return(simplified.WithSyntaxRoot(formatted));
        }
예제 #2
0
        private static void AddRouteAttribute(SemanticModel semanticModel, SyntaxNode root, DocumentEditor documentEditor, TextSpan diagnosticSpan, CancellationToken cancellationToken)
        {
            var methodDeclaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType <MethodDeclarationSyntax>().First();

            var    method = semanticModel.GetDeclaredSymbol(methodDeclaration, cancellationToken);
            string?route  = null;

            foreach (var parameter in method.Parameters)
            {
                // Simple types participate in overload selection. We'll assume they all come from route and use it to produce a route for this action.
                // https://github.com/aspnet/AspNetWebStack/blob/749384689e027a2fcd29eb79a9137b94cea611a8/src/System.Web.Http/Internal/TypeHelper.cs#L63-L72
                if (parameter.Type.IsValueType ||
                    SymbolEqualityComparer.Default.Equals(parameter.Type, semanticModel.Compilation.GetSpecialType(SpecialType.System_String)) ||
                    SymbolEqualityComparer.Default.Equals(parameter.Type, semanticModel.Compilation.GetSpecialType(SpecialType.System_DateTime)) ||
                    SymbolEqualityComparer.Default.Equals(parameter.Type, semanticModel.Compilation.GetSpecialType(SpecialType.System_Decimal)))
                {
                    route += $"/{{{parameter.Name}}}";
                }
            }

            if (route is null)
            {
                return;
            }

            route = "[controller]/[action]" + route;

            var actionAttribute = SyntaxFactory.Attribute(
                SyntaxFactory.ParseName("Microsoft.AspNetCore.Mvc.Route").WithAdditionalAnnotations(Simplifier.Annotation))
                                  .AddArgumentListArguments(
                SyntaxFactory.AttributeArgument(
                    SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(route))));

            documentEditor.AddAttribute(methodDeclaration, actionAttribute);
        }
예제 #3
0
 private static void AddAttribute(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, string parameterName)
 {
     editor.AddAttribute(
         propertyDeclaration,
         editor.Generator.AddAttributeArguments(
             Attribute,
             new[] { editor.Generator.AttributeArgument(editor.Generator.LiteralExpression(parameterName)) }));
 }
예제 #4
0
 private static void AddAttribute(DocumentEditor editor, ClassDeclarationSyntax classDeclaration, ITypeSymbol returnType)
 {
     editor.AddAttribute(
         classDeclaration,
         editor.Generator.AddAttributeArguments(
             Attribute,
             new[] { editor.Generator.AttributeArgument(editor.Generator.TypeOfExpression(editor.Generator.TypeExpression(returnType))) }));
 }
        private static async Task <Document> AddNonSerializedAttribute(Document document, SyntaxNode fieldNode, CancellationToken cancellationToken)
        {
            DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);

            SyntaxNode attr = editor.Generator.Attribute(editor.Generator.TypeExpression(WellKnownTypes.NonSerializedAttribute(editor.SemanticModel.Compilation)));

            editor.AddAttribute(fieldNode, attr);
            return(editor.GetChangedDocument());
        }
예제 #6
0
        private static async Task <Document> AddSerializableAttribute(Document document, SyntaxNode node, CancellationToken cancellationToken)
        {
            DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);

            SyntaxNode attr = editor.Generator.Attribute(editor.Generator.TypeExpression(
                                                             editor.SemanticModel.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemSerializableAttribute)));

            editor.AddAttribute(node, attr);
            return(editor.GetChangedDocument());
        }
예제 #7
0
        private static void AddAttribute(DocumentEditor editor, MethodDeclarationSyntax classDeclaration, ITypeSymbol type)
        {
            TypeOfExpressionSyntax TypeOf(ITypeSymbol t)
            {
                if (t != null)
                {
                    return((TypeOfExpressionSyntax)editor.Generator.TypeOfExpression(editor.Generator.TypeExpression(t)));
                }

                return((TypeOfExpressionSyntax)editor.Generator.TypeOfExpression(SyntaxFactory.ParseTypeName("TYPE")));
            }

            editor.AddAttribute(
                classDeclaration,
                editor.Generator.AddAttributeArguments(
                    Attribute,
                    new[] { editor.Generator.AttributeArgument(TypeOf(type)) }));
        }
        private static async Task <Document> AddKeyAttributeAsync(Document document, INamedTypeSymbol type, CancellationToken cancellationToken)
        {
            if (type.DeclaringSyntaxReferences.Length != 0)
            {
                document = document.Project.GetDocument(type.DeclaringSyntaxReferences[0].SyntaxTree);
            }

            DocumentEditor editor = await DocumentEditor.CreateAsync(document).ConfigureAwait(false);

            ISymbol[] targets = type.GetAllMembers()
                                .Where(x => x.Kind == SymbolKind.Property || x.Kind == SymbolKind.Field)
                                .Where(x => x.GetAttributes().FindAttributeShortName(MessagePackAnalyzer.IgnoreShortName) == null && x.GetAttributes().FindAttributeShortName(MessagePackAnalyzer.IgnoreDataMemberShortName) == null)
                                .Where(x => !x.IsStatic)
                                .Where(x =>
            {
                var p = x as IPropertySymbol;
                if (p == null)
                {
                    var f = x as IFieldSymbol;
                    if (f.IsImplicitlyDeclared)
                    {
                        return(false);
                    }

                    return(true);
                }

                return(p.ExplicitInterfaceImplementations.Length == 0);
            })
                                .ToArray();

            var startOrder = targets
                             .Select(x => x.GetAttributes().FindAttributeShortName(MessagePackAnalyzer.KeyAttributeShortName))
                             .Where(x => x != null)
                             .Select(x => x.ConstructorArguments[0])
                             .Where(x => !x.IsNull)
                             .Where(x => x.Value.GetType() == typeof(int))
                             .Select(x => (int)x.Value)
                             .DefaultIfEmpty(-1) // if empty, start from zero.
                             .Max() + 1;

            foreach (ISymbol item in targets)
            {
                SyntaxNode node = await item.DeclaringSyntaxReferences[0].GetSyntaxAsync().ConfigureAwait(false);

                AttributeData attr = item.GetAttributes().FindAttributeShortName(MessagePackAnalyzer.KeyAttributeShortName);
                if (attr != null)
                {
                    continue; // already tagged Index.
                }

                AttributeListSyntax attribute = RoslynExtensions.ParseAttributeList($"[Key({startOrder++})]")
                                                .WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed);

                editor.AddAttribute(node, attribute);
            }

            if (type.GetAttributes().FindAttributeShortName(MessagePackAnalyzer.MessagePackObjectAttributeShortName) == null)
            {
                SyntaxNode rootNode = await type.DeclaringSyntaxReferences[0].GetSyntaxAsync().ConfigureAwait(false);
                editor.AddAttribute(rootNode, RoslynExtensions.ParseAttributeList("[MessagePackObject]"));
            }

            Document newDocument = editor.GetChangedDocument();
            var      newRoot     = editor.GetChangedRoot() as CompilationUnitSyntax;

            newDocument = newDocument.WithSyntaxRoot(newRoot.WithUsing("MessagePack"));

            return(newDocument);
        }