C# Extension Not Detecting Generated Classes from Roslyn Source Generators Using AdditionalTextsProvider

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

When using a Roslyn incremental source generator that consumes files via AdditionalTextsProvider (from IncrementalGeneratorInitializationContext), the C# extension in Cursor does not recognize the generated classes. This manifests as:

  1. Red squiggles indicating the type cannot be found
  2. Missing IntelliSense/autocomplete for the generated class
  3. “Type not found” errors in the editor

However:

  • The code compiles successfully with dotnet build
  • Other IDE extensions (e.g., DotRush) correctly detect and provide IntelliSense for the generated classes
  • The generated files are present in the build output

This suggests the C# extension’s language service is not properly processing or indexing the generated source files from AdditionalTextsProvider-based generators.

Workaround

Adding <CompilerGeneratedFilesOutputPath> to the csproj helps in some cases, but the issue persists. The workaround is not reliable and doesn’t fully resolve the problem.

Additional Information

  • The generator uses IIncrementalGenerator (the recommended modern API)
  • The generator correctly implements AdditionalTextsProvider pattern
  • Generated files are created in the expected location (obj/GeneratedFiles/ or similar)
  • The issue is specific to generators using AdditionalTextsProvider; other generators may work
  • DotRush extension correctly handles this scenario, suggesting the issue is with Cursor’s C# extension implementation

Steps to Reproduce

  1. Create a new .NET project
  2. Add a Roslyn source generator project that uses AdditionalTextsProvider
  3. Reference the generator in the main project
  4. Create a JSON file and mark it as AdditionalFiles in the csproj
  5. Use the generated class in code
  6. Observe that Cursor’s C# extension shows errors, while the code compiles fine

Minimal Reproduction

1. Source Generator Project (SampleGenerator.csproj)

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <LangVersion>latest</LangVersion>
    <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
    <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
    <IsRoslynComponent>true</IsRoslynComponent>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
  </ItemGroup>
</Project>

2. Source Generator Code (SampleGenerator.cs)

using System.Collections.Immutable;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;

namespace SampleGenerator;

[Generator]
public class SampleGenerator : IIncrementalGenerator
{
    private const string JsonFileName = "sample-data.json";

    public void Initialize(IncrementalGeneratorInitializationContext context)
    {
        // Provider that looks for JSON files via AdditionalTextsProvider
        var jsonFile = context.AdditionalTextsProvider.Where(static file =>
            Path.GetFileName(file.Path)?.Equals(JsonFileName, StringComparison.Ordinal) == true
        );

        // Register the output source
        context.RegisterSourceOutput(
            context.CompilationProvider.Combine(jsonFile.Collect()),
            (ctx, t) => GenerateCode(ctx, t.Right)
        );
    }

    private static void GenerateCode(
        SourceProductionContext ctx,
        ImmutableArray<AdditionalText> jsons
    )
    {
        if (jsons.Length == 0)
        {
            return;
        }

        var additionalText = jsons.First();

        if (additionalText.GetText()?.ToString() is { } jsonText)
        {
            try
            {
                var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonText);

                var code = $@"// <auto-generated />
namespace SampleApp;

public static class GeneratedClass
{{
    public static string GetValue(string key)
    {{
        return key switch
        {{
{string.Join("\n", data?.Select(kvp => $"            \"{kvp.Key}\" => \"{kvp.Value}\",") ?? Array.Empty<string>())}
            _ => string.Empty
        }};
    }}
}}
";

                ctx.AddSource("GeneratedClass.g.cs", code);
            }
            catch (Exception ex)
            {
                ctx.ReportDiagnostic(
                    Diagnostic.Create(
                        new DiagnosticDescriptor(
                            "SG001",
                            "JSON Parse Error",
                            $"Failed to parse {JsonFileName}: {{0}}",
                            "SampleGenerator",
                            DiagnosticSeverity.Error,
                            true
                        ),
                        Location.None,
                        ex.Message
                    )
                );
            }
        }
    }
}

3. Main Project (SampleApp.csproj)

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
    <!-- This helps some language services discover generated files -->
    <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
  </PropertyGroup>
  <ItemGroup>
    <!-- Mark JSON file as AdditionalFiles for the generator -->
    <AdditionalFiles Include="sample-data.json" />
  </ItemGroup>
  <ItemGroup>
    <!-- Reference the source generator -->
    <ProjectReference
      Include="..\SampleGenerator\SampleGenerator.csproj"
      ReferenceOutputAssembly="false"
      OutputItemType="Analyzer"
    />
  </ItemGroup>
</Project>

4. JSON Data File (sample-data.json)

{
  "Hello": "World",
  "Foo": "Bar",
  "Test": "Value"
}

5. Usage Example (Program.cs)

using SampleApp;

// This line shows red squiggles in Cursor's C# extension
// but compiles successfully and works in DotRush
var value = GeneratedClass.GetValue("Hello");
Console.WriteLine(value); // Should output "World"

Expected Behavior

The C# extension should:

  1. Detect the generated GeneratedClass type
  2. Provide IntelliSense/autocomplete for the class
  3. Show no errors or warnings for valid usage
  4. Recognize the class immediately after build (or with proper language service refresh)

Operating System

MacOS

Current Cursor Version (Menu → About Cursor → Copy)

Version: 2.2.36
VSCode Version: 1.105.1
Commit: 55c9bc11e99cedd1fb93fbb7996abf779c583150
Date: 2025-12-18T06:25:21.733Z
Electron: 37.7.0
Chromium: 138.0.7204.251
Node.js: 22.20.0
V8: 13.8.258.32-electron.0
OS: Darwin arm64 24.6.0

Does this stop you from using Cursor

No - Cursor works, but with this issue

1 Like

Thanks for the detailed reproduction steps. I’ve raised with the extensions team. A few questions to help narrow this down:

  1. Which C# extension are you using - C# Dev Kit, OmniSharp, or the older C# (powered by OmniSharp)?
  2. Does the same setup work correctly in VS Code with the same extension?

If it works in VS Code but not Cursor with the same extension, that would point to a Cursor-specific issue. If it fails in both, it’s likely upstream. Either way, the team has been flagged on this.

The current setup that does not work is with the extension:

C# for Cursor

Identifier

anysphere.csharp

Version

1.0.1

Last Updated

2025-12-11, 15:24:54