NeVeSpl / NTypewriter

File/code generator using Scriban text templates populated with C# code metadata from Roslyn API.
https://nevespl.github.io/NTypewriter/
MIT License
117 stars 24 forks source link

Failed to compile user code (System.Collections) #102

Closed Auirsblade closed 5 months ago

Auirsblade commented 5 months ago

Getting an error when trying to get SourceGenerator to use an .nt.cs user code file. I'm referencing System.Collections.Generic for the use of List, but it doesn't seem to be finding it as I get the following error:

14>NTypewriterCustom.nt.cs(13,41): Error CS0012 : The type 'List<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Collections, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

The user code is a relatively straightforward workaround for handling multiple nested generic types:

using System;
using System.Linq;
using System.Collections.Generic;
using NTypewriter.CodeModel;
using NTypewriter.CodeModel.Functions;

namespace _
{
    class NTypewriterCustom
    {
        public static string MapTypeName(IType type) 
        {
            List<IType> typeArguments = type.TypeArguments.ToList();
            switch (typeArguments.Count)
            {
                case 2:
                    if (type.Name == $"KeyValuePair<{typeArguments[0]}, {typeArguments[1]}>")
                    {
                        return $"{{key: {typeArguments[0]}, value: {typeArguments[1]}}}";
                    }
                    break;
                case 1:
                    if (type.IsEnumerable)
                    {
                        return $"{MapTypeName(typeArguments[0])}[]";
                    }
                    break;
            }
            return type.ToTypeScriptType();
        }  
    }
}

Is there a way to designate the target assembly versions? My current thought is that it has something to do with the SDK Roslyn is targeting, since it seems to just be hitting the most recent version, as on my computer it's looking for .NET 8, but for other developers it's hitting .NET 6.

Edit: Reading through #84 it seems like this issue is similar, since it only happens for me when running in Rider (no NTypewriter extension), but not in Visual Studio with the extension installed. For extensionless implementations, do all referenced assemblies need to be included in the SourceGenerator project?

NeVeSpl commented 5 months ago

84 is not similar unfortunately. VS addin and source generator are using exactly the same runtime/code for compiling .nt.cs files. Theoretically the set of available assemblies should be the same, but environments are completely different VS is still on .net4.8, Rider probably on net.core. Your first thought was good, somehow source generator run by Rider is trying to do compilation targeting net.core, but all referenced assemblies are provided for net.standard, and I do not see any line that would tell compiler to explicitly target net.standard:

https://github.com/NeVeSpl/NTypewriter/blob/8c015cbd6ef1a93afb0b4799e3a4f97eeb61071d/NTypewriter.Runtime/UserCode/UserCodeLoader.cs#L157-L183

Auirsblade commented 5 months ago

Yea that certainly makes sense, Rider does seem to be trying to compile using Core even though when peeking at the assembly explorer it recognizes the NTypewriter.SourceGenerator assembly as .NET Standard v2... To confirm your theory I uninstalled the extension from VS and it still compiled just fine, so it's just a Rider issue.

NeVeSpl commented 5 months ago

The problem may be in how assemblies are resolved for the compilation, in one of the future releases I will try to replace manually setting references to assemblies with this library:

https://github.com/jaredpar/basic-reference-assemblies

It looks promising, it should give more deterministic results, and hopefully the same results for VS/48 vs Rider/.core, but I wonder if it will work with Blazor .... but that is different story.

Auirsblade commented 5 months ago

Another interesting tidbit - I ran the source generator code through CI, and jenkins also failed to build it. Seeing that, I figured I'd try running it through VS via the terminal dotnet build command and it also failed, so there must be something very specific about what VS does when it builds that's different than the usual dotnet build?

Update: I then ran MSBuild from rider and it works. So it seems to be an MSBuild vs dotnet build issue.

It seems the issue is indeed core/framework. dotnet build is using this and fails (both locally and via CI): MSBuild version 17.8.3+195e7f5a3 for .NET while MSBuild uses this and works (in VS and Rider): MSBuild version 17.8.5+b5265ef37 for .NET Framework

NeVeSpl commented 5 months ago

Problem is fixed in NTypewriter.SourceGenerator v0.3.2

Auirsblade commented 5 months ago

Sweet I'll get it tested once the CI finishes. Cheers!

Auirsblade commented 5 months ago

Updated to the latest nuget packages for .Runtime and .SourceGenerator and still having compiling issues with MSBuild version 17.8.3+195e7f5a3 for .NET, I'll poke around and run the source code locally and see if I can get something working.

NeVeSpl commented 5 months ago

That is impossible :D. The same error message? Did you delete obj and bin folders to make sure that something is not cached? I was able to reproduce problem, and indeed there was difference between MSbuild for .NET vs .NET Framework, but using basic-reference-assemblies seems to resolved problem.

Auirsblade commented 5 months ago

I ran a clean, but didn't manually delete bin and obj, I can try that too :)

Auirsblade commented 5 months ago

I ran a clean, but didn't manually delete bin and obj, I can try that too :)

Yep same result after bin/obj delete and rebuild