Skip to content

Rewritten argument lists keep stranded indentation #152

Description

@virzak

Symptom

An argument list which loses an argument, or which gains the receiver of an unwrapped extension call, keeps the indentation of the original layout without the line breaks that made it meaningful:

global::SharpCompress.Archives.IArchiveEntryExtensions.WriteTo(archiveEntry,                     streamToWriteTo,
        global::SharpCompress.Common.Constants.BufferSize,
        progress: progress)                ;

The code is correct and compiles. It just does not read like something a person would write, which matters for a generator whose output people are invited to inspect.

Reproduced against SharpCompress, whose sources are CSharpier-formatted and so chain calls across lines throughout:

) =>
    await archiveEntry
        .WriteToAsync(
            streamToWriteTo,
            Constants.BufferSize,
            progress: progress,
            cancellationToken: cancellationToken
        )
        .ConfigureAwait(false);

Two separate causes

  1. Removing an argument (here cancellationToken) takes the line break which preceded it but leaves the indentation of what follows.
  2. UnwrapExtension rebuilds the list with ArgumentList(newList), which mints a fresh pair of parentheses and so discards the trivia on the originals - including the break after the opening one, and the break after the closing one which KeepExpressionBeforeDot wants to carry over to the ; when it drops a trailing .ConfigureAwait().

What did not work

Preserving the original parentheses (ies.ArgumentList.WithArguments(newList)) and giving the inserted receiver the leading trivia of the argument it displaces. By the time UnwrapExtension runs, the list it sees has already been rebuilt by the argument-removal pass, so the trivia it would copy is gone; the receiver ends up indented onto the wrong line and ConditionalExtensionTests.LongChained regresses to a ; stranded on a line of its own.

Whatever the fix is, it likely belongs where the arguments are removed rather than where the extension is unwrapped, or in a normalization pass over the finished list.

Scope

Cosmetic. Filed so the analysis is not lost, not as a blocker.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions