Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Diagnostics.CodeAnalysis;
using CSharpier.Core.DocTypes;
using CSharpier.Core.Utilities;
using Microsoft.CodeAnalysis;
Expand All @@ -9,13 +8,6 @@ namespace CSharpier.Core.CSharp.SyntaxPrinter.SyntaxNodePrinters;

internal record PrintedNode(CSharpSyntaxNode Node, Doc Doc);

// This is based on prettier/src/language-js/print/member-chain.js
// various discussions/prs about how to potentially improve the formatting
// https://github.com/prettier/prettier/issues/5737
// https://github.com/prettier/prettier/issues/7884
// https://github.com/prettier/prettier/issues/8003
// https://github.com/prettier/prettier/issues/8902
// https://github.com/prettier/prettier/pull/7889
internal static class InvocationExpression
{
public static Doc Print(InvocationExpressionSyntax node, PrintingContext context)
Expand All @@ -30,33 +22,27 @@ public static Doc PrintMemberChain(ExpressionSyntax node, PrintingContext contex

FlattenAndPrintNodes(node, printedNodes, context);

var groups = printedNodes.Any(o => o.Node is InvocationExpressionSyntax)
? GroupPrintedNodesPrettierStyle(printedNodes)
: GroupPrintedNodesOnLines(printedNodes);
var groups = GroupPrintedNodesOnLines(printedNodes);

var oneLine = SelectManyDocsToArray(groups);

var shouldMergeFirstTwoGroups = ShouldMergeFirstTwoGroups(groups, parent);

var cutoff = shouldMergeFirstTwoGroups ? 3 : 2;

var forceOneLine =
(
groups.Count <= cutoff
groups.Count <= 2
&& (
groups
.Skip(shouldMergeFirstTwoGroups ? 1 : 0)
.Any(o =>
o.Last().Node
is not (
InvocationExpressionSyntax
or ElementAccessExpressionSyntax
or PostfixUnaryExpressionSyntax
{
Operand: InvocationExpressionSyntax
}
)
)
groups.Any(o =>
o.Last().Node
is not (
InvocationExpressionSyntax
or ElementAccessExpressionSyntax
or PostfixUnaryExpressionSyntax
{
Operand: InvocationExpressionSyntax
}
)
)
// if the last group contains just a !, make sure it doesn't end up on a new line
|| (
groups.Last().Count == 1
Expand Down Expand Up @@ -266,95 +252,6 @@ or IdentifierNameSyntax
return groups;
}

private static List<List<PrintedNode>> GroupPrintedNodesPrettierStyle(
List<PrintedNode> printedNodes
)
{
// We want to group the printed nodes in the following manner
//
// a().b.c().d().e
// will be grouped as
// [
// [Identifier, InvocationExpression],
// [MemberAccessExpression], [MemberAccessExpression, InvocationExpression],
// [MemberAccessExpression, InvocationExpression],
// [MemberAccessExpression],
// ]

// so that we can print it as
// a()
// .b.c()
// .d()
// .e

// TODO #451 this whole thing could possibly just turn into a big loop
// based on the current node, and the next/previous node, decide when to create new groups.
// certain nodes need to stay in the current group, other nodes indicate that a new group needs to be created.
var groups = new List<List<PrintedNode>>();
var currentGroup = new List<PrintedNode> { printedNodes[0] };
var index = 1;
for (; index < printedNodes.Count; index++)
{
if (printedNodes[index].Node is InvocationExpressionSyntax)
{
currentGroup.Add(printedNodes[index]);
}
else
{
break;
}
}

if (
printedNodes[0].Node is not (InvocationExpressionSyntax or PostfixUnaryExpressionSyntax)
&& index < printedNodes.Count
&& printedNodes[index].Node
is ElementAccessExpressionSyntax
or PostfixUnaryExpressionSyntax
)
{
currentGroup.Add(printedNodes[index]);
index++;
}

groups.Add(currentGroup);
currentGroup = [];

var hasSeenNodeThatRequiresBreak = false;
for (; index < printedNodes.Count; index++)
{
if (
hasSeenNodeThatRequiresBreak
&& printedNodes[index].Node
is MemberAccessExpressionSyntax
or ConditionalAccessExpressionSyntax
)
{
groups.Add(currentGroup);
currentGroup = [];
hasSeenNodeThatRequiresBreak = false;
}

if (
printedNodes[index].Node
is InvocationExpressionSyntax
or ElementAccessExpressionSyntax
)
{
hasSeenNodeThatRequiresBreak = true;
}
currentGroup.Add(printedNodes[index]);
}

if (currentGroup.Count != 0)
{
groups.Add(currentGroup);
}

return groups;
}

[SuppressMessage("ReSharper", "ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator")]
private static Doc[] SelectManyDocsToArray(List<List<PrintedNode>> groups)
{
var arrayLength = 0;
Expand Down Expand Up @@ -454,6 +351,14 @@ private static bool ShouldMergeFirstTwoGroups(
return false;
}

if (
groups[1]
.None(o => o.Node is InvocationExpressionSyntax or ElementAccessExpressionSyntax)
)
{
return true;
}

var firstNode = groups[0][0].Node;

if (
Expand All @@ -469,8 +374,6 @@ or BaseExpressionSyntax
return false;
}

// TODO maybe some things to fix in here
// https://github.com/belav/csharpier-repos/pull/100/files
if (
groups[1].Count == 1
|| parent
Expand Down
12 changes: 12 additions & 0 deletions Src/CSharpier.Core/Utilities/IEnumerableExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace CSharpier.Core.Utilities;

internal static class IEnumerableExtensions
{
public static bool None<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate
)
{
return !source.Any(predicate);
}
}
2 changes: 1 addition & 1 deletion Src/CSharpier.Generators/CSharpier.Generators.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<PackageScribanIncludeSource>true</PackageScribanIncludeSource>
<LangVersion>13</LangVersion>
<NoWarn>SYSLIB0013</NoWarn>
<NoWarn>SYSLIB0013;NU1903</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Common" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ class TestClass
) ?? someOtherValue;

var x =
someValue
.Property.CallLongMethod_____________________________________()
someValue.Property
.CallLongMethod_____________________________________()
.CallMethod(
someLongValue__________________________________________,
someLongValue__________________________________________
Expand Down Expand Up @@ -273,32 +273,35 @@ class TestClass
someLongValue__________________________________________,
someLongValue__________________________________________
)
).SomeProperty.CallMethod() ?? someOtherValue;
).SomeProperty
.CallMethod() ?? someOtherValue;

var x =
(
CallMethod(
someLongValue__________________________________________,
someLongValue__________________________________________
)
)?.SomeProperty.CallMethod() ?? someOtherValue;
)?.SomeProperty
.CallMethod() ?? someOtherValue;

var x =
(
CallMethod(
someLongValue__________________________________________,
someLongValue__________________________________________
)
)?.SomeProperty?.CallMethod() ?? someOtherValue;
)?.SomeProperty
?.CallMethod() ?? someOtherValue;

var x =
(
CallMethod(
someLongValue__________________________________________,
someLongValue__________________________________________
)
)
.SomeProperty.CallMethod()
).SomeProperty
.CallMethod()
.CallMethod()
?? someOtherValue;

Expand All @@ -308,8 +311,8 @@ class TestClass
someLongValue__________________________________________,
someLongValue__________________________________________
)
)
?.SomeProperty.CallMethod()
)?.SomeProperty
.CallMethod()
.CallMethod()
?? someOtherValue;

Expand Down Expand Up @@ -346,20 +349,20 @@ class TestClass
) ?? someOtherValue;

var x =
someValue
.Property.CallLongMethod_____________________________________()
someValue.Property
.CallLongMethod_____________________________________()
.CallMethod__________()
?? throw new Exception();

var x =
someValue
.Property.CallLongMethod_____________________________________()
someValue.Property
.CallLongMethod_____________________________________()
.CallMethod__________(someParameter)
?? throw new Exception();

var x =
someValue
.Property.CallLongMethod_____________________________________()
someValue.Property
.CallLongMethod_____________________________________()
.CallLongMethod___________________________________________________()
?? throw new Exception();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,33 @@
var someVariable =
someObject____________.Property_______________.CallMethod______________________();
var someVariable = someObject____________.Property_______________
.CallMethod______________________();

var someVariable = someObject.Property.CallMethod(someValue =>
someValue.SomeProperty == someOtherValue___________________________
);
var someVariable = someObject.Property
.CallMethod(someValue => someValue.SomeProperty == someOtherValue___________________________);

var someVariable = someObject
.Property()
.CallMethod()
.CallMethod(someValue => someValue.SomeProperty == someOtherValue___________________________);

var someVariable = someObject
.Property.CallMethod(someValue =>
someValue.SomeProperty == someOtherValue___________________________
)
var someVariable = someObject.Property
.CallMethod(someValue => someValue.SomeProperty == someOtherValue___________________________)
.CallMethod();

var someVariable = someObject
.Property()
.CallMethod()
.CallMethod(someValue => someValue.SomeProperty == someOtherValue___________________________)
.CallMethod();

// TODO too hard to change this for now, will do it in https://github.com/belav/csharpier/issues/451
var someVariable = this.Property.CallMethod(someValue =>
someValue.SomeProperty == someOtherValue___________________________
);
var someVariable = this.Property
.CallMethod(someValue => someValue.SomeProperty == someOtherValue___________________________);

var someVariable = this.CallMethod()
.CallMethod(someValue => someValue.SomeProperty == someOtherValue___________________________);

var someVariable = this.Array[1]
.CallMethod(someValue => someValue.SomeProperty == someOtherValue___________________________);

var someVariable = this
.Property.CallMethod(someValue =>
someValue.SomeProperty == someOtherValue___________________________
)
var someVariable = this.Property
.CallMethod(someValue => someValue.SomeProperty == someOtherValue___________________________)
.CallMethod();

var someVariable = this.CallMethod()
Expand Down
Loading
Loading