-
Notifications
You must be signed in to change notification settings - Fork 5k
Define convention to consume and/or package analyzers #69069
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
Define convention to consume and/or package analyzers #69069
Conversation
Tagging subscribers to this area: @dotnet/area-infrastructure-libraries Issue DetailsFixes #61321 Until now we required source libraries to define ProjectReferences when As an example: This change makes it possible to define the shared framework analyzer Out-of-band projects which ship analyzers inside their produced package,
|
d14a0fe
to
08ec129
Compare
Fixes dotnet#61321 Until now we required source libraries to define ProjectReferences when an analyzer should be part of the shared framework. That strategy causes analyzer projects to leak into the ProjectReference closure and by that into a solution file. As an example: When another library references the source library that references the analyzer, the analyzer is part of the dependency closure even though it might not be required. This change makes it possible to define the shared framework analyzer projects in the NetCoreAppLibrary.props file for both the .NETCoreApp, and the AspNetCoreApp shared framework. Out-of-band projects which ship analyzers inside their produced package, continue to reference the analyzers via the `AnalyzerProject` item.
08ec129
to
a826907
Compare
...crosoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj
Show resolved
Hide resolved
so we don't apply TargetFramework filters nor do we pass in TargetFramework. | ||
When BuildProjectReferences=false we make sure to set BuildReference=false to make | ||
sure not to try to call GetTargetPath in the outerbuild of the analyzer project. --> | ||
<ProjectReference Include="@(AnalyzerReference)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why isn't this needed anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you originally added this code, source generators unnecessarily multi-targeted (by using TargetFramework
instead of TargetFrameworks
). Since then, source generators were updated to not multi-target and we do have general protection that makes sure that they only target netstandard2.0. The TargetFramework.SDK was updated to support single tfms and same as in the SDK, drops the TargetFramework metadata from ProjectReference items (to not cause unnecessary evaluations).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I couldn't remember exactly why we added this and I tried to trace it back in history and couldn't see it. I trust your judgement. Maybe a few things to try for regression purposes:
- Open the S.T.J sln and build it.
dotnet build --no-dependencies System.Text.Json.csproj
dotnet pack System.Text.Json.csproj
dotnet pack ---no-build System.Text.Json.csproj
$(LibrariesProjectRoot)System.Runtime.InteropServices\gen\Microsoft.Interop.SourceGeneration\Microsoft.Interop.SourceGeneration.csproj" | ||
OutputItemType="Analyzer" | ||
ReferenceOutputAssembly="false" /> | ||
<AnalyzerReference Include="$(LibrariesProjectRoot)System.Runtime.InteropServices\gen\LibraryImportGenerator\LibraryImportGenerator.csproj; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still need to do this in targets? Could we make libraries in the shared framework use AnalyzerReference
just like they have to declare their reference to Interop and then have libraries outside the shared framework just get it (like customer projects will, now that its in the refpack)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's eventually the goal, yes. I just yesterday discussed this with @jkoritzinsky in the infrastructure stand-up. Anything that's OOB should get the analyzers via the targeting pack and anything inside the shared framework should explicitly reference the analyzers. Devil in the details: You still need an explicit analyzer reference when you build pre net7.0 (net6.0, netstandard2.0, net462).
Therefore, we will still need to reference the analyzer for anything that is not NetCoreAppCurrent. In addition to that, Visual Studio's CPS currently has a bug that causes ProjectReferences that aren't referenced by the "main" active configuration to not be built. Because of that, I would prefer to keep the explicit analyzers reference on NetCoreAppCurrent (OOB) for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still need to do this in targets? Could we make libraries in the shared framework use AnalyzerReference just like they have to declare their reference to Interop
Just to check, you did see that this logic doesn't run inside a target, just in a targets file, right?
What you are proposing could definitely be done BUT the current logic in generators.targets already does that automatically when you either reference System.Runtime.InteropServices or System.Private.CoreLib. IMO, I would treat the LibraryImportGenerator
source generator as a transitive analyzer dependency of InteropServices and CoreLib. The current logic already does that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to check, you did see that this logic doesn't run inside a target, just in a targets file, right?
Yes. I was just thinking that if we made it easy enough for projects to opt in it might be better to have them explicitly opt into referencing the analyzer, just like they explicitly reference every other reference. It could avoid that magic/complexity in the condition, and it might reduce the number of places that actually reference the analyzer.
<!-- Support building only the reference assemblies. --> | ||
<ItemGroup Condition="'$(RefOnly)' != 'true'"> | ||
<ProjectReference Include="sfx-src.proj" OutputItemType="SharedFrameworkAssembly" /> | ||
<ProjectReference Include="sfx-gen.proj" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you double check that we still include the analyzers in the ref-pack after this change? Also the ASP.NET transport package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just verified this locally by building from a clean state and the analyzers are correctly placed into the targeting packs' and the packages' analyzers/dotnet/(cs)/ folder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I opened #69233 though as the LibraryImportGenerator might only work for C# projects and is currently not marked as lanague specific.
Fixes #61321
Fixes #69111
Until now we required source libraries to define ProjectReferences when
an analyzer should be part of the shared framework. That strategy causes
analyzer projects to leak into the ProjectReference closure and by that
into a solution file.
As an example:
When another library references the source library that references the
analyzer, the analyzer is part of the dependency closure even though it
might not be required.
This change makes it possible to define the shared framework analyzer
projects in the NetCoreAppLibrary.props file for both the .NETCoreApp,
and the AspNetCoreApp shared framework.
Out-of-band projects which ship analyzers inside their produced package,
continue to reference the analyzers via the
AnalyzerProject
item.