dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
19k stars 4.03k forks source link

Source Generators: "CompileXaml" task fails when using source generators in WinUI 3 Project #46300

Closed kaivol closed 4 years ago

kaivol commented 4 years ago

Version Used:

Windows Version 2004 (Build 19041.388) dotnet 5.0.100-preview.7.20366.6 Microsoft Visual Studio Enterprise 2019 Preview Version 16.7.0 Preview 5.0 WinUI 3.0.0-preview2.200713.0

<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.7.0-4.final" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.0-beta1.final" PrivateAssets="all" />

Steps to Reproduce:

  1. Create a new Blank App, Packaged (WinUI in Desktop) project
  2. Add a source generator that only generates a single class with one static method:
    public void Execute(SourceGeneratorContext context)
    {
    context.AddSource("GeneratedClass", SourceText.From(@"
        namespace Generated
        {
            class GeneratedClass
            {
                public static string Text() => ""Text from generator"";
            }
        }
    ", Encoding.UTF8));
    }
  3. Call this generated method from the WinUI project's MainWindow.xaml.cs:
    private async void myButton_Click(object sender, RoutedEventArgs e)
    {
    var res = Generated.GeneratedClass.Text();
    await new ContentDialog
    {
        Content = res,
        XamlRoot = Content.XamlRoot,
    }.ShowAsync();
    }

Expected Behavior:

Project build should succeed.

Actual Behavior:

Build fails with the following errors:

Microsoft.UI.Xaml.Markup.Compiler.interop.targets(700,9): error MSB4181: The "CompileXaml" task returned false but did not log an error
MainWindow.xaml.cs(36,23,36,32): error CS0103: The name 'Generated' does not exist in the current context

Additional Information

The error only occures when you directly call the generated method:

Replacing

var res = Generated.GeneratedClass.Text();

with

var gen = Type.GetType("Generated.GeneratedClass")!;
var res = gen.GetMethod("Text", BindingFlags.Public | BindingFlags.Static)!.Invoke(null, null);

allows the project to compile without error and show the correct text in the ContentDialog.

jaredpar commented 4 years ago

At a glance I believe this is an issue in the WinUI build pipeline. Seems that when they're building their intermediate assembly (for type inspection) they're not including the source generators in that compilation request and hence the compilation is incomplete. Think they need to change their process to include source generators.

chsienki commented 4 years ago

Interesting, the issue is because we explicitly disable analyzers from running during XamlPreCompile here:

https://github.com/dotnet/msbuild/blob/22ec4fd5ab25118784f46a8e20fe1dd5b3f02a7c/src/Tasks/Microsoft.CSharp.CurrentVersion.targets#L240-L241

We can obviously fix it by turning on analyzers in pre-compile, but I assume these were disabled for perf reasons. @mavasani or @rainersigwald any recollection on this one? Looks like its been this way for some time.

I wonder if we need to add another flag that says 'run generators, but not analyzers' :( at that point we lose a lot of the free infra we got from re-using all the analyzer mechanisms directly, and I start to wonder if we should just have a dedicated /generators: flag.

chsienki commented 4 years ago

@KaiDevelopment as a temporary workaround you can add Analyzers="@(Analyzer)" on line 252 of <VisualStudioInstallPath>\MSBuild\Current\Bin\Microsoft.CSharp.CurrentVersion.targets if you feel comfortable editing the MSBuild targets.

mavasani commented 4 years ago

@chsienki https://github.com/dotnet/roslyn/issues/1622 for context

mavasani commented 4 years ago

Also adding @KirillOsenkov who initially identified the issue #1622. I am not sure what is a good solution here..

jmarolf commented 4 years ago

Analyzers should be disabled here, but I think source generators should not. An analyzer not running will not break your build but a source generator failing to run will.

mavasani commented 4 years ago

Yes, we discussed this offline and we will add a compiler switch to allow skipping only analyzers.

kaivol commented 4 years ago

@KaiDevelopment as a temporary workaround you can add Analyzers="@(Analyzer)" on line 252 of <VisualStudioInstallPath>\MSBuild\Current\Bin\Microsoft.CSharp.CurrentVersion.targets if you feel comfortable editing the MSBuild targets.

@chsienki: Thank you, it's working great.

I'll close this issue as a permanent solution is coming.

dotMorten commented 3 years ago

@mavasani. Was a permanent solution ever shipped? I'm hitting this issue with WinUI3 and the new C#/Win32 generators, and wondering what workaround to apply.