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

Fix a couple of exceptions encountered when formatting documents with preprocessor directives #11373

Merged

Conversation

davidwengier
Copy link
Contributor

Fixes #11372

When you assume, you make a fool out of people who use the .Single() method and expect a good time.

@davidwengier davidwengier requested a review from a team as a code owner January 9, 2025 07:16
Comment on lines -110 to +117
var annotation = trivia.GetAnnotations(MarkerId).Single();
if (!int.TryParse(annotation.Data, out var projectedIndex))
// We only expect one annotation because we built the entire trivia with a single annotation, but
// we need to be defensive here. Annotations are a little hard to work with though, so apologies for
// the slightly odd method of validation.
using var enumerator = trivia.GetAnnotations(MarkerId).GetEnumerator();
enumerator.MoveNext();
var annotation = enumerator.Current;
// We shouldn't be able to enumerate any more, and we should be able to parse our data out of the annotation.
if (enumerator.MoveNext() ||
!int.TryParse(annotation.Data, out var projectedIndex))
Copy link
Member

Choose a reason for hiding this comment

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

The defensive code seems fine to me, but what are the conditions where multiple annotations are returned?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Given this document with source mappings at each $$

<div>
@{$$
#if DEBUG
$$}

@{$$
#endif
$$}
</div>

If DEBUG is not defined, then the whole span between directives is a single "DisabledTextTrivia", but obviously it contains two mappings, so two points to track.

Copy link
Contributor

@ryzngard ryzngard left a comment

Choose a reason for hiding this comment

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

Overall looks good. Not sure I like the formatting but I don't think it's necessarily bad so signing off.

<div />
@{
#if DEBUG
}
Copy link
Contributor

Choose a reason for hiding this comment

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

huh... this looks wrong to me :/

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand this either TBH. Is the preprocessor directive increasing the indent level? It doesn't seem to in standalone C# file. E.g.

if (true)
{
#if DEBUG
if (true)
{
#endif
}
}

formatted becomes

if (true)
{
#if DEBUG
    if (true)
    {
#endif
    }
}

which is what I would expect

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To be very clear, this PR doesn't attempt to actually adjust how this document is formatted, it just makes the formatting engine not crash. The {get;set;} being spaced out correctly here is providing value to the user that they didn't get before.

Having said that, in the tests there are no preprocessor defines (actually we have no way to pass them to the Razor compiler at all I don't think) so the code in the #if is not parsed or formatted by Roslyn. Pretend it doesn't exist, and the result looks right.

linePositionSpan = default;
return false;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

When does this happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think due to FUSE, there was a zero-width marker token at the end of the document which upset this algorithm. It's entirely possible this never happens in real life, but being defensive doesn't hurt.

@davidwengier
Copy link
Contributor Author

Thanks for the reviews. I wanted to get this in before the new formatting engine, since it won't hit this path at all, but on type formatting still could.

@davidwengier davidwengier merged commit f5c6264 into dotnet:main Jan 10, 2025
12 checks passed
@davidwengier davidwengier deleted the PreprocessorDirectiveFormatting branch January 10, 2025 01:15
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Jan 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Razor pages with preprocessor directives don't format
4 participants