-
Notifications
You must be signed in to change notification settings - Fork 4k
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
When replacing CodeStyle analyzers do not provide Features analyzers fallback options #75534
When replacing CodeStyle analyzers do not provide Features analyzers fallback options #75534
Conversation
Also plumbs through updating the attribute throughout the various Solution and *State classes.
Use the unmapped references to update the HasSdkCodeStyleAnalyzer ProjectAttribute.
When Features analyzers are being used to replace SDK CodeStyle analyzer we need to treat them as project analyzers and not provide them with the Host's fallback options.
…analyzers. In particular we will treat Features analyzers as project analyzers when a project is using SDK CodeStyle analyzers. This mirrors the change that redirects Features analyzers in the HostStateSets. This is necessary to keep the CompilationsWithAnalyzers in sync with the statesets.
@@ -1061,6 +1093,14 @@ private OneOrMany<string> GetMappedAnalyzerPaths(string fullPath) | |||
_ => false, | |||
}; | |||
|
|||
private void UpdateHasSdkCodeStyleAnalyzers() |
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.
Is this used?
_unmappedProjectAnalyzerPaths.Add(fullPath); | ||
|
||
// Determine if we started using SDK CodeStyle analyzers while access to _unmappedProjectAnalyzerPaths is gated. | ||
containsSdkCodeStyleAnalyzers = _unmappedProjectAnalyzerPaths.Any(IsSdkCodeStyleAnalyzer); |
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 we do containsSdkCodeStyleAnalyzers = _hasSdkCodeStyleAnalyzers | IsSdkCodeStyleAnalyzer(fullPath)
instead of enumerating all the paths each time?
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.
agree on tweaking this.
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.
Changing this to only track the codestyle analyzer paths instead of tracking all analyzer paths. Only one call to IsSdkCodeStyleAnalyzer
when adding or removing.
@@ -58,6 +58,11 @@ internal sealed partial class ProjectSystemProject | |||
/// </summary> | |||
private readonly HashSet<string> _projectAnalyzerPaths = []; | |||
|
|||
/// <summary> |
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.
Add explanation of what mapping of analyzer references means.
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.
Changing this field name to _sdkCodeStyleAnalyzerPaths
which I think is self explanatory.
var hostAnalyzerCollection = new List<ImmutableArray<DiagnosticAnalyzer>>(); | ||
var projectAnalyzerCollection = new List<ImmutableArray<DiagnosticAnalyzer>>(); | ||
|
||
foreach (var kvp in analyzersPerReference) |
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.
Deconstruct: foreach (var (referenceId, analyzers) in analyzersPerReference)
"Microsoft.CodeAnalysis.VisualBasic.Features.dll", | ||
}.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase); | ||
|
||
private static ImmutableSegmentedDictionary<string, bool> s_analyzerFullPathToIsFeatureAnalyzer = ImmutableSegmentedDictionary<string, bool>.Empty; |
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 need to cache this? It's just simple comparison of 3 strings.
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.
You can simplify to:
bool IsFeaturesAnalyzer(this AnalyzerReference reference)
{
var fileNameSpan = reference.FullPath.AsSpan(FileNameUtilities.IndexOfFileName(reference.FullPath));
return
fileNameSpan.Equals("Microsoft.CodeAnalysis.Features.dll", StringComparison.OrdinalIgnoreCase) ||
fileNameSpan.Equals("Microsoft.CodeAnalysis.CSharp.Features.dll", StringComparison.OrdinalIgnoreCase) ||
fileNameSpan.Equals("Microsoft.CodeAnalysis.VisualBasic.Features.dll", StringComparison.OrdinalIgnoreCase);
}
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.
agreed. dictionaries fo rthis seem unnecessary.
Reviewed up to commit 5. |
_unmappedProjectAnalyzerPaths.Add(fullPath); | ||
|
||
// Determine if we started using SDK CodeStyle analyzers while access to _unmappedProjectAnalyzerPaths is gated. | ||
containsSdkCodeStyleAnalyzers = _unmappedProjectAnalyzerPaths.Any(IsSdkCodeStyleAnalyzer); |
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.
❓ What about
containsSdkCdoeStyleAnalyzers = HasSdkCodeStyleAnalyzers || IsSdkCodeStyleAnalyzer(fullPath);
_unmappedProjectAnalyzerPaths.Remove(fullPath); | ||
|
||
// Determine if we are still using SDK CodeStyle analyzers while access to _unmappedProjectAnalyzerPaths is gated. | ||
containsSdkCodeStyleAnalyzers = _unmappedProjectAnalyzerPaths.Any(IsSdkCodeStyleAnalyzer); |
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 also simplify this one:
containsSdkCodeStyleAnalyzers = IsSdkCodeStyleAnalyzer(fullPath)
? _unmappedProjectAnalyzerPaths.Any(IsSdkCodeStyleAnalyzer)
: HasSdkCodeStyleAnalyzers;
|
||
return new HostAnalyzerStateSets(analyzerMap); | ||
} | ||
|
||
static (IEnumerable<ImmutableArray<DiagnosticAnalyzer>> HostAnalyzerCollection, IEnumerable<ImmutableArray<DiagnosticAnalyzer>> ProjectAnalyzerCollection) GetAnalyzerCollections( |
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.
def don't like returning these as lazy enumerbles. can you make both an ImmutableArray<ImmutableArray<...
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 could but then we have to do something about the common case where we aren't redirecting and are returning analyzersPerReference.Values
which is an IEnumerable<ImmutableArray<DiagnosticAnalyzer>>
. The use of these IEnumerable's is also piped into StateManager.CreateStateSetMap
. This might be cleanup for a follow up PR.
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.
which is an IEnumerable<ImmutableArray>
Ick :) Can that one change?
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.
at the very least, don't return mutable lists. return an immutable array here. that way we don't have to worry about it changing.
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.
Updated to use ArrayBuilder instead of List.
This PR adds a ProjectAttribute to track whether the Project uses the SDK CodeStyle analyzers. This attribute is populated by the ProjectSystemProject which has access to the unmapped set of AnalyzerReferences. This attribute is then used when creating the HostAnalyzerStateSets to determine whether the Features analyzers should be treated as Project analyzers or not. It is also used by the DiagnosticComputer when building the Host and Project CompilationWithAnalyzers to ensure they mirror the statesets.
Suggest to review a commit at a time.