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

Ensure Location.None in additional locations can round trip correctly #76623

Merged
merged 1 commit into from
Jan 5, 2025

Conversation

Youssef1313
Copy link
Member

If an analyzer adds Location.None in additional location, it gets removed away in the code fix.

This can be useful to preserve in case the analyzer can have multiple additional locations, some of which are kinda "optional", but each has a separate meaning that is determined by its index.

Currently, the only way around that is to not use Location.None, and instead use the properties map to determine the meanings.

NOTE: Even after this is merged, analyzer/codefix authors shouldn't really rely on the new behavior if they intend to support earlier versions of VS. This PR is intended to stabilize things in future when the fix becomes in an "old enough" VS version.

FYI @Sergio0694

@Youssef1313 Youssef1313 requested a review from a team as a code owner January 5, 2025 08:16
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Analyzers untriaged Issues and PRs which have not yet been triaged by a lead labels Jan 5, 2025
@@ -263,13 +263,24 @@ private static ImmutableArray<DiagnosticDataLocation> GetAdditionalLocations(Tex
{
if (location.IsInSource)
{
builder.AddIfNotNull(CreateLocation(document.Project.Solution.GetDocument(location.SourceTree), location));
builder.Add(CreateLocation(document.Project.Solution.GetDocument(location.SourceTree), location));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CreateLocation always returns non-null. So switched AddIfNotNull to simply Add.

var diagnostic = await diagnosticData.ToDiagnosticAsync(document.Project, CancellationToken.None);
var roundTripDiagnosticData = DiagnosticData.Create(diagnostic, document);

var roundTripAdditionalLocation = Assert.Single(roundTripDiagnosticData.AdditionalLocations);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assert would fail without the fix.

@dotnet-policy-service dotnet-policy-service bot added Community The pull request was submitted by a contributor who is not a Microsoft employee. VSCode labels Jan 5, 2025
@Youssef1313
Copy link
Member Author

Youssef1313 commented Jan 5, 2025

@CyrusNajmabadi I'm curious why having a separate serializable type was this the taken approach? Couldn't the compiler's Location implementations be made serializable by applying DataContract attribute to them (and DataMember attribute on the members)?

That way, if a user decided, for whatever reason, to implement their own Location, they can make it serializable and will have it preserved in the codefix. Yes I do understand that it's unlikely to be needed and probably no one is doing it already. But feels like it can be supported and having the code simplified. Do you see any downsides (or technical limitations) to making compiler's Location serializable right away?

@Youssef1313 Youssef1313 changed the title Ensure AdditionalLocation.None can round trip correctly Ensure Location.None in additional locations can round trip correctly Jan 5, 2025
@Youssef1313 Youssef1313 force-pushed the diagnostic-roundtrip branch from 12a5051 to a1c72a3 Compare January 5, 2025 08:26
Assert.Null(noneAdditionalLocation.DocumentId);
Assert.Null(roundTripAdditionalLocation.DocumentId);
Assert.Equal(noneAdditionalLocation.UnmappedFileSpan, roundTripAdditionalLocation.UnmappedFileSpan);
Assert.Same(diagnostic.AdditionalLocations.Single(), Location.None);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we verify that producing diagnostics from the diagnosticdata also works and gives back Location.None?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm interpreting this correctly, the diagnostic variable is created from diagnosticData and is asserted at line 204 to have Location.None additional location. So, both ways are already tested. We started with DiagnosticData, then to Diagnostic, then back to DiagnosticData. The original and final DiagnosticData are asserted that both have additional location with null DocumentId and have the same UnmappedFileSpan. And the Diagnostic is asserted to have a single additional location which is Location.None

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. Gotcha. That's sufficient for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Analyzers Community The pull request was submitted by a contributor who is not a Microsoft employee. untriaged Issues and PRs which have not yet been triaged by a lead VSCode
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants