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

Correctly apply anchor indentation adjustments in the presence of trivia #59654

Merged
merged 5 commits into from
Feb 23, 2022

Conversation

sharwell
Copy link
Member

Fixes #57465

@sharwell sharwell requested a review from a team as a code owner February 18, 2022 22:20
Copy link
Contributor

@davidwengier davidwengier left a comment

Choose a reason for hiding this comment

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

Thank you <3

2 +
3)
2 +
3)
Copy link
Member

Choose a reason for hiding this comment

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

i'm curious what happened here.

Copy link
Member Author

Choose a reason for hiding this comment

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

These lines previously anchored to from, but now anchor to the first token on the line containing from (var). Since var didn't move, these lines were not altered.

Copy link
Member Author

Choose a reason for hiding this comment

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

Note that anchoring is different from relative indentation. The latter applies to the select keyword on the next line.

Copy link
Member

Choose a reason for hiding this comment

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

hrmmmmmm.

i am worried about this. are we sure we don't want this to be anchored to the 'from'. While i genuinely think the anchoring change makes sense for many cases, queries are so special that it seems like we would want them them to follow that. (lambdas may be similar in that regard).

Copy link
Member Author

Choose a reason for hiding this comment

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

Also note that the new behavior is only problematic when all of the following hold:

  1. The original anchor token is not the first token on the line
  2. The first token on the line with the anchor token is in the correct location
  3. The anchor token is not in the correct location (i.e. spaces need to be added or removed to correct the position of the anchor token)
  4. The now position of the anchor token continues to be on the same line
  5. The anchored token on a subsequent line is correctly aligned with the mispositioned anchor token, and needs to retain its position after the anchor adjustment

Of all the tests that needed updating, this is the only one which could be argued to meet all these conditions. However, it's also easy to argue that this case does not meet condition (5), and therefore the new behavior is equally acceptable.

Copy link
Member Author

Choose a reason for hiding this comment

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

➡️ Testing greatly increased by adding an idempotency check for format document tests

if (existingWhitespaceBetween.Spaces != this.Spaces)
return LineColumnRule.PreserveWithGivenSpaces(spaces: this.Spaces);
else
return LineColumnRule.PreserveLinesWithDefaultIndentation(lines: 0);
Copy link
Member

Choose a reason for hiding this comment

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

i would doc this line. i think i get it, but it would be nice to ahve confirmation of intent.

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 block now eliminated

@@ -403,8 +403,9 @@ public void AddAnchorIndentationOperation(AnchorIndentationOperation operation)
return;
}

var originalSpace = _tokenStream.GetOriginalColumn(operation.StartToken);
var data = new AnchorData(operation, originalSpace);
var anchorToken = _tokenStream.FirstTokenOfBaseTokenLine(operation.AnchorToken);
Copy link
Member

Choose a reason for hiding this comment

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

doc.

Copy link
Member Author

Choose a reason for hiding this comment

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

➡️ Now documented

Copy link
Member

Choose a reason for hiding this comment

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

great doc, thanks.

@@ -491,7 +491,7 @@ End Class</Code>
Dim expected = <Code>Class C
Sub Method()
Dim a = From q In
{1, 3, 5}
{1, 3, 5}
Copy link
Member

Choose a reason for hiding this comment

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

this does not not seem good. what happened here?

Copy link
Member

Choose a reason for hiding this comment

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

ok. based on your previous comment, this is explained. that said, this is so weird too. why did this value end up on the next line? that feels like a bug itself.

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 was already on its own line, which is a strange situation from the start.

Where q > 10
Select q
End Sub
End Class</Code>
Copy link
Member

Choose a reason for hiding this comment

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

i'll reiterate that this seems not good. we could try taking this PR though and seeing if people have problems with it.

That said, i medium-strongly feel that within a query we should be keeping hte anchor attached to the start of hte query, not the start of hte line.

Is there a way we could have the best of both worlds? Your approach for most anchors, but allow an achor to override that with a flag that says "no, do not attach to start of line, keep me attached to this actual node".

Copy link
Member Author

@sharwell sharwell Feb 23, 2022

Choose a reason for hiding this comment

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

Is there a way we could have the best of both worlds?

There is, possibly. In the original form, I had a new flag to control the anchor selection. All of them used "first token on line", and when I came back to query expressions I was worried about the following situation:

  1. User has a correctly formatted expression:

    Dim a = From q In
                {1, 3, 5}
            Where q > 10
            Select q
  2. User accidentally hits tab between = and From:

    Dim a =     From q In
                {1, 3, 5}
            Where q > 10
            Select q
  3. User presses Ctrl+K, Ctrl+D to format document¹. Do to movement of the anchor, a change is made to a line that was already correct:

    Dim a = From q In
            {1, 3, 5}
            Where q > 10
            Select q

Eventually I concluded that it's more likely for an entire block to be indented incorrectly than for a vertically-aligned subsection to be indented incorrectly, and kept the anchor pointing to the first token on the line.

¹ Moving to a different line and/or saving the document alone is not sufficient to trigger the problematic behavior, because these actions instruct the formatter to only touch "dirty" lines, and that doesn't include the line with the inline array.

@sharwell sharwell merged commit e0f5df7 into dotnet:main Feb 23, 2022
@ghost ghost added this to the Next milestone Feb 23, 2022
@sharwell sharwell deleted the formatting-anchors branch February 23, 2022 18:23
@RikkiGibson RikkiGibson modified the milestones: Next, 17.2.P2 Mar 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Formatter requires two passes in the presence of directives inside lambda block bodies, inside argument lists
4 participants