Skip to content

Higher Level SyntaxProvider APIs for incremental generators #54725

@chsienki

Description

@chsienki

Background and Motivation

An extremely common pattern seen in source generators involves inserting an attribute via PostInitialization, then finding all symbols that are marked with that attribute. There are currently several different ways to acheive this, and we often hear from customers that they would like a 'canonical' compiler approved method. While we provide examples in the cookbook, it seems like we have an opportunity to provide a set of APIs to do this directly which will allow customers to fall into the 'pit of success' and allow us to potentially optimize further as we know exactly what they are trying to acheive.

Proposed API

namespace Microsoft.CodeAnalysis
{
    public readonly struct SyntaxValueProvider
    {
+       /// <summary>
+       /// Creates an <see cref="IncrementalValuesProvider{T}"/> that can provide a transform over all <see cref="SyntaxNode"/>s marked with a specified attribute.
+       /// </summary>
+       /// <param name="attributeFQN">The FullyQualifiedName of the attribute used to search for nodes that are annotated with it.</param>
+       /// <param name="transform">A function that performs the transfomation of the found nodes</param>
+       /// <returns>An <see cref="IncrementalValuesProvider{T}"/> that provides the results of the transformation</returns>
+       public IncrementalValuesProvider<T> FromAttribute<T>(string attributeFQN, Func<GeneratorSyntaxContext, AttributeData attributeData, CancellationToken, T> transform);
}

Usage Examples

    // regular post initalization injected attribute
    ctx.RegisterPostInitializationOutput((c) => c.AddSource("myAttribute", @"using System;
namespace AutoNotify
{
   [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
   sealed class AutoNotifyAttribute : Attribute
   {
       public AutoNotifyAttribute()
       {
       }
       public string PropertyName { get; set; }
   }
"));
    
    // search by existing / post init injected attribute
    var x = ctx.SyntaxProvider.FromAttribute("AutoNotify.AutoNotifyAttribute", (syntaxContext, attribData, ct) => ...);

Error handling / resolution

There are multiple possible resolution strategies to the attribute look up (should it exist in source only? can it exist in a library?) and we'll take an opinionated stance on this, rather than provide overloads that provide these different behaviours. If an author wants full control they can use the exisiting lower level primitives as today.

Open Questions

Should AttributeData be on the Context or passed as another lambda parameter?

Metadata

Metadata

Labels

Area-CompilersConcept-APIThis issue involves adding, removing, clarification, or modification of an API.Feature - Source GeneratorsSource GeneratorsFeature Requestapi-needs-workAPI needs work before it is approved, it is NOT ready for implementation

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions