dart_style icon indicating copy to clipboard operation
dart_style copied to clipboard

Incorrect indentation of trailing comma argument list in switch expression

Open munificent opened this issue 1 year ago • 2 comments

A function call with a trailing argument list in a switch expression currently formats like this:

main() {
  {
    return TextFieldTapRegion(
      onLongPressMoveUpdate: (longPressMoveUpdateDetails) {
        (switch (Theme.of(this.context).platform) {
          TargetPlatform.iOS || TargetPlatform.macOS =>
            _renderEditable.selectPositionAt(
            from: longPressMoveUpdateDetails.globalPosition,
            cause: SelectionChangedCause.longPress,
          ),
          TargetPlatform.android ||
                TargetPlatform.fuchsia ||
                TargetPlatform.linux ||
                TargetPlatform.windows =>
            _renderEditable.selectWordsInRange(
            from: longPressMoveUpdateDetails.globalPosition -
                longPressMoveUpdateDetails.offsetFromOrigin,
            to: longPressMoveUpdateDetails.globalPosition,
            cause: SelectionChangedCause.longPress,
          )
        });
      },
    );
  }
}

That's definitely wrong. It should be:

main() {
  {
    return TextFieldTapRegion(
      onLongPressMoveUpdate: (longPressMoveUpdateDetails) {
        (switch (Theme.of(this.context).platform) {
          TargetPlatform.iOS || TargetPlatform.macOS =>
            _renderEditable.selectPositionAt(
              from: longPressMoveUpdateDetails.globalPosition,
              cause: SelectionChangedCause.longPress,
            ),
          TargetPlatform.android ||
                TargetPlatform.fuchsia ||
                TargetPlatform.linux ||
                TargetPlatform.windows =>
            _renderEditable.selectWordsInRange(
              from: longPressMoveUpdateDetails.globalPosition -
                  longPressMoveUpdateDetails.offsetFromOrigin,
              to: longPressMoveUpdateDetails.globalPosition,
              cause: SelectionChangedCause.longPress,
            )
        });
      },
    );
  }
}

We may also want to consider special-casing || as the outer-most pattern in a switch expression case and not indent the subsequent arms, since they're more like parallel cases:

main() {
  {
    return TextFieldTapRegion(
      onLongPressMoveUpdate: (longPressMoveUpdateDetails) {
        (switch (Theme.of(this.context).platform) {
          TargetPlatform.iOS || TargetPlatform.macOS =>
            _renderEditable.selectPositionAt(
              from: longPressMoveUpdateDetails.globalPosition,
              cause: SelectionChangedCause.longPress,
            ),
          TargetPlatform.android ||
          TargetPlatform.fuchsia ||
          TargetPlatform.linux ||
          TargetPlatform.windows =>
            _renderEditable.selectWordsInRange(
              from: longPressMoveUpdateDetails.globalPosition -
                  longPressMoveUpdateDetails.offsetFromOrigin,
              to: longPressMoveUpdateDetails.globalPosition,
              cause: SelectionChangedCause.longPress,
            )
        });
      },
    );
  }
}

munificent avatar Mar 23 '23 17:03 munificent

Also, this one is even worse:

main() {
  {
    return TextFieldTapRegion(
      onLongPressMoveUpdate: (longPressMoveUpdateDetails) =>
          switch (Theme.of(this.context).platform) {
        TargetPlatform.iOS || TargetPlatform.macOS =>
          _renderEditable.selectPositionAt(
          from: longPressMoveUpdateDetails.globalPosition,
          cause: SelectionChangedCause.longPress,
        ),
        TargetPlatform.android ||
              TargetPlatform.fuchsia ||
              TargetPlatform.linux ||
              TargetPlatform.windows =>
          _renderEditable.selectWordsInRange(
          from: longPressMoveUpdateDetails.globalPosition -
              longPressMoveUpdateDetails.offsetFromOrigin,
          to: longPressMoveUpdateDetails.globalPosition,
          cause: SelectionChangedCause.longPress,
        )
      },
    );
  }
}

Note that the switch line is indented farther than the cases.

munificent avatar Mar 23 '23 17:03 munificent

I made some progress on this with #1203. It turns out that missing indentation on switch bodies here:

main() {
  {
    return TextFieldTapRegion(
      onLongPressMoveUpdate: (longPressMoveUpdateDetails) =>
          switch (Theme.of(this.context).platform) {
        TargetPlatform.android =>
          _renderEditable.selectWordsInRange()
      },
    );
  }
}

Is mostly deliberate. It looks bad in this example, but it makes a lot more sense when there's no split after =>:

main() {
  {
    return TextFieldTapRegion(
      onLongPressMoveUpdate: () => switch (platform) {
        TargetPlatform.android =>
          _renderEditable.selectWordsInRange()
      },
    );
  }
}

Ideally, the indentation would change based on whether we split after the => but unfortunately, the architecture of the formatter can't currently support that. Filed #1202 to track.

munificent avatar Apr 04 '23 00:04 munificent

I ran these examples through the forthcoming tall style and it's doing the right thing, so I'm going to go ahead and close this.

munificent avatar Aug 02 '24 23:08 munificent