Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Source Generators support .NET Standard 2.1? #47087

Closed
lthoa opened this issue Aug 24, 2020 · 32 comments
Closed

Source Generators support .NET Standard 2.1? #47087

lthoa opened this issue Aug 24, 2020 · 32 comments

Comments

@lthoa
Copy link

lthoa commented Aug 24, 2020

Source Generators only support being loaded into consuming libraries as .NET Standard 2.0 components today.
I really need it to support .NET Standard 2.1 to use Grpc.Net.Client.Web.
Do you have any solution to use Grpc.Net.Client.Web (netstandard2.1) with Source Generator?
Do you have a plan for .NET Standard 2.1?

Thank you.

@RikkiGibson
Copy link
Contributor

/cc @chsienki

@sharwell
Copy link
Member

sharwell commented Aug 24, 2020

.NET Standard 2.1 can be used under the following conditions:

  1. The generator will work during builds with .NET tooling (e.g. dotnet build or dotnet msbuild), but will not work for builds with .NET Framework tooling (e.g. msbuild)
  2. The generator will not work for IDE scenarios, which includes builds within Visual Studio and all IntelliSense functionality

The second limitation in particular seems sufficiently problematic to say that the scenario is not recommended.

@lthoa
Copy link
Author

lthoa commented Aug 24, 2020

.NET Standard 2.1 can be used under the following conditions:

  1. The generator will work during builds with .NET tooling (e.g. dotnet build or dotnet msbuild), but will not work for builds with .NET Framework tooling (e.g. msbuild)
  2. The generator will not work for IDE scenarios, which includes builds within Visual Studio and all IntelliSense functionality

The second limitation in particular seems sufficiently problematic to say that the scenario is not recommended.

