Skip to content
Merged
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
38 changes: 30 additions & 8 deletions src/Zomp.SyncMethodGenerator/AsyncToSyncRewriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1159,9 +1159,14 @@ bool ShouldRemoveArgumentLocal(ArgumentSyntax arg, int index)

if (invalid.Contains(node.Arguments.Count - 1))
{
retval = retval
.WithCloseParenToken(@base.CloseParenToken.WithLeadingTrivia())
.WithOpenParenToken(@base.OpenParenToken.WithTrailingTrivia());
retval = retval.WithCloseParenToken(@base.CloseParenToken.WithLeadingTrivia());

// The newline which followed the opening parenthesis belongs to whichever argument
// now comes first, so it only goes when nothing is left to put on that line.
if (newParams.Count == 0)
{
retval = retval.WithOpenParenToken(@base.OpenParenToken.WithTrailingTrivia());
}
}

return retval;
Expand Down Expand Up @@ -2021,23 +2026,40 @@ private InvocationExpressionSyntax UnwrapExtension(InvocationExpressionSyntax ie
var arguments = ies.ArgumentList.Arguments;
var separators = arguments.GetSeparators();

// A list broken after its opening parenthesis gives each argument a line of its own. The
// receiver is about to become the first of them, so it wants the line the argument it
// displaces was starting, rather than the one the parenthesis is on.
var lineBreak = ies.ArgumentList.OpenParenToken.TrailingTrivia
.LastOrDefault(static t => t.IsKind(SyntaxKind.EndOfLineTrivia));
var brokenAfterOpenParen = lineBreak != default;

SyntaxToken[] newSeparators = arguments.Count < 1 ? []
: [Token(SyntaxKind.CommaToken).AppendSpace(), .. separators];
: [brokenAfterOpenParen
? Token(SyntaxKind.CommaToken).WithTrailingTrivia(lineBreak)
: Token(SyntaxKind.CommaToken).AppendSpace(), .. separators];

// The receiver becomes the first argument, so whatever separated it from the dot - a
// line break in a chained call - would otherwise land between it and the comma which
// now follows.
var @as = Argument(expression.WithoutTrivia());

// The argument the receiver displaces is no longer the first thing on its line, so
// indentation which was written to place it at the start of one only leaves a gap after
// the comma. Indentation which still follows a line break is left alone.
// The argument the receiver displaces either keeps the line it was starting, in which
// case the receiver takes its indentation and the comma between them takes the break, or
// it no longer starts one, in which case indentation written to place it at the start of
// a line only leaves a gap after the comma.
List<ArgumentSyntax> newArguments = [.. arguments];
if (newArguments is [var displaced, ..]
&& displaced.GetLeadingTrivia() is { Count: > 0 } leading
&& leading.All(static t => t.IsKind(SyntaxKind.WhitespaceTrivia)))
{
newArguments[0] = displaced.WithoutLeadingTrivia();
if (brokenAfterOpenParen)
{
@as = @as.WithLeadingTrivia(leading);
}
else
{
newArguments[0] = displaced.WithoutLeadingTrivia();
}
}

var newList = SeparatedList([@as, .. newArguments], newSeparators);
Expand Down
17 changes: 17 additions & 0 deletions tests/Generator.Tests/ArgumentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,22 @@ public async Task CallProgressMethodAsync()
{
await ProgressMethodAsync(progress: null);
}
""".Verify();

[Fact]
public Task KeepLineBreaksWhenTheLastArgumentIsDropped() => """
public void ProgressMethod(int p1, int p2) { }

public async Task ProgressMethodAsync(int p1, int p2, CancellationToken cancellationToken) => await Task.CompletedTask;

[Zomp.SyncMethodGenerator.CreateSyncVersion]
public async Task CallProgressMethodAsync(CancellationToken cancellationToken)
{
await ProgressMethodAsync(
1,
2,
cancellationToken
);
}
""".Verify();
}
2 changes: 1 addition & 1 deletion tests/Generator.Tests/ExtensionMethodTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ public async Task CopyAsync(

#if NET8_0_OR_GREATER
[Fact]
public Task CSharp_14_ExtensionUnwrapsOntoOneLine() => """
public Task CSharp_14_ExtensionDropsTheChainBreakAfterTheReceiver() => """
namespace Helpers
{
internal static partial class StreamExtensions
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//HintName: Test.Class.CallProgressMethodAsync.g.cs
public void CallProgressMethod()
{
ProgressMethod(
1,
2);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ public static partial class StreamCallers
extension(global::System.IO.Stream stream)
{
public void DrainTwice() =>
global::Helpers.StreamExtensions.Drain(stream, 1024);
global::Helpers.StreamExtensions.Drain(
stream,
1024);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ public void Copy(
global::System.IO.Stream destination,
global::System.IProgress<int>? progress = null
) =>
global::Helpers.StreamExtensions.WriteTo(stream, destination,
global::Helpers.StreamExtensions.WriteTo(
stream,
destination,
4096,
progress: progress);
}
Expand Down
Loading