Closed Emik03 closed 1 year ago
Tagging subscribers to this area: @dotnet/area-system-text-regularexpressions See info in area-owners.md if you want to be subscribed.
Author: | Emik03 |
---|---|
Assignees: | - |
Labels: | `area-System.Text.RegularExpressions` |
Milestone: | - |
This imports every namespace
Why would you want this?
This imports every namespace
Why would you want this?
For the same reason that C# 10's global using
feature does, which is that most IDEs already show every single type and auto-import namespaces, just that this is amped up a notch. Type name conflicts do happen, but they would happen anyway if you happen to use both, and the naming conventions as described by Microsoft already discourage naming things that most definitely would conflict with other types from the standard library. I personally find that declaring using X = Y.Z;
is not that big of a deal anyway.
Regardless, I don't think it's entirely unreasonable to think that someone may run into a similar issue at some point in the future having made a source generator that just so happens to also globally import that exact namespace. It feels incredibly weird that the code compiles, but the generator doesn't, it's a pitfall waiting to happen in my opinion as was the case with me.
If you import the NS via SrcGen, then aren't you implicitly relying on the output from one SrcGen in another SrcGen? that's one of the scenarios which afaik are not supported. You can't depend on the output of one SrcGen in another SrcGen.
If you import the NS via SrcGen, then aren't you implicitly relying on the output from one SrcGen in another SrcGen? that's one of the scenarios which afaik are not supported. You can't depend on the output of one SrcGen in another SrcGen.
While this is very true, I feel that in all cases GeneratedRegexAttribute
is unambiguous. Would introducing an edgecase of "if we have no idea where GeneratedRegexAttribute
comes from, but we indeed see its exact name present, to treat it as such anyway" cause any potential regressions or problems down the road?
Seems to me a problem with Emik.SourceGenerators.Tattoo
in that it needs https://github.com/dotnet/roslyn/issues/57239 to better meet its functionality needs. In lieu of that it might want to do its generation outside of compile in an MSBuild task to ensure that happens before other generators run.
I don't think our generators should loosen their binding behavior for attributes. Take that argument to the limit - it means generators should never consider namespace in type name comparisons (since this is what every generator that wants to work with that global usings generator would need to do) and that's clearly a bad idea.
I agree with @ericstj; we should not squat on the GeneratedRegex
name and assume that it's the .NET SDK's to use regardless of namespace.
(And, as a technical aside, the Roslyn APIs we use to efficiently find relevant attributed methods expect the full namespace-qualified attribute name: https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.syntaxvalueprovider.forattributewithmetadataname?view=roslyn-dotnet-4.6.0. Use of that method is critical for generator performance.)
Thanks for the suggestion, though, and for highlighting the difficulties with this particular other generator.
This is a very valid point, and I've changed my mind regarding the change. I hope to see the mentioned issue be figured out sometime.
I'll append a workaround here in case if anyone in the future stumbles on this: While unclean, the temporary solution takes inspiration with the aforementioned suggestion regarding making it an MSBuild
task, and ultimately decided the best (albeit hacky) approach is to write to the file system directly, creating a generated file within the project root, and then only regenerating it if no file is found to have the name GlobalUsings.g.cs
such that you are able to move the file wherever you desire. This guarantees the file will exist in every context, and doesn't rely on any ordering of operations.
Thanks for considering this issue!
Description
System.Text.RegularExpressions.Generator
fails to recognize allGeneratedRegexAttribute
annotations when the importSystem.Text.RegularExpressions
is done by source generation. (see reproduction steps)This bug was discovered because the source generator had stopped working for me, and I couldn't find any resource about it not working. This was due to the fact that I was the only one to import
Emik.SourceGenerators.Tattoo
. This imports every namespace, which includesSystem.Text.RegularExpressions
.Reproduction Steps
Create files as specified by each header, and copy the contents of the code blocks into said files.
You may follow either the instructions for with or without. The one with the dependency is a more minimal example, but the other one proves that it's not my analyzer's fault.
With
Emik.SourceGenerators.Tattoo
(shorter)./SanityCheckSourceGenerators.Sample/SanityCheckSourceGenerators.Sample.csproj
./SanityCheckSourceGenerators.Sample/A.cs
Execute
dotnet build
onSanityCheckSourceGenerators.Sample
, or compile it in your IDE of choice.Without
Emik.SourceGenerators.Tattoo
(much longer; without magic dependency)./SanityCheckSourceGenerators/SanityCheckSourceGenerators.csproj
./SanityCheckSourceGenerators/Generator.cs
./SanityCheckSourceGenerators.Sample/SanityCheckSourceGenerators.Sample.csproj
./SanityCheckSourceGenerators.Sample/A.cs
Execute
dotnet build
onSanityCheckSourceGenerators.Sample
, or compile it in your IDE of choice.Expected behavior
Source-generates the method, and therefore compiles, as this log demonstrates.
Actual behavior
Doesn't source-generate the method, and therefore fails to compile since the method is no longer implemented.
SDK
7.0.304
SDK
8.0.100-preview.6.23330.14
Regression?
Unlikely. The source generator was introduced in
.NET 7
, and I tested it both on7.0.306
and8.0.100-preview.6.23330.14
. (the latest SDKs for both versions at the time of writing this)Known Workarounds
Write your own global using explicitly:
./SanityCheckSourceGenerators.Sample/GlobalUsings.cs
Now it recognizes the method. When executing
dotnet build
, the build finally passes.A real-world example of a commit that implements this is a project that I maintain, which can be seen here.
Configuration
7.0.304
/8.0.100-preview.6.23330.14
I am pretty confident this affects all environments, however I have yet to actually confirm this.
Other information
No response