Skip to content

The null coalescing operator is grouped in an unexpected place #1769

@ogaken-1

Description

@ogaken-1

CSharpier Version: 1.2.1

Input:

var x =
    someValue.SomeCall().SomeProperty.SomeProperty
    ?? someValue.SomeCall().SomeProperty.SomeProperty;

var x =
    someValue.SomeCall().SomeProperty?.SomeCall().SomeProperty
    ?? someValue.SomeCall().SomeProperty?.SomeCall().SomeProperty;

var x =
    someValue.SomeCall().A_______.B_______.C_______
    ?? someValue.SomeCall().A_______.B_______.C_______;

Output:

var x =
    someValue.SomeCall().SomeProperty.SomeProperty ?? someValue
        .SomeCall()
        .SomeProperty.SomeProperty;

var x =
    someValue.SomeCall().SomeProperty?.SomeCall().SomeProperty ?? someValue
        .SomeCall()
        .SomeProperty?.SomeCall()
        .SomeProperty;

var x =
    someValue.SomeCall().A_______.B_______.C_______ ?? someValue
        .SomeCall()
        .A_______.B_______.C_______;

Expected behavior:

var x =
    someValue.SomeCall().SomeProperty.SomeProperty
    ?? someValue.SomeCall().SomeProperty.SomeProperty;

var x =
    someValue.SomeCall().SomeProperty?.SomeCall().SomeProperty
    ?? someValue.SomeCall().SomeProperty?.SomeCall().SomeProperty;

var x =
    someValue.SomeCall().A_______.B_______.C_______
    ?? someValue.SomeCall().A_______.B_______.C_______;

From #1681, some null coalescing operators no longer have their right-hand expression on its own line.

In the chain > 3 condition, the left-hand expression becomes a grouping target just by being slightly more complex.

I confirmed that the first and second examples above can be avoided by converting the condition to chain > 4, but I don't think that's a very good solution.

The reason why changes like #1681 were probably made is that, while addressing the pattern reported in #1573, they also had to handle existing formatting like the example below, and got stuck on how to define the left-hand side.

var coalesceIsSpecial =
    CallSomething(
        someLongValue__________________________________________,
        someLongValue__________________________________________
    ) ?? someOtherValue;

This pattern is tricky to handle, but while listing several plausible examples, I thought that "if the left-hand expression is an InvocationExpression and the MemberAccessExpression is built solely from property accesses, then group it" might work well.

var coalesceIsSpecial =
    CallSomething(
        someLongValue__________________________________________,
        someLongValue__________________________________________
    ) ?? someOtherValue;

var x =
    someValue
        .Property.CallLongMethod_____________________________________()
        .CallMethod(
            someLongValue__________________________________________,
            someLongValue__________________________________________
        )
    ?? someOtherValue;

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

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

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

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions