dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.1k stars 1.17k forks source link

Visual Studio 17.2.6 Breaks CommunityToolkit.Mvvm #6792

Closed jamiehankins closed 2 years ago

jamiehankins commented 2 years ago

Version Used: 17.2.6

Steps to Reproduce:

  1. Create a WPF exe project targeting net6.0-windows
  2. Reference CommunityToolkit.Mvvm like so: <PackageReference Include="CommunityToolkit.Mvvm" Version="7.1.2" />
  3. Create a simple class inheriting from ObservableObject, like so:
    
    using CommunityToolkit.Mvvm.ComponentModel;

namespace ObservablePropertyTest { public partial class TestVM : ObservableObject { [ObservableProperty] private string _testString = string.Empty; } }


**Expected Behavior**:
In 17.2.5, it built and ran fine.

**Actual Behavior**:

Rebuild started... 1>------ Rebuild All started: Project: ObservablePropertyTest, Configuration: Debug Any CPU ------ Restored C:\git\ObservablePropertyTest\ObservablePropertyTest.csproj (in 2 ms). 1>C:\git\ObservablePropertyTest\CommunityToolkit.Mvvm.SourceGenerators\CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator__KnownINotifyPropertyChangedOrChangingArgs.cs(12,27,12,70): error CS0101: The namespace 'CommunityToolkit.Mvvm.ComponentModel.Internals' already contains a definition for 'KnownINotifyPropertyChangedOrChangingArgs' 1>C:\git\ObservablePropertyTest\CommunityToolkit.Mvvm.SourceGenerators\CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator__KnownINotifyPropertyChangedOrChangingArgs.cs(7,6,7,51): error CS0579: Duplicate 'global::System.CodeDom.Compiler.GeneratedCode' attribute 1>C:\git\ObservablePropertyTest\CommunityToolkit.Mvvm.SourceGenerators\CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator__KnownINotifyPropertyChangedOrChangingArgs.cs(8,6,8,52): error CS0579: Duplicate 'global::System.Diagnostics.DebuggerNonUserCode' attribute 1>C:\git\ObservablePropertyTest\CommunityToolkit.Mvvm.SourceGenerators\CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator__KnownINotifyPropertyChangedOrChangingArgs.cs(9,6,9,69): error CS0579: Duplicate 'global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage' attribute 1>C:\git\ObservablePropertyTest\CommunityToolkit.Mvvm.SourceGenerators\CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator__KnownINotifyPropertyChangedOrChangingArgs.cs(10,6,10,51): error CS0579: Duplicate 'global::System.ComponentModel.EditorBrowsable' attribute 1>C:\git\ObservablePropertyTest\CommunityToolkit.Mvvm.SourceGenerators\CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator__KnownINotifyPropertyChangedOrChangingArgs.cs(11,6,11,29): error CS0579: Duplicate 'global::System.Obsolete' attribute 1>C:\git\ObservablePropertyTest\CommunityToolkit.Mvvm.SourceGenerators\CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator\ObservablePropertyTest.TestVM.cs(12,23,12,33): error CS0102: The type 'TestVM' already contains a definition for 'TestString' 1>Done building project "ObservablePropertyTest_yynlzhol_wpftmp.csproj" -- FAILED. ========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========



It appears that somehow the CommunityToolkit.Mvvm source generators are being run twice.

If you create a WPF class library, things work fine. They're only broken in a WPF app.

Here is my test project:
[ObservablePropertyTest.zip](https://github.com/dotnet/roslyn/files/9097397/ObservablePropertyTest.zip)
rasyidf commented 2 years ago

Is the fix for this available in the .NET 7 preview SDK at this point?

Still occurred in latest .NET 7 Preview

Gakk commented 2 years ago
<Target Name="RemoveDuplicateAnalyzers" BeforeTargets="CoreCompile">
    <!-- Work around https://github.com/dotnet/wpf/issues/6792 -->

    <ItemGroup>
        <FilteredAnalyzer Include="@(Analyzer->Distinct())" />
        <Analyzer Remove="@(Analyzer)" />
        <Analyzer Include="@(FilteredAnalyzer)" />
    </ItemGroup>
</Target>

Thanks @rainersigwald for this solution. It looks like it fixed the issue with the duplicate analyzers 🙂👍

Unfortunately it also looks like it may have an unattended side effect 🤔 I have a WPF application, and it has a constructor with a parameter:

public partial class App : System.Windows.Application
{
    public App(SplashScreen splash)
    {
        // (removed for readability)
    }
}

MSBuild then generates a partial class with Main(), but this now uses a constructor without parameters - which in my case does not exist:

// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
// (...)
public partial class App : System.Windows.Application
{
    // (removed for readability)

    [System.STAThreadAttribute()]
    [System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "6.0.8.0")]
    public static void Main() {
        LocusMobile.Client.App app = new LocusMobile.Client.App();
        app.InitializeComponent();
        app.Run();
    }
}

Resulting in:

error CS7036: There is no argument given that corresponds to the required formal parameter 'splash' of 'App.App(SplashScreen)'

Anyone other that has experienced this with the workaround? Or also has a constructor with a parameter that is not affected by this workaround, and can confirm that this issue must come from something else?

I experienced this issue with the generators when switching from legacy project file to SDK style project file, so my error might be related to something else as well...

ThomasGoulet73 commented 2 years ago

Hey @Gakk, I doubt that your issue is related to analyzers/generators.

This is likely the cause: I experienced this issue with the generators when switching from legacy project file to SDK style project file

Without a repro I can only speculate but it looks like you use your own Main entry point instead of the generated App.Main and pass a SplashScreen to the constructor of App. In your legacy project file, App.xaml was probably included as Page instead of ApplicationDefinition which meant that App.Main was never generated. If you do not use the generated App.Main, you need to set the MSBuild property EnableDefaultApplicationDefinition to false in your project. If this does not fix your issue, please open a new Github issue without a repro project since it is probably unrelated to this one.

Thanks.

ThomasGoulet73 commented 2 years ago

This issue should now be fixed in .Net SDK 6.0.9 released today.

ecxdev commented 2 years ago

I had the same problem today! How to fix it?

`Version: 6.0.401 Commit: 0906eae6f8

Runtime Environment: OS Name: Windows OS Version: 10.0.19044 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\6.0.401\

global.json file: Not found

Host: Version: 6.0.9 Architecture: x64 Commit: 163a63591c

.NET SDKs installed: 6.0.401 [C:\Program Files\dotnet\sdk]

.NET runtimes installed: Microsoft.AspNetCore.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 3.1.22 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.22 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]`

virzak commented 2 years ago

@ecxdev If you have .NET 7 preview-7 upgrade to .NET 7 RC-1 and it should fix it. Either that or specify version 6 in global.json

ecxdev commented 2 years ago
<Target Name="RemoveDuplicateAnalyzers" BeforeTargets="CoreCompile">
    <!-- Work around https://github.com/dotnet/wpf/issues/6792 -->

    <ItemGroup>
        <FilteredAnalyzer Include="@(Analyzer->Distinct())" />
        <Analyzer Remove="@(Analyzer)" />
        <Analyzer Include="@(FilteredAnalyzer)" />
    </ItemGroup>
</Target>

The project was rebuilt successfully when I deleted this previously inserted code from the project file.