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

Improving formatting of InvocationExpressions #444

Merged
merged 28 commits into from
Oct 18, 2021
Merged

Improving formatting of InvocationExpressions #444

merged 28 commits into from
Oct 18, 2021

Conversation

belav
Copy link
Owner

@belav belav commented Sep 27, 2021

closes #7

@belav
Copy link
Owner Author

belav commented Sep 27, 2021

This is starting to get close, still lots of edge cases to check, lots of code to review after formatting with this, and some cleanup after the code "finished".
I split off some unrelated doc tree cleanup to #445

@belav
Copy link
Owner Author

belav commented Oct 11, 2021

I am calling this good enough. It is on par with the current state of prettier, and I pulled out a couple of edge case issues + #451
It includes all the changes from #445 so it should probably not be reviewed until that is merged.

@belav belav marked this pull request as ready for review October 11, 2021 18:11
shocklateboy92
shocklateboy92 previously approved these changes Oct 17, 2021
Copy link
Collaborator

@shocklateboy92 shocklateboy92 left a comment

Choose a reason for hiding this comment

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

Okay, that was a beast of a PR! 🐻

Tried to stick to the business logic, but a fair bit of bikeshedding did creep into my comments.

Src/CSharpier.Playground/Properties/launchSettings.json Outdated Show resolved Hide resolved
Src/CSharpier.Tests/DocUtilitiesTests.cs Outdated Show resolved Hide resolved
for (var x = 0; x < docs.Length; x++)
{
var printResult = PrintIndentedDocTree(docs[x]);
result += printResult;
Copy link
Collaborator

Choose a reason for hiding this comment

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

You're doing string concat in a for loop. I know you've done a fair bit of benchmarks on this already.
Do you have a rule of thumb for when it's worth using a StringBuilder or even a pool of StringBuilders?

Copy link
Owner Author

Choose a reason for hiding this comment

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

DocSerializer is only used during testing, and it wasn't straightforward to switch over to a StringBuilder so I was just throwing code in it and not worrying about it.
But! I was motivated to figure it out after your comment. So now it uses a single StringBuilder.

return doc switch
{
IHasContents hasContents => ContainsBreak(hasContents.Contents),
Concat concat => concat.Contents.Any(ContainsBreak),
Copy link
Collaborator

Choose a reason for hiding this comment

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

How come Concat doesn't implement IHasContents?
Do they mean different things sematically?

Copy link
Owner Author

Choose a reason for hiding this comment

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

I think I have gotten confused and asked the same question.
Concat.Contents is a List<Doc>
IHasContents.Contents is a Doc
One of the two should probably get renamed.
Or.... maybe Concat shouldn't really exist, because it is really just a List<Doc>, but I don't know how feasible it is to make that work.

or PredefinedTypeSyntax
or IdentifierNameSyntax
{
Identifier: { Text: { Length: <= 4 } }
Copy link
Collaborator

Choose a reason for hiding this comment

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

pattern matching for the win! 🎉🎉🎉

this
.CallMethod()
.CallMethod();
vs
Copy link
Collaborator

Choose a reason for hiding this comment

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

it would be clearer if you used "instead of" rather than "vs", to make it clearer which behavior is the result of not merging the first two groups.

*/
private static bool ShouldMergeFirstTwoGroups(List<List<PrintedNode>> groups)
{
if (groups.Count < 2 || groups[0].Count != 1)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this also take into account the length of the first token?
e.g. should:

this
  .CallMethod()
  .CallMethod()

break differently than

someLongAssVariableName
  .CallMethod()
  .CallMethod()

Copy link
Owner Author

Choose a reason for hiding this comment

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

Lower down in the method handles short identifiers. This if statement just bails out early in some situations.

@@ -131,14 +131,25 @@ public static Doc Print(CSharpSyntaxNode node)
);
}

if (typeParameterList != null)
if (typeParameterList != null && typeParameterList.Parameters.Any())
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: you can merge these two checks into one pattern: typeParameterList is { Count: > 0 }

@belav belav merged commit c1a0e40 into master Oct 18, 2021
@belav belav deleted the invocations branch October 18, 2021 17:01
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.

(finally) Improve formatting of InvocationExpressions
2 participants