belav / csharpier

CSharpier is an opinionated code formatter for c#.
https://csharpier.com
MIT License
1.43k stars 99 forks source link

Make long parenthesized expressions not always break. #1115

Open belav opened 10 months ago

belav commented 10 months ago

closes #921

The goal of this ticket was to prefer breaking trailing members on a parenthesized expression before breaking the expression. For example.

// input
(someObject as SomeLongType__________________________________________).CallMethod();

// expected
(someObject as SomeLongType__________________________________________)
    .CallMethod();

// actual
(
    someObject as SomeLongType__________________________________________
).CallMethod();

The way it is currently implemented though results in the following

var asyncMethodsWithToken = (
    from method in asyncMethods
    where method.GetParameters().Any(pi => pi.ParameterType == typeof(CancellationToken))
    select method
)
    .ToList();

// previously
var asyncMethodsWithToken = (
    from method in asyncMethods
    where method.GetParameters().Any(pi => pi.ParameterType == typeof(CancellationToken))
    select method
).ToList();

This does mean things are more consistent with longer chains

var asyncMethodsWithToken = (
    from method in asyncMethods
    where method.GetParameters().Any(pi => pi.ParameterType == typeof(CancellationToken))
    select method
)
    .ToList________________________()
    .ToList________________________()
    .ToList________________________();

Another example where I think the old version was probably better

Assert.Equal(
    CoreStrings.FindValueTypeMismatch(0, "IntKey", "string", "int"),
    (
        await Assert.ThrowsAsync<ArgumentException>(
            () =>
                Finder
                    .FindAsync<IntKey>(cancellationType, context, new object[] { "77" })
                    .AsTask()
        )
    )
        .Message
);

// previously
Assert.Equal(
    CoreStrings.FindValueTypeMismatch(0, "IntKey", "string", "int"),
    (
        await Assert.ThrowsAsync<ArgumentException>(
            () =>
                Finder
                    .FindAsync<IntKey>(cancellationType, context, new object[] { "77" })
                    .AsTask()
        )
    ).Message
);

I'm not sure how much work it would be to keep the tailing call next to the ) if the contents of the parenthsized expression break.

FWIW prettier does not have any logic around this.

shocklateboy92 commented 10 months ago

Do we have a group type that breaks if its children are longer than its siblings' children?

belav commented 10 months ago

Do we have a group type that breaks if its children are longer than its siblings' children?

No and the way things work I don't know if it would be possibly.

A ConditionalGroup may accomplish something like that. If the first possible group breaks the children and does not break the siblings and is considered to fit, then it gets printed.