MessagePack-CSharp / MessagePack-CSharp

Extremely Fast MessagePack Serializer for C#(.NET, .NET Core, Unity, Xamarin). / msgpack.org[C#]
Other
5.71k stars 696 forks source link

MPC Support for global using when targeting older frameworks. #1353

Closed cdanek closed 2 years ago

cdanek commented 2 years ago

Is your feature request related to a problem? Please describe.

I have a class library targeting .NET 4.7.2, for which I'm leveraging the AOT generation from MPC so that the library is usable in Unity with IL2CPP. I thought I'd be smarter than I am and leverage the new language features in C#10 (which I really like to use in other projects) by setting the langversion to 10.0 in the csproj file. Unfortunately, after quite a bit of hacking and experimentation, I've discovered that classes that do not have usings (and instead leverage global usings elsewhere) behave erratically / not at all when using MPC.

Describe the solution you'd like

MPC generates code for objects that are contained in files that have global usings.

Additional context

Here is a minimal reproduction of the problem.

Normal behaviour:

using System;
using MessagePack;

[MessagePackObject]
public class MyClass
{
    [Key(0)] public Guid Value { get; set; }
}

Generating code (using dotnet mpc -i myproj.csproj -o generated.cs) works as expected:

Project Compilation Start:ConsoleApp1
Project Compilation Complete:00:00:00.3523256
Method Collect Start
Method Collect Complete:00:00:00.0747810
Output Generation Start
[Out]generated.cs
Output Generation Complete:00:00:00.0106997

Changing this to the following 2 files:

// File 1 - Program.cs
global using System;
global using MessagePack;
Console.WriteLine("Hello, World!");

// File 2 - MyClass.cs
[MessagePackObject]
public class MyClass
{
    [Key(0)] public Guid Value { get; set; }
}

Yields:

Project Compilation Start:ConsoleApp1
Project Compilation Complete:00:00:00.2841137
Method Collect Start
Method Collect Complete:00:00:00.0030308
Output Generation Start
[Out]generated.cs
Generated result is empty, unexpected result?                         // FAILURE HERE
Output Generation Complete:00:00:00.0050481

Other erratic examples (not as easy to reproduce, but similar setup) have error messages like:

Project Compilation Start:ConsoleApp1
Project Compilation Complete:00:00:00.3308229
Method Collect Start
Fail in console app running on MessagepackCompiler.RunAsync
MessagePackCompiler.CodeAnalysis.MessagePackGeneratorResolveFailedException: all public members must mark KeyAttribute or IgnoreMemberAttribute. type: global::TestConsoleApp4.BigDecimal member:Mantissa
   at MessagePackCompiler.CodeAnalysis.TypeCollector.GetObjectInfo(INamedTypeSymbol type) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 679
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectObject(INamedTypeSymbol type) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 580
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectCore(ITypeSymbol typeSymbol) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 381
   at MessagePackCompiler.CodeAnalysis.TypeCollector.Collect() in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 301
   at MessagePackCompiler.CodeGenerator.GenerateFileAsync(Compilation compilation, String output, String resolverName, String namespace, Boolean useMapMode, String multipleIfDirectiveOutputSymbols, String[] externalIgnoreTypeNames) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeGenerator.cs:line 64
   at MessagePack.Generator.MessagepackCompiler.RunAsync(String input, String output, String conditionalSymbol, String resolverName, String namespace, Boolean useMapMode, String multipleIfDirectiveOutputSymbols, String[] externalIgnoreTypeNames) in D:\a\1\s\src\MessagePack.Generator\MessagepackCompiler.cs:line 65
   at ConsoleAppFramework.ConsoleAppEngine.RunCore(ConsoleAppContext ctx, Type type, MethodInfo methodInfo, String[] args, Int32 argsOffset)
Project Compilation Start:ConsoleApp1
failed to get metadata of System.Threading.Tasks.Task`1
failed to get metadata of System.Threading.Tasks.Task
failed to get metadata of System.Runtime.Serialization.IgnoreDataMemberAttribute
Project Compilation Complete:00:00:00.3282818
Method Collect Start
Fail in console app running on MessagepackCompiler.RunAsync
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at MessagePackCompiler.CodeAnalysis.TypeCollector.GetObjectInfo(INamedTypeSymbol type) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 586
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectObject(INamedTypeSymbol type) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 580
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectCore(ITypeSymbol typeSymbol) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 381
   at MessagePackCompiler.CodeAnalysis.TypeCollector.Collect() in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 301
   at MessagePackCompiler.CodeGenerator.GenerateFileAsync(Compilation compilation, String output, String resolverName, String namespace, Boolean useMapMode, String multipleIfDirectiveOutputSymbols, String[] externalIgnoreTypeNames) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeGenerator.cs:line 64
   at MessagePack.Generator.MessagepackCompiler.RunAsync(String input, String output, String conditionalSymbol, String resolverName, String namespace, Boolean useMapMode, String multipleIfDirectiveOutputSymbols, String[] externalIgnoreTypeNames) in D:\a\1\s\src\MessagePack.Generator\MessagepackCompiler.cs:line 65
   at ConsoleAppFramework.ConsoleAppEngine.RunCore(ConsoleAppContext ctx, Type type, MethodInfo methodInfo, String[] args, Int32 argsOffset)
Project Compilation Start:ISG-Shared
Project Compilation Complete:00:00:00.7357822
Method Collect Start
Fail in console app running on MessagepackCompiler.RunAsync
MessagePackCompiler.CodeAnalysis.MessagePackGeneratorResolveFailedException: Serialization Object must mark MessagePackObjectAttribute. type: global::KaimiraGames.ISG.Shared.Models.Idle.GeneratorKey
   at MessagePackCompiler.CodeAnalysis.TypeCollector.GetObjectInfo(INamedTypeSymbol type) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 589
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectObject(INamedTypeSymbol type) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 580
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectCore(ITypeSymbol typeSymbol) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 381
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectGeneric(INamedTypeSymbol type) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 496
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectCore(ITypeSymbol typeSymbol) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 360
   at MessagePackCompiler.CodeAnalysis.TypeCollector.GetObjectInfo(INamedTypeSymbol type) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 723
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectObject(INamedTypeSymbol type) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 580
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectCore(ITypeSymbol typeSymbol) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 381
   at MessagePackCompiler.CodeAnalysis.TypeCollector.Collect() in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 301
   at MessagePackCompiler.CodeGenerator.GenerateFileAsync(Compilation compilation, String output, String resolverName, String namespace, Boolean useMapMode, String multipleIfDirectiveOutputSymbols, String[] externalIgnoreTypeNames) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeGenerator.cs:line 64
   at MessagePack.Generator.MessagepackCompiler.RunAsync(String input, String output, String conditionalSymbol, String resolverName, String namespace, Boolean useMapMode, String multipleIfDirectiveOutputSymbols, String[] externalIgnoreTypeNames) in D:\a\1\s\src\MessagePack.Generator\MessagepackCompiler.cs:line 65
   at ConsoleAppFramework.ConsoleAppEngine.RunCore(ConsoleAppContext ctx, Type type, MethodInfo methodInfo, String[] args, Int32 argsOffset)

In each of the 3 above examples, the classes were (I presume) formatted correctly, as changing the lang version to 8.0 or "default" and reverting use of global using resolved the MPC errors.

pCYSl5EDgo commented 2 years ago

mpc's Roslyn version is now 3.10.0 C#10 seems to be supported since 4.

To solve this problem we need to update the version. I am worried that the VS2019 16.11users will not be able to use mpc aot.

cdanek commented 2 years ago

Thank you for the comment. Is it possible to upgrade to a higher Roslyn version for my own MPC use in C#10 projects?

pCYSl5EDgo commented 2 years ago

Ready to merge

AArnott commented 2 years ago

mpc carries its own roslyn dependencies with it, so it shouldn't be a problem to raise the target roslyn version. When/if we add roslyn Source Generators support though, such a thing would be of more concern. But I don't expect that to play well with Unity.

AArnott commented 2 years ago

Does #1368 finish fixing this, @pCYSl5EDgo?

pCYSl5EDgo commented 2 years ago

I think the fix is done. The C#10 feature test should be added to Sandbox or TestData2.

AArnott commented 2 years ago

Great. Are you planning to add the test, @pCYSl5EDgo ?

pCYSl5EDgo commented 2 years ago

@AArnott Yes. #1371