Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can indentation of multiline arrow functions be 2 instead of 4? #809

Closed
kasperpeulen opened this issue Apr 30, 2019 · 8 comments
Closed

Comments

@kasperpeulen
Copy link

The indentation of multiline arrow functions is now 4. For example:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter layout demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter layout demo'),
        ),
        body: Center(child: buildRow()),
      ),
    );
  }

  Widget buildRow() => Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Image.asset('images/pic1.jpg'),
          Image.asset('images/pic2.jpg'),
          Image.asset('images/pic3.jpg'),
        ],
      );

  Widget buildColumn() => Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Image.asset('images/pic1.jpg'),
          Image.asset('images/pic2.jpg'),
          Image.asset('images/pic3.jpg'),
        ],
      );
}

This example is from a flutter example. I personally avoid arrow functions like above for my flutter code at this moment. The reason is purely aesthetic. The indentation seems too much and therefore it also doesn't align well with block body functions.

If it would be indented 2 it would look like this:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter layout demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter layout demo'),
        ),
        body: Center(child: buildRow()),
      ),
    );
  }

  Widget buildRow() => Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Image.asset('images/pic1.jpg'),
        Image.asset('images/pic2.jpg'),
        Image.asset('images/pic3.jpg'),
      ],
    );

  Widget buildColumn() => Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Image.asset('images/pic1.jpg'),
        Image.asset('images/pic2.jpg'),
        Image.asset('images/pic3.jpg'),
      ],
    );
}

If multiline arrow function could also start on the next line, it would be the most pleasing to the eyes in my opinion:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter layout demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter layout demo'),
        ),
        body: Center(child: buildRow()),
      ),
    );
  }

  Widget buildRow() => //
    Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Image.asset('images/pic1.jpg'),
        Image.asset('images/pic2.jpg'),
        Image.asset('images/pic3.jpg'),
      ],
    );

  Widget buildColumn() => //
    Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Image.asset('images/pic1.jpg'),
        Image.asset('images/pic2.jpg'),
        Image.asset('images/pic3.jpg'),
      ],
    );
}

Using a comment forces dart_fmt to align the expression on the next line, but I would love if this is automatic.

The main reason I start this issue, is because I believe in having as little noise as possible in our flutter UI code. Arrow functions like in this last example, have very little noise, and look very symmetric and aesthetically pleasing.

@a14n
Copy link
Contributor

a14n commented Apr 30, 2019

Formatting of expression functions should be improved by #794

@jeiea
Copy link

jeiea commented Nov 17, 2020

@a14n Is that PR effective in the latest flutter? I can't get the wanted result.

@a14n
Copy link
Contributor

a14n commented Nov 17, 2020

Can you paste the resulting code here?

@jeiea
Copy link

jeiea commented Nov 17, 2020

Same as OP.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter layout demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter layout demo'),
        ),
        body: Center(child: buildRow()),
      ),
    );
  }

  Widget buildRow() => Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Image.asset('images/pic1.jpg'),
          Image.asset('images/pic2.jpg'),
          Image.asset('images/pic3.jpg'),
        ],
      );

  Widget buildColumn() => Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Image.asset('images/pic1.jpg'),
          Image.asset('images/pic2.jpg'),
          Image.asset('images/pic3.jpg'),
        ],
      );
}
Flutter 1.22.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 8874f21e79 (3 weeks ago) • 2020-10-29 14:14:35 -0700
Engine • revision a1440ca392
Tools • Dart 2.10.3
vscode Dart, Flutter extension: 3.16.0

@a14n
Copy link
Contributor

a14n commented Nov 17, 2020

The above PR doesn't handle expression function body.

@duzenko
Copy link

duzenko commented Dec 17, 2020

The repro case is as simple as

  get a => [
        0,
      ];
  final b = [
    0,
  ];

@chiholai-sanasofthk
Copy link

bump, very annoying

@munificent
Copy link
Member

I think the forthcoming tall style handles this more or less how I expect, though it isn't exactly what's requested.

When it can, it avoids splitting after => at all. In those cases, it doesn't add any indentation at all, which gives you:

class MyApp extends StatelessWidget {
  Widget buildRow() => Row(children: [
    Image.asset('images/pic1.jpg'),
    Image.asset('images/pic2.jpg'),
    Image.asset('images/pic3.jpg'),
  ]);
}

That seems to be what most users prefer based on comments on other issues and looking at the Flutter repo's hand formatting.

But it does still sometimes decide to split after the =>. When it does, you get +4 indentation, not +2. That's because there is no closing delimiter to match the => and when an undelimited construct splits, it always gets +4 expression-like indentation. So with a longer argument list to Row(), you get:

class MyApp extends StatelessWidget {
  Widget buildRow() =>
      Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
        Image.asset('images/pic1.jpg'),
        Image.asset('images/pic2.jpg'),
        Image.asset('images/pic3.jpg'),
      ]);
}

It might be better to prefer:

class MyApp extends StatelessWidget {
  Widget buildRow() => Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
      Image.asset('images/pic1.jpg'),
      Image.asset('images/pic2.jpg'),
      Image.asset('images/pic3.jpg'),
    ],
  );
}

But that's a separate style choice around how whether splitting an argument list in certain ways should take priority over splitting the surrounding construct (in this case =>). The heuristics for that are hard to get right. It's easy to make one example look better while making ten others worse. I think the rules the new style has now are pretty good, but we can maybe consider tweaking them in a separate issue.

Since this issue is about the indentation and the new style is working as I expect, I'm going to go ahead and close this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants