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)); }
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); }
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)) })); }
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()); }
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()); }
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); }