0

I'm working on a large code base with multiple linked projects, so I've decided to write some source generators to auto-generate some boilerplate code. My project structure looks something like this:

GeneratorProject (.NET standard 2.0 C# source generators)
^
CoreProject (.NET 8 C# class library)
^
UIProject (.NET 8 Blazor)

GeneratorProject generates code into CoreProject, and CoreProject is used by UIProject. Everything works just fine in CoreProject. For example: GeneratorProject creates a static class named MyObjects into CoreProject with a list of static readonly objects for convenience. When I write code within CoreProject, I can type MyObjects. and Intellisense will show me a list of every static object in MyObjects.

My problem: If I'm typing code within UIProject, and I type MyObjects., no such list of suggestions appears. The suggestion for even just MyObjects doesn't appear while typing that out. If I end up typing a valid object name within MyObjects, it does get recognized and compiles (no syntax errors and hovering over the fully-typed out name shows its definition like normal).

Not having those suggestions come up while typing defeats the convenience of generating these lists of static objects - the list may be very long and the names not the easiest to remember without typing suggestions. This is just one example of what I'm using generators for to illustrate the problem.

How could I get Intellisense suggestions that show me objects built by source generators within UIProject?

Things I've tried: I can emit compiler-generated files in CoreProject, and ignore those files on build. The idea came from here when researching how to solve this problem: https://github.com/dotnet/roslyn/issues/50451#issuecomment-1609304299 I add this to CoreProject.csproj:

    <PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>$(ProjectDir)_generated</CompilerGeneratedFilesOutputPath>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
        <NoWarn>1701;1702</NoWarn>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
        <NoWarn>1701;1702</NoWarn>
    </PropertyGroup>
    <Target Name="SkipSourceGeneratedFiles" BeforeTargets="CoreCompile">
        <ItemGroup>
            <Compile Remove="_generated/**/*" />
        </ItemGroup>
    </Target>

This causes all my generated files to appear in the solution explorer under the _generated folder. This does make typing suggestions work in UIProject, but a new problem appears: Visual Studio sees two copies of every generated file and shows an error (red squiggle) under every spot I reference something from a generated file. All the errors are CS0229: Ambiguity between 'MyObjects.something' and 'MyObjects.something'. The program still builds and runs just fine, since the csproj indicates anything in the _generated folder gets excluded from build, so only the real generator files get built. But most files now have false positive errors all over the place, which in the Visual Studio error list are indistinguishable from real errors, which will be unacceptable when working with a larger team. However, if there is a way to suppress CS0229 in Visual Studio, that would solve my problem enough that I could work with it.

Something else I've tried: I've been messing around with attaching GeneratorProject directly to UIProject, alongside CoreProject. This way I'd be creating generated code in both CoreProject and UIProject. The generators would work exactly how they do now for CoreProject. But I'd add code to the generators to detect if the current project has a reference to an assembly that references GeneratorProject. If it does, it'd basically generate the same files it's generating for CoreProject, but the generated files for UIProject would just reference the ones in CoreProject. An example:

The generator is creating this file in CoreProject:

namespace CoreProject.GeneratorOutput;

public static class MyObjects
{
    public static readonly SomeObject something = new("this is an example");
}

When the generator runs on UIProject, it'd check if UIProject references a project that references GeneratorProject. It does - it finds CoreProject. In the generator, I'd know what this generator created for CoreProject. So it'd generate something like this for UIProject:

namespace UIProject.GeneratorOutput;

public static class MyObjects
{
    public SomeObject something => CoreProject.GeneratorOutput.MyObjects.something;
}

This kind of pattern could work for static classes that are just a list of static objects like this, though the generator code would have to get a bit uglier. However, this MyObjects example is only one generator use case I have - I have other generators that do things like generate properties on non-static objects. This pattern wouldn't work for those - I'd have to do something like generate a class that inherits from the CoreProject class and change the property names slightly, which would get really ugly and not really usable.

Bottom line: Has anyone dealt with this issue before, and know of a workaround or a fix?

For technical details: I'm using Visual Studio 2022 Enterprise version 17.9.5, my core and UI projects are in C# and on .NET 8, and my generator project is using Microsoft.CodeAnalysis.CSharp version 4.6.0. I'd be happy to provide more info if it helps!

EDIT

I've created a minimal reproduction if this issue: https://github.com/mpagliaro98/IntellisenseTest

In the example, GeneratorProject generates a static class into CoreProject with the namespace CoreProject.GeneratorOutput. The problem can be demonstrated on Home.razor (UIProject > Components > Pages > Home.razor). You can type out the full MyObjects.something and once it's fully typed, Visual Studio recognizes it. But while you're typing, the final result doesn't appear in the text suggestions at all. But typing out CoreClass.SomeFunction(), which was not created by the generator, appears in the suggestions just fine. You can also demonstrate this in UIProject > UIProjectClass.cs, which just shows the issue on a regular cs file and not a razor file. CoreProject > CoreClass.cs also shows how this isn't a problem in the project where the generated code lives - typing out MyObjects. gives proper suggestions.

I put a block of commented-out code in CoreProject.csproj, and un-commenting that will show what I tried to do in the "things I've tried" section. Typing suggestions will work properly in UIProject with that un-commented, but now Visual Studio will think there's duplicates of every generated object, and show syntax errors even though everything compiles. You may need to clean, then build, then restart visual studio to see the syntax errors due to how Visual Studio caches generators and their output.

3
  • You can take a look at my answer about how can we handle this situation. This is actually a C# issue. Commented Apr 15, 2024 at 8:12
  • Hello, i cloned your sample code and tested in my VS2022 Enterprise 17.9.6 and was able to reproduce the issue. I noticed that somebody also reported a similar issue here. It looks like a Razor issue. I suggest you to create a issue on Github. You can also learn more about MS's roadmap and when plan to address these issues. Referred doc. Commented May 1, 2024 at 8:57
  • @DouXu-MSFT Thanks for linking to that issue! That one didn't come up in my search but it appears to be my exact same issue. I'll add any other information I have to that one Commented May 5, 2024 at 1:00

1 Answer 1

0

I am able to reproduce your issue:

enter image description here

The issue you encountered is caused by namespace-name/class-name confliction.

So, there are two ways to handle this situation:

1, Change the class name CoreProject in GeneratorProject, for example:

using System;

namespace GeneratorProject
{
    public class Class1
    {

    }
    public static class Gen_CoreProject { //You can change this class name.
        public static void testmethod() { }
    }
}

After that, you will be directly use the Gen_CoreProject class with no problem.

2, Set and use the alias of the namespace, for example:

using CoreProject;
using GenCore = GeneratorProject.CoreProject; //You can use this.
namespace UIProject
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
            GenCore.testmethod(); //And use this.
        }
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

I don't think that's exactly the issue I'm running into. I created a minimal reproduction of the issue and put it on Github: github.com/mpagliaro98/IntellisenseTest - see my edit on the main post for more info about it
@mpagliaro98 Are you sure the project you shared is correct? I didn't find the definition of the MyObjects.
MyObjects is created by the source generator, which is used by CoreProject. You'll usually need to build at least once for the source to be generated, and may need to close and re-open VS once or twice for any false positive syntax errors to go away. Here's an image of where you can see it in VS

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.