Thank you, But I am using Visual Studio :(

@RikkiGibson
Copy link
Contributor

It feels like ideally the part of the functionality of Grpc.Net.Client.Web that is required at generation time could be spun off into a netstandard2.0 package.

@lthoa
Copy link
Author

lthoa commented Aug 25, 2020

the functionality of Grpc.Net.Client.Web

Thank @RikkiGibson ,
I have also thought of this solution. Create the function of Grpc.Net.Client.Web source code using T4.
My projects have previously used T4 to generate source code. But the T4 also has its limitations that made me switch to Source Generators.

@sharwell
Copy link
Member

sharwell commented Aug 25, 2020

@lthoa It's not clear what the limitation here is. According to grpc/grpc-dotnet#905, Grpc.Net.Client.Web doesn't target netstandard2.0 because it doesn't support the HttpResponseMessage.TrailingHeaders property. However, this limitation would not apply to source generators because the source generator can't use HttpClient at all. Source generators are not allowed to perform I/O operations outside of the APIs provided by the compiler.

@lthoa
Copy link
Author

lthoa commented Aug 25, 2020

Thank @sharwell ,

I really like Source Generators and want to use it but we don't have a channel to discuss or learn so I have to ask you here.
Sorry for bothering you

I need to generate classes that inherits from an interface. That interface is netcoreapp3.1 library.

// netcoreapp3.1 liblary already exist
public interface IDataMigration
{
        ISchemaBuilder SchemaBuilder { get; set; }
}

// Using Source Generators
public class ObjectMigrations : IDataMigration
{     
     // code
}

Is posible to use Source Generators with Visual Studio in this case?
Can you help me.

Thank you,

@PathogenDavid
Copy link
Contributor

@lthoa It's a bit hard to understand what you're trying to accomplish from that limited example, but are you trying to use reflection to inspect IDataMigration to generate ObjectMigrations? You should use the symbol metadata provided by the compiler instead. (IE: Compilation.GetTypeByMetadataName) It doesn't seem like your source generator should actually need a reference to the library containing IDataMigration unless I'm missing something.

You might find it useful to look at @davidwengier's "Auto Notify" sample here: https://sourcegen.dev/ (Select it from the dropdown.)

@davidwengier
Copy link
Contributor

davidwengier commented Aug 25, 2020

@lthoa Your source generator outputs code that is compiled in the context of the project that consumes it. So if your consuming project can see the IDataMigration interface, then you can generate source that requires it without your source generator needing to reference the library that it is contained in.

A good example of this is the "Dependency Injection" sample in sourcegen.dev as it can generate code that creates instances of Foo and returns references to IFoo, but those types don't exist anywhere in the generator itself.

@lthoa
Copy link
Author

lthoa commented Aug 25, 2020

Thank you very much @PathogenDavid, @davidwengier .
I will try sourcegen.dev now

@sharwell sharwell added the Resolution-Answered The question has been answered label Aug 25, 2020
@RikkiGibson
Copy link
Contributor

That's a really cool project @davidwengier 😄

@trampster
Copy link

Given that Source Generators seem ideal for serializers and serializers need Span to be efficient, And .net Standard 2.0 doesn't support Span

I'm working on a Source Generator Json Serailizer and I need .net Standard 2.1 to be able to make a performant serializer. This limitation is a huge problem for me.

@PathogenDavid
Copy link
Contributor

@trampster The actual source generator does not necessarily need access to the types used in the code it emits.

Also you can use System.Memory to access Span<T> and related types in older frameworks.

@RikkiGibson
Copy link
Contributor

RikkiGibson commented Sep 15, 2020

Indeed, if the compiler or extensions needed to actually load netstandard2.1 libraries and not just their metadata, it would be very difficult to develop applications that use such a library using Visual Studio 😉

@trampster
Copy link

I assume this is because Visual Studio still targets .net framework and has not be ported to .net core/.NET 5, when can we expect Visual Studio to move to .net core/.NET 5?

@sharwell
Copy link
Member

@trampster the source generator and the code produced by the source generator do not need to run on the same framework. You can use a netstandard2.0 source generator to produce code that only runs on netstandard2.1.

@trampster
Copy link

@sharwell thanks, I got that from @RikkiGibson comment.

My source generator was depending on a .net standard 2.1 lib. I have broken that dependency for now by pulling in only the source file I need rather than the whole project, but it's far from ideal.

Please answer my question, is this limitation caused by Visual Studio not having been ported to .net core/.NET 5. And if so when can we expect this to happen so this limitation can be lifted.

@sharwell
Copy link
Member

The compiler supports execution on .NET Framework even from the command line. While I cannot guarantee that this will not change, I would be very surprised to see this change in version 3.x.

@dominikjeske
Copy link

@sharwell Is this behaviour will change in Visual Studio 2022? I'm talking about support for .NET Standard 2.1/.NET 5+

@sharwell
Copy link
Member

sharwell commented Aug 18, 2021

@dominikjeske I am not aware of any plans which have the potential to support a source generator targeting anything but .NET Standard 2.0 for the duration of Visual Studio 2022.

The source generator requirement to target netstandard2.0 has no impact on the ability of a source generator to produce code for net5.0 and net6.0. Several source generators only support net5.0 and newer, but the source generator itself still targets netstandard2.0.

@trampster
Copy link

trampster commented Aug 18, 2021

Imagine the situation where you have a source generator for a net5.0 lib or .Net Standard 2.1 lib which detects calls to it's library which can be performed at compile time (saving huge amounts of time at runtime).

It then does those calls at compile time by calling the .net5.0 lib and generates code which shortcuts the library call.

This is currently impossible because of this limitation.

@nczsl
Copy link

nczsl commented Sep 11, 2021

Please let source generators support netstandard2.1 and. Net5.0, because there are c# developers under vscode who can't use vs's smart sensing and add analyzers. They just need to put the generated code in the / obj directory for use

@sharwell
Copy link
Member

@trampster any chance you could create a sample to demonstrate this?

@nczsl can you provide a sample as well? Note that vscode support for source generators is likely a different request altogether, and wouldn't be related to the netstandard2.0 requirement.

@nczsl
Copy link

nczsl commented Sep 12, 2021

@sharwell My requirements are as follows. For example, there is a basic project, which is an entity project that can be shared by clients and servers. There are usually some business entities in it. Then a generator project can reference this entity and wrap it, so as to do some mechanical and repetitive things, and this generator class does not have to be an analyzer, It should still be a regular project, but the generated code is automatically generated to the. /obj directory through the generator. Like grpc, I think it may be a popular function of the generator, which may better reflect its value. Compared with the analyzer, it is more regular and easier to use.

@nczsl
Copy link

nczsl commented Sep 12, 2021

According to the current generated code generation method, we can know that the generator can intercept and parse the information of any change in the entity project, so its generation logic is based on the business descriptive project referenced by it, which is a dependency, so it can automatically respond to its changes in a certain range, In this way, developers only need a smaller amount of code to describe more concise and business-oriented code. Other cumbersome and repetitive tasks can be completed by the generator packaging it, such as technical platform docking, framework requirements, and other codes can be completed automatically in this way. So it's really useful. It is not necessary to inject and modify through a complex generator, which is easier, more intuitive and simpler, because it means that you do not need to provide various placeholder codes in advance, such as partial class, partial method interface, etc. There is no need to do complex code awareness so that the IDE can synchronize developers' code changes.

@nczsl
Copy link

nczsl commented Sep 13, 2021

I thought it over again and found that partial is really difficult or missing for the generator, which is very important. Moreover, I believe that the generator's incoming dependencies cannot be limited to CSharp's code metadata. It should also include SQL, CSV and other documents. Sometimes it is very useful to generate code directly through regular parsing of SQL scripts, so the generator is really very useful. I still insist that generating code directly to the. /obj directory, like grpc, is a very useful scheme and should be an option for users like the analyzer.

@taori
Copy link

taori commented Apr 8, 2024

I am still experiencing this as sort of an issue. i have one class library and a library that contains the generator. the generator references the library and is also part of the generator nupkg. in order to use the classlib in the generator i need to multitarget as net6;netstandard2.0 - now that puts me in a situation where i have to backport api's that don't exist in netstandard2.0 or throw them on netstandard2.0 as not supported. That is rather inconvenient. I hope i am explaining it well enough.

@damienhoneyford
Copy link

The biggest limitation in restricting the generator to netstandard2.0 is that Span/ReadOnlySpan support is severely restricted, even with the System.Memory package in play, StringBuilder, TextWriter, etc. don't know how to deal with these types, leaving you with no way to write a 'high performance' generator -- this really needs addressing, given the focus on performance that the .NET team has taken in recent years.

@sharwell
Copy link
Member

sharwell commented Apr 22, 2024

... leaving you with no way to write a 'high performance' generator ...

@damienhoneyford I am not aware of any case to date where those APIs resulted in being responsible for the observable overhead of a source generator. I'd be happy to review if you can provide data to suggest otherwise, but this seems to be hypothetical concern more than an empirical one.

We have had discussions recently about new APIs to allow more efficient construction of SourceText during generator output stages, but these changes would also not rely on anything newer than netstandard2.0.

@CyrusNajmabadi
Copy link
Member

I agree with Sam on this. I've done several dozen investigations into real world generators and teh perf issues that arose from them. Not a single one was due to any sort of API usage that would have gotten better with netstandard2.1. If there is a real world example we could look at, that would be helpful.

@damienhoneyford
Copy link

@damienhoneyford I am not aware of any case to date where those APIs resulted in being responsible for the observable overhead of a source generator. I'd be happy to review if you can provide data to suggest otherwise, but this seems to be hypothetical concern more than an empirical one.

I agree with Sam on this. I've done several dozen investigations into real world generators and teh perf issues that arose from them. Not a single one was due to any sort of API usage that would have gotten better with netstandard2.1. If there is a real world example we could look at, that would be helpful.

It is absolutely hypothetical you're right, and I'm happy to hear that the performance wouldn't be noticeably impacted by the use of Span-based APIs, though it does leave me somewhat confused as to why such effort was undertaken to make those APIs in the first place if they make so little difference...

@CyrusNajmabadi
Copy link
Member

though it does leave me somewhat confused as to why such effort was undertaken to make those APIs in the first place if they make so little difference...

They make a big difference in certain domains. So far, those domains have little (if any) intersection with SGs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests