Giter Club home page Giter Club logo

dart_style's Introduction

The dart_style package defines an automatic, opinionated formatter for Dart code. It replaces the whitespace in your program with what it deems to be the best formatting for it. Resulting code should follow the Dart style guide but, moreso, should look nice to most human readers, most of the time.

The formatter handles indentation, inline whitespace, and (by far the most difficult) intelligent line wrapping. It has no problems with nested collections, function expressions, long argument lists, or otherwise tricky code.

The formatter turns code like this:

// BEFORE formatting
if (tag=='style'||tag=='script'&&(type==null||type == TYPE_JS
      ||type==TYPE_DART)||
  tag=='link'&&(rel=='stylesheet'||rel=='import')) {}

into:

// AFTER formatting
if (tag == 'style' ||
  tag == 'script' &&
      (type == null || type == TYPE_JS || type == TYPE_DART) ||
  tag == 'link' && (rel == 'stylesheet' || rel == 'import')) {}

The formatter will never break your code—you can safely invoke it automatically from build and presubmit scripts.

Style fixes

The formatter can also apply non-whitespace changes to make your code consistently idiomatic. You must opt into these by passing either --fix which applies all style fixes, or any of the --fix--prefixed flags to apply specific fixes.

For example, running with --fix-named-default-separator changes this:

greet(String name, {String title: "Captain"}) {
  print("Greetings, $title $name!");
}

into:

greet(String name, {String title = "Captain"}) {
  print("Greetings, $title $name!");
}

Using the formatter

The formatter is part of the unified dart developer tool included in the Dart SDK, so most users get it directly from there. That has the latest version of the formatter that was available when the SDK was released.

IDEs and editors that support Dart usually provide easy ways to run the formatter. For example, in WebStorm you can right-click a .dart file and then choose Reformat with Dart Style.

Here's a simple example of using the formatter on the command line:

$ dart format test.dart

This command formats the test.dart file and writes the result to the file.

dart format takes a list of paths, which can point to directories or files. If the path is a directory, it processes every .dart file in that directory or any of its subdirectories.

By default, it formats each file and write the formatting changes to the files. If you pass --output show, it prints the formatted code to stdout.

You may pass a -l option to control the width of the page that it wraps lines to fit within, but you're strongly encouraged to keep the default line length of 80 columns.

Validating files

If you want to use the formatter in something like a presubmit script or commit hook, you can pass flags to omit writing formatting changes to disk and to update the exit code to indicate success/failure:

$ dart format --output=none --set-exit-if-changed .

Running other versions of the formatter CLI command

If you need to run a different version of the formatter, you can globally activate the package from the dart_style package on pub.dev:

$ pub global activate dart_style
$ pub global run dart_style:format ...

Using the dart_style API

The package also exposes a single dart_style library containing a programmatic API for formatting code. Simple usage looks like this:

import 'package:dart_style/dart_style.dart';

main() {
  final formatter = DartFormatter();

  try {
    print(formatter.format("""
    library an_entire_compilation_unit;

    class SomeClass {}
    """));

    print(formatter.formatStatement("aSingle(statement);"));
  } on FormatterException catch (ex) {
    print(ex);
  }
}

Other resources

  • Before sending an email, see if you are asking a frequently asked question.

  • Before filing a bug, or if you want to understand how work on the formatter is managed, see how we track issues.

dart_style's People

Contributors

a14n avatar athomas avatar bkonyi avatar bwilkerson avatar chalin avatar dependabot[bot] avatar derekxu16 avatar dev-aentgs avatar devoncarew avatar eneev-a avatar franklinyow avatar jacob314 avatar jakemac53 avatar jensjoha avatar jolkdarr avatar kallentu avatar kevmoo avatar lrhn avatar matey-jack avatar michaelrfairhurst avatar mraleph avatar munificent avatar natebosch avatar nex3 avatar parlough avatar scheglov avatar sfshaza2 avatar srawlins avatar stereotype441 avatar whesse avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dart_style's Issues

do not generate trailing whitespace on empty lines

In the following example #EOL is just a marker of where the end of the line is:

class A {
  Field f;
#EOL
  A(this.f);
}

the output of the formatter adds a space at the end of the empty line between the field and the class constructor:

class A {
  Field f;
 #EOL 
  A(this.f);
}

Add tests for labels

The formatter changed this sample from Chapter 2 of Dart: Up and Running:

nowClosed:
  case 'NOW_CLOSED':

to this:

nowClosed: case 'NOW_CLOSED':

I don't know whether the label should be indented or flush left (the style guide doesn't mention labels), but I sure didn't expect the case to be on the same line as the label. The full code for that function currently looks like this:

switchItUp() {
  var command = 'CLOSED';
  switch (command) {
    case 'CLOSED':
      executeClosed();
      continue nowClosed; // Continues executing at the nowClosed label.

  nowClosed:
    case 'NOW_CLOSED':
      // Runs for both CLOSED and NOW_CLOSED.
      executeNowClosed();
      break;
  }
}

trailing comma on short vs long maps and lists

Currently this text:

var aaax = {
'asdasdaa' : 'b',
'asdasdaa' : 'c',
'asdasasa' : 'e',
'asdasaas' : 'd',
};

will be formatted correctly as follows:

var aaax = {
  'asdasdaa': 'b',
  'asdasdaa': 'c',
  'asdasasa': 'e',
  'asdasaas': 'd',
};

This is what I expected, and I like that we keep the trailing comma. (please do not remove it :))

however, if the map fits in a single line:

var x = {
'asdasdaa' : 'b',
'asdasdaa' : 'c',
'asdasasa' : 'e',
'asdasaas' : 'd',
};

we get:

var x = {'asdasdaa': 'b', 'asdasdaa': 'c', 'asdasasa': 'e', 'asdasaas': 'd',};

I would expect the formatter to remove the last comma:

var x = {'asdasdaa': 'b', 'asdasdaa': 'c', 'asdasasa': 'e', 'asdasaas': 'd'};

cascades indentation

Cascades and chained calls are both indented 4 spaces, but cascades should be 2 spaces.

For both, it would be nice to avoid the line break before the first . if the code before the . is short enough.

For example, this input could be unchanged:

  sb..write('Use a StringBuffer ')
    ..writeAll(['for', 'efficient', 'string', 'creation'], ' ')
    ..write('.');

Instead it has this output:

  sb
      ..write('Use a StringBuffer ')
      ..writeAll(['for', 'efficient', 'string', 'creation'], ' ')
      ..write('.');

I expected either the same as the input (saving one line, which matters in doc samples) or this:

  sb
    ..write('Use a StringBuffer ')
    ..writeAll(['for', 'efficient', 'string', 'creation'], ' ')
    ..write('.');

This is related to issue #39.

If one argument in an argument list is multiline, surrounding arguments should have their own lines

Currently,

_log(new LogEntry(error.transform, error.transform.primaryId,
        LogLevel.ERROR, message, null),
    arg);

is formatted as

_log(new LogEntry(error.transform, error.transform.primaryId, LogLevel.ERROR,
    message, null), arg);

The second argument to _log is hidden after the long argument list for new LogEntry(). If one argument is multi-line, no part of it should be on the same line as other arguments.

comment breaks indentation in if-return pattern

More fun with comments... A comment breaks indentation in if-return pattern. For example, this source:

foo() {
  if (true)
    // comment!
    return 0;
}

produces

foo() {
  if (true)
  // comment!
  return 0;
}

Keep method names closer to receiver than to args

Currently

return _provideDirectorySources(graph.packages[package], "bin")
    .then((_) => BarbackServer.bind(
        this, _hostname, 0, package: package, rootDirectory: "bin"));

is formatted as

return _provideDirectorySources(graph.packages[package], "bin")
    .then((_) => BarbackServer
        .bind(this, _hostname, 0, package: package, rootDirectory: "bin"));

It seems weird to me that .bind is so separate from BarbackServer. It seems like the most important aspect of a method call is the receiver; that's what gives the reader context about what concrete method is being called.

Comments in the middle of a statement throw off indentation

     return options.releaseMode &&
-      // TODO(sigmund): remove this exclusion once we have dev_transformers
-      // (dartbug.com/14187)
-      !id.path.startsWith('lib/') &&
-      // may filter non-entry HTML files and internal artifacts
-      (id.extension == '.html' || id.extension == _DATA_EXTENSION) &&
-      // keep any entry points
-      !options.isHtmlEntryPoint(id);
+        
+    // TODO(sigmund): remove this exclusion once we have dev_transformers
+    // (dartbug.com/14187)
+    !id.path.startsWith('lib/') &&
+        
+    // may filter non-entry HTML files and internal artifacts
+    (id.extension == '.html' || id.extension == _DATA_EXTENSION) &&
+        
+    // keep any entry points
+    !options.isHtmlEntryPoint(id);

switch statements can get much longer/harder to read

Hard to make a general rule, but I had

     switch (pattern[0]) {
      case 'a': return formatAmPm(date);
      case 'c': return formatStandaloneDay(date);
      case 'd': return formatDayOfMonth(date);
      case 'D': return formatDayOfYear(date);
      ...

and it turns into

   switch (pattern[0]) {
      case 'a':
        return formatAmPm(date);
      case 'c':
        return formatStandaloneDay(date);
      case 'd':
        return formatDayOfMonth(date);
      case 'D':
        return formatDayOfYear(date);

where it's both longer and harder to see at a glance what the cases are.

odd format with if-return (no braces) if return expression is long

I'm not sure we can do anything better here, but I'm just creating this bug in case there is something I'm missing.

This program

foo() {
  if (xxxxxxxxxxxxxxxx || xxxxxxxxxxxxxxxxxxxxx)
    return xxxxxxxxxxxxxx ? xxxxxxxxxxxxxxxxxxxx : xxxxxxxxxxxxxxxxxxxxxxxxxx;
}

is generated as:

foo() {
  if (xxxxxxxxxxxxxxxx || xxxxxxxxxxxxxxxxxxxxx) return xxxxxxxxxxxxxx ?
      xxxxxxxxxxxxxxxxxxxx : xxxxxxxxxxxxxxxxxxxxxxxxxx;
}

can we do better?

Weird indentation after adjacent strings

Before:

dragInfo['avatar'].style.cssText = 'border: 3px solid $color;'
    'width: 32px; height: 32px; '
    'border-radius: 32px; background-color: whitesmoke';

The formatter produces:

dragInfo['avatar'].style.cssText =
    'border: 3px solid $color;' 'width: 32px; height: 32px; '
        'border-radius: 32px; background-color: whitesmoke';

Extra newlines before comments in list literal

Sometimes, you really just want to break convention, see the following:

 const _urlAttributes = const [
-  'action', '_action',          // in form
-  'background', '_background',  // in body
-  'cite', '_cite',              // in blockquote, del, ins, q
-  'data', '_data',              // in object
-  'formaction', '_formaction',  // in button, input
-  'href', '_href',              // in a, area, link, base, command
-  'icon', '_icon',              // in command
-  'manifest', '_manifest',      // in html
-  'poster', '_poster',          // in video
-  'src', '_src',                // in audio, embed, iframe, img, input, script,
-                                //    source, track,video
+  'action',
+  '_action',
+  
+
+  // in form
+  'background',
+  '_background',
+  
+
+  // in body
+  'cite',
+  '_cite',
+  
+
+  // in blockquote, del, ins, q
+  'data',
+  '_data',
+  
+
+  // in object
+  'formaction',
+  '_formaction',
+  
+
+  // in button, input
+  'href',
+  '_href',
+  
+
+  // in a, area, link, base, command
+  'icon',
+  '_icon',
+  
+
+  // in command
+  'manifest',
+  '_manifest',
+  
+
+  // in html
+  'poster',
+  '_poster',
+  
+
+  // in video
+  'src',
+  '_src',
+
+
+// in audio, embed, iframe, img, input, script,
+//    source, track,video
 ];

import statements are not wrapped

I'd expect this test to pass

40 columns                              |
>>> https://github.com/dart-lang/dart_style/issues/14
import 'dart:io' show Alphabet, Bookings, Calendar, Dentist, Elephant;
<<<
import 'dart:io' show Alphabet,
    Bookings, Calendar, Dentist,
    Elephant;

Lots of short named arguments gets very ugly

from intl/test/message_extraction/sample_with_messages.dart

before:

pluralThatFailsParsing(noOfThings) => Intl.plural(noOfThings,
    one: "1 thing:",
    other: "$noOfThings things:",
    name: "pluralThatFailsParsing",
    args: [noOfThings],
    desc: "How many things are there?");

after:

pluralThatFailsParsing(noOfThings) => Intl.plural(noOfThings, one: "1 thing:",
    other: "$noOfThings things:", name: "pluralThatFailsParsing", args: [
  noOfThings
], desc: "How many things are there?");

The handling of the list parameter "args" is particularly bad, but in general I think the first form, or maybe the first form with the positional argument also on its own line, would be greatly preferable.

Don't change alignment of // comments on consecutive rows

The formatter wants each // comment to start one space after the end of the line, but often comments are more readable if they're aligned. Would it be possible to detect when comments are aligned and continue to keep them aligned?

Input:

  assert(v.x == 2 && v.y == 3);         // v   == (2,3)
  assert((v+w).x == 4 && (v+w).y == 5); // v+w == (4,5)
  assert((v-w).x == 0 && (v-w).y == 1); // v-w == (0,1)

Output:

  assert(v.x == 2 && v.y == 3); // v   == (2,3)
  assert((v + w).x == 4 && (v + w).y == 5); // v+w == (4,5)
  assert((v - w).x == 0 && (v - w).y == 1); // v-w == (0,1)

Ideal:

  assert(v.x == 2 && v.y == 3);             // v   == (2,3)
  assert((v + w).x == 4 && (v + w).y == 5); // v+w == (4,5)
  assert((v - w).x == 0 && (v - w).y == 1); // v-w == (0,1)

This code is from https://github.com/dart-lang/dart-up-and-running-book/blob/master/code/ch02/vector.dart (part of a test for a snippet in Chapter 2).

Should use additional indentation to convey deeper nesting

Current

_log(new LogEntry(error.transform, error.transform.primaryId,
        LogLevel.ERROR, message, null));

is formatted as

_log(new LogEntry(error.transform, error.transform.primaryId,
    LogLevel.ERROR, message, null));

Having extra indentation for the second line is important to visually convey that the arguments are being passed to the inner function rather than the outer one. This is especially true if there are additional arguments.

This seems better when the "then"s line up

Not sure how to describe this, and it should probably just be rewritten, but it seems nicer in the before version where at least the .then calls line up

    return initFunction("en_US", dir)
        .then((_) {
          return Future.forEach(DateFormat.allLocalesWithSymbols(), (locale) {
            return initFunction(locale, dir);
          });
        })
        .then((_) {
          initialized = true;
        });

versus

    return initFunction("en_US", dir).then((_) {
      return Future.forEach(DateFormat.allLocalesWithSymbols(), (locale) {
        return initFunction(locale, dir);
      });
    }).then((_) {
      initialized = true;
    });

Not respecting line length when formatting long map entries

var German = const {
  "DAY": "27",
  "ABBR_WEEKDAY": "Fr.",
  "WEEKDAY": "Freitag",
  "ABBR_STANDALONE_MONTH": "Jan",
  "STANDALONE_MONTH": "Januar",
  "NUM_MONTH": "1",
  "NUM_MONTH_DAY": "27.1.",
  "NUM_MONTH_WEEKDAY_DAY": "Fr., 27.1.",
  "ABBR_MONTH": "Jan",
  "ABBR_MONTH_DAY": "27. Jan.",
  "ABBR_MONTH_WEEKDAY_DAY": "Fr., 27. Jan.",
  "MONTH": "Januar",
  "MONTH_DAY": "27. Januar",
  "MONTH_WEEKDAY_DAY": "Freitag, 27. Januar",
  "ABBR_QUARTER": "Q1",
  "QUARTER": "1. Quartal",
  "YEAR": "2012",
  "YEAR_NUM_MONTH": "1.2012",
  "YEAR_NUM_MONTH_DAY": "27.1.2012",
  "YEAR_NUM_MONTH_WEEKDAY_DAY": "Fr., 27.1.2012",
  "YEAR_ABBR_MONTH": "Jan. 2012",
  "YEAR_ABBR_MONTH_DAY": "27. Jan. 2012",
  "YEAR_ABBR_MONTH_WEEKDAY_DAY": "Fr., 27. Jan. 2012",
  "YEAR_MONTH": "Januar 2012",
  "YEAR_MONTH_DAY": "27. Januar 2012",
  "YEAR_MONTH_WEEKDAY_DAY": "Freitag, 27. Januar 2012",
  "YEAR_ABBR_QUARTER": "Q1 2012",
  "YEAR_QUARTER": "1. Quartal 2012",
  "HOUR24": "20 Uhr",
  "HOUR24_MINUTE": "20:58",
  "HOUR24_MINUTE_SECOND": "20:58:59",
  "HOUR": "20 Uhr",
  "HOUR_MINUTE": "20:58",
  "HOUR_MINUTE_SECOND": "20:58:59",
  "MINUTE": "58",
  "MINUTE_SECOND": "58:59",
  "SECOND": "59",
  "LOCATION_TZ": "Vereinigte Staaten Zeit (Los Angeles)",
  "GENERIC_TZ": "Nordamerikanische Westküstenzeit",
  "ABBR_GENERIC_TZ": "Vereinigte Staaten Zeit (Los Angeles)",
  "SPECIFIC_TZ": "Nordamerikanische Westküsten-Winterzeit",
  "ABBR_SPECIFIC_TZ": "GMT-08:00",
  "ABBR_UTC_TZ": "GMT-08:00",
  "YEAR_MONTH_WEEKDAY_DAY + HOUR_MINUTE_SECOND": "Freitag, 27. Januar 2012 20:58:59",
  "YEAR_MONTH_WEEKDAY_DAY + HOUR_MINUTE_SECOND + GENERIC_TZ": "Freitag, 27. Januar 2012 20:58:59 Nordamerikanische Westküstenzeit",
  "YEAR_ABBR_MONTH_WEEKDAY_DAY + HOUR_MINUTE_SECOND + ABBR_SPECIFIC_TZ": "Fr., 27. Jan 2012 20:58:59 GMT-08:00",
  "HOUR_MINUTE_SECOND + ABBR_GENERIC_TZ": "20:58:59 Vereinigte Staaten Zeit (Los Angeles)",
  "HOUR_MINUTE + ABBR_SPECIFIC_TZ": "20:58 GMT-08:00"
};

do not generate trailing whitespace before initializers

example test case (#EOL is not part of the input):

library foo;

class A {
  final C veryverylonglonglonglonglonglonglongname1;
  final C veryverylonglonglonglonglonglonglongname2;
  A(this.veryverylonglonglonglonglonglonglongname1)#EOL
      // comment
      : veryverylonglonglonglonglonglonglongname2 = new C();
}

The output will generate an extra space after the constructor arguments:

library foo;

class A {
  final C veryverylonglonglonglonglonglonglongname1;
  final C veryverylonglonglonglonglonglonglongname2;
  A(this.veryverylonglonglonglonglonglonglongname1) #EOL
      // comment
      : veryverylonglonglonglonglonglonglongname2 = new C();
}

If any method call starts on its own line, they all should

Currently

return AdminServer
    .bind(this, _hostname, port)
    .then((server) => _adminServer = server);

is formatted as

return AdminServer
    .bind(this, _hostname, port).then((server) => _adminServer = server);

The former seems clearer; in the latter, the then call looks like it's just part of the arguments to bind at a glance. I think the general rule here is that if any method call in a chain begins on a new line (.bind here), every method call in that chain should begin on a new line as well.

Overzealous wrapping in a map

I can't figure out why the first line is wrapped.

Input:

  var hawaiianBeaches = {
    'oahu'       : ['waikiki', 'kailua', 'waimanalo'],
    'big island' : ['wailea bay', 'pololu beach'],
    'kauai'      : ['hanalei', 'poipu']
  };

Output:

  var hawaiianBeaches = {
    'oahu': [
      'waikiki',
      'kailua',
      'waimanalo'
    ],
    'big island': ['wailea bay', 'pololu beach'],
    'kauai': ['hanalei', 'poipu']
  };

Expected:

  var hawaiianBeaches = {
    'oahu': ['waikiki', 'kailua', 'waimanalo'],
    'big island': ['wailea bay', 'pololu beach'],
    'kauai': ['hanalei', 'poipu']
  };

Ideally, the :s would still be aligned:

  var hawaiianBeaches = {
    'oahu'      : ['waikiki', 'kailua', 'waimanalo'],
    'big island': ['wailea bay', 'pololu beach'],
    'kauai'     : ['hanalei', 'poipu']
  };

Improper indentation in last chained call

The old indentation, while perhaps not ideal, was pretty clear that onDone and onError were arguments to listen():

  inputStream
    .transform(UTF8.decoder)
    .transform(new LineSplitter())
    .listen(
      (String line) { 
        print('Got ${line.length} characters from stream');
      },
      onDone: () { print('file is now closed'); },
      onError: (e) { print(e.toString()); });

The output of the formatter loses that clarity:

  inputStream
      .transform(UTF8.decoder)
      .transform(new LineSplitter())
      .listen((String line) {
    print('Got ${line.length} characters from stream');
  }, onDone: () {
    print('file is now closed');
  }, onError: (e) {
    print(e.toString());
  });

I'd expect something more like this:

  inputStream
      .transform(UTF8.decoder)
      .transform(new LineSplitter())
      .listen((String line) {
        print('Got ${line.length} characters from stream');
      }, onDone: () {
        print('file is now closed');
      }, onError: (e) {
        print(e.toString());
      });

List not lined up with main statement

If the rule for a list occurring anywhere in a statement is that it should be indeneted, based on the enclosing statement, then this seems wrong.

    var s = new Serialization()
            ..addRuleFor(Various, constructor: "Foo", constructorFields: [
          "d",
          "e"
        ]);

or at least inconsistent with

pluralThatFailsParsing(noOfThings) => Intl.plural(noOfThings, one: "1 thing:",
    other: "$noOfThings things:", name: "pluralThatFailsParsing", args: [
  noOfThings
], desc: "How many things are there?");

no longer skips sym_links

if you run it at the root of a project, it will formal all of the package directories, too

I'd vote for explicitly NOT navigating into sym_linked dirs – unless you add an explicit opt-in

Allow specifying the line length

Due to page width constraints, I need to use a 50-character (or so) line length for samples. It'd be wonderful if the formatter accepted a line length argument.

cascade indented by 8

In serialization/test/transformer/transformer_test_core.dart, I get formatting

  var serialization1 = new Serialization(format: format)
          ..addRules(rules.values);

where it's indented the cascade by 8 where I would think it should be 4.

Force newline between adjacent strings

from intl/test/message_extraction/verify_messages.dart

before:

  verify(
      "Caractères qui doivent être échapper, par exemple barres \\ "
      "dollars \${ (les accolades sont ok), et xml/html réservés <& et "
      "des citations \" "
      "avec quelques paramètres ainsi 1, 2, et 3");

after:

  verify("Caractères qui doivent être échapper, par exemple barres \\ "
      "dollars \${ (les accolades sont ok), et xml/html réservés <& et "
      "des citations \" " "avec quelques paramètres ainsi 1, 2, et 3");

It's possible that the escaped quote in there might also be involved.

do not generate blank line with whitespaces before comment

this:

library foo;

class A {
  final Map x;
  A() : x = {
        // comment
        'foo': 1,
        'bar': 2,
      };
}

generates:

library foo;

class A {
  final Map x;
  A() : x = {
        #EOL
        // comment
        'foo': 1,
        'bar': 2,
      };
}

#EOF

(as with the other bugs, #EOL and #EOF are my markers here to highlight the white space)

Fails to wrap long lines in parameter lists

Currently

List<Set<TransformerId>> _stageTransformers(
    Map<TransformerId, Set<TransformerId>> transformerDependencies) {

is formatted as

List<Set<TransformerId>> _stageTransformers(Map<TransformerId, Set<TransformerId>> transformerDependencies) {

Which is clearly more than 80 characters.

Weird wrapping for if statement

-      if (tag == 'style' || tag == 'script' &&
-            (type == null || type == TYPE_JS || type == TYPE_DART) ||
+      if (tag == 'style' ||
+          tag ==
+          'script' && (type == null || type == TYPE_JS || type == TYPE_DART) ||
           tag == 'link' && (rel == 'stylesheet' || rel == 'import')) {

Consider keeping groups of optional parameters together

The formatter changed this:

String say(String from, String msg,
  [String device='carrier pigeon', String mood]) {

To this:

String say(String from, String msg, [String device = 'carrier pigeon',
    String mood]) {

I wasn't sure the line break was necessary, but assuming it was, I expected the break in a different place, like this:

String say(String from, String msg,
    [String device = 'carrier pigeon', String mood]) {

I think the line break felt wrong because it seemed like it was breaking up an expression.

Lists in parameters are not indented correctly

before:

Future<ProcessResult> extractMessages(ProcessResult previousResult) => run(
    previousResult, [asTestDirPath('../../bin/extract_to_arb.dart'),
    '--suppress-warnings', 'sample_with_messages.dart',
    'part_of_sample_with_messages.dart']);

after:

Future<ProcessResult> extractMessages(ProcessResult previousResult) =>
    run(previousResult, [
  asTestDirPath('../../bin/extract_to_arb.dart'),
  '--suppress-warnings',
  'sample_with_messages.dart',
  'part_of_sample_with_messages.dart'
]);

There's another example in #22

Closure in chained function call doesn't have proper indentation

-      experimentalBootstrap = document.querySelectorAll('link').any((link) =>
-          link.attributes['rel'] == 'import' &&
-          link.attributes['href'] == POLYMER_EXPERIMENTAL_HTML);
+      experimentalBootstrap = document
+          .querySelectorAll('link')
+          .any((link) => link.attributes['rel'] ==
+          'import' && link.attributes['href'] == POLYMER_EXPERIMENTAL_HTML);

formatter is adding blank line at the end

The formatter injects an extra blank line at the end of the file. No need for it.

Example:

class A {
  A();
}
#EOF

(#EOF is not in the file, just added to make the EOF clear),

the formatter produces:

class A {
  A();
}

#EOF

Moving end of line comment in a map to the next line is deceptive

before:

  'af' : const {
    'd': 'd', // DAY
    'E': 'EEE', // ABBR_WEEKDAY
    'EEEE': 'EEEE', // WEEKDAY
    'LLL': 'LLL', // ABBR_STANDALONE_MONTH

after:

  'af': const {
    'd': 'd',
     // DAY
    'E': 'EEE',
     // ABBR_WEEKDAY
    'EEEE': 'EEEE',
     // WEEKDAY
    'LLL': 'LLL',
     // ABBR_STANDALONE_MONTH

Makes it look like the // DAY comment applies to the 'E' entry, as well as making the map take up twice as many lines.

Lines should avoid being split within method calls

Currently

var overlapping = _directories.keys.where((directory) =>
    path.isWithin(directory, rootDirectory) ||
    path.isWithin(rootDirectory, directory)).toList();

is formatted as

var overlapping = _directories.keys
    .where((directory) => path.isWithin(directory, rootDirectory) || path
        .isWithin(rootDirectory, directory)).toList();

The fact that the wrapping occurs between path and .isWithin seems very weird to me. It feels internal to an expression in a way that wrapping after the || doesn't. Maybe the line-break heuristics should be tweaked to give more weight to keeping method calls together if possible.

Give preference to generate many chained calls, each on its own line.

Give preference to generate many chained calls, each on its own line. For example, preserve:

Future foo() {
  return new Future(() {})
      .then(doSomething)
      .then(doSomething)
      .then(doSomething)
      .then(doSomething)
      .then(doSomething)
      .then(doSomething)
      .then(doSomething)
      .then(doSomething)
      .then(doSomething)
      .then(doSomething)
      .then(doSomething)
      .then(doSomething)
      .then(doSomething)
      .then(doSomething);
}

instead of producing:

Future foo() {
  return new Future(() {}).then(doSomething).then(doSomething)
      .then(doSomething).then(doSomething).then(doSomething).then(doSomething)
      .then(doSomething).then(doSomething).then(doSomething).then(doSomething)
      .then(doSomething).then(doSomething).then(doSomething).then(doSomething);
}

try to not group ternary if when possible

return new _Concat(
      (left != null) ? left : this.left,
      (right != null) ? right : this.right);

renders as

return new _Concat((left != null) ? left :
      this.left, (right != null) ? right : this.right);

Don't move a triple-quote to the next line and indent it as the only thing on the line

before:

String prologue(String locale) => """
/**
 * DO NOT EDIT. This is code generated via pkg/intl/generate_localized.dart
 * This is a library that provides messages for a $locale locale. All the
...

after:

String prologue(String locale) =>
    """
/**
 * DO NOT EDIT. This is code generated via pkg/intl/generate_localized.dart
 * This is a library that provides messages for a $locale locale. All the
...

give precedence to break binary operators before method calls

Example code:

foo() {
  assert(argument != argument && (argument.isDynamic || argument.isSubTypeOf(argument, argument)));
}

output I get today:

foo() {
  assert(argument != argument && (argument.isDynamic || argument
      .isSubTypeOf(argument, argument)));
}

expected output:

foo() {
  assert(argument != argument && (argument.isDynamic ||
      argument.isSubTypeOf(argument, argument)));
}

Don't collapse map literals onto fewer lines

It seems like this is expanding lists with more than a certain number of entries to be one per line, but is doing the opposite with map entries.

before

Map numberFormatSymbols = const {
  /**
   * Number formatting symbols for locale af.
   */
  "af" : const NumberSymbols(
      NAME: "af",
      DECIMAL_SEP: ',',
      GROUP_SEP: '\u00A0',
      PERCENT: '%',
      ZERO_DIGIT: '0',
      PLUS_SIGN: '+',
      MINUS_SIGN: '-',
      EXP_SYMBOL: 'E',
      PERMILL: '\u2030',
      INFINITY: '\u221E',
      NAN: 'NaN',
      DECIMAL_PATTERN: '#,##0.###',
      SCIENTIFIC_PATTERN: '#E0',
      PERCENT_PATTERN: '#,##0%',
      CURRENCY_PATTERN: '\u00A4#,##0.00',
      DEF_CURRENCY_CODE: 'ZAR'
),
...

after:

Map numberFormatSymbols = const {

  /**
   * Number formatting symbols for locale af.
   */
  "af": const NumberSymbols(NAME: "af", DECIMAL_SEP: ',', GROUP_SEP: '\u00A0',
      PERCENT: '%', ZERO_DIGIT: '0', PLUS_SIGN: '+', MINUS_SIGN: '-',
      EXP_SYMBOL: 'E', PERMILL: '\u2030', INFINITY: '\u221E', NAN: 'NaN',
      DECIMAL_PATTERN: '#,##0.###', SCIENTIFIC_PATTERN: '#E0',
      PERCENT_PATTERN: '#,##0%', CURRENCY_PATTERN: '\u00A4#,##0.00',
      DEF_CURRENCY_CODE: 'ZAR'),

Pulling .map up onto previous line makes indentation more confusing even if it fits

before:

  Map<int, DateTime> generateDates(int year, int leapDay) =>
      new Iterable.generate(365 + leapDay, (n) => n + 1)
        .map((day) {
          var result = new DateTime(year, 1, day);
          // TODO(alanknight): This is a workaround for dartbug.com/15560.
          if (result.toUtc() == result) result = new DateTime(year, 1, day);
          return result;
        }).toList().asMap();

after:

  Map<int, DateTime> generateDates(int year, int leapDay) =>
      new Iterable.generate(365 + leapDay, (n) => n + 1).map((day) {
    var result = new DateTime(year, 1, day);
    // TODO(alanknight): This is a workaround for dartbug.com/15560.
    if (result.toUtc() == result) result = new DateTime(year, 1, day);
    return result;
  }).toList().asMap();

function args shouldn't break on a . if possible

A couple examples of ones that look weird to me:

-      return _parseHtml(content, id.path, logger,
-        checkDocType: options.isHtmlEntryPoint(id));
+      return _parseHtml(content, id.path, logger, checkDocType: options
+          .isHtmlEntryPoint(id));

and

-        logger.warning(HTML5_WARNING.create({'message': e.message}),
-            span: e.span);
+        logger.warning(HTML5_WARNING
+            .create({'message': e.message}), span: e.span);

and

-  return builder.relative(builder.join('/', id.path),
-      from: builder.join('/', builder.dirname(sourceId.path)));
+  return builder.relative(builder.join('/', id.path), from: builder
+      .join('/', builder.dirname(sourceId.path)));

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.