Merge branch 'chalin-max-sdk-to-3-0714' of https://github.com/chalin/dart_style into chalin-chalin-max-sdk-to-3-0714
# Conflicts:
# CHANGELOG.md
# analysis_options.yaml
# pubspec.lock
# pubspec.yaml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c6a1e24..63bbed8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
# 1.1.3
+* Preserve whitespace in multi-line strings inside string interpolations (#711).
+ **Note!** This bug means that dart_style 1.1.2 may make semantics changes to
+ your strings. You should avoid that version and use 1.1.3.
+
* Set max SDK version to <3.0.0, and adjusted other dependencies.
# 1.1.2
diff --git a/README.md b/README.md
index 3746768..a0d4400 100644
--- a/README.md
+++ b/README.md
@@ -5,10 +5,10 @@
[dart style guide]: https://www.dartlang.org/guides/language/effective-dart/style
-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 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:
@@ -36,8 +36,8 @@
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.
+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:
@@ -57,19 +57,23 @@
## Getting dartfmt
-Dartfmt is included in the Dart SDK, so you might want to add the SDK's bin
-directory to your system path.
+Dartfmt is included in the Dart SDK, so most users get it directly from there.
+That has the latest version of dartfmt that was available when the SDK was
+released.
-If you want to make sure you are running the latest version of dartfmt,
-you can [globally activate][] the package from the dart_style package
-on pub.dartlang.org, and let pub put its executable on your path:
+If you want to make sure you are running the latest version of dartfmt, you can
+[globally activate][] the package from the dart_style package on
+pub.dartlang.org:
$ pub global activate dart_style
$ dartfmt ...
+For this to work, you need to put pub's bin directory on your PATH before the
+Dart SDL directory. Otherwise, the SDK's dartfmt will shadow this one.
+
[globally activate]: https://www.dartlang.org/tools/pub/cmd/pub-global.html
-If you don't want `dartfmt` on your path, you can run it explicitly:
+If you don't want pub to put `dartfmt` on your PATH, you can run it explicitly:
$ pub global activate dart_style --no-executables
$ pub global run dart_style:format ...
@@ -77,28 +81,27 @@
## Using dartfmt
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**.
+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 dartfmt on the command line:
$ dartfmt test.dart
-This command formats the `test.dart` file and writes the result to
-standard output.
+This command formats the `test.dart` file and writes the result to standard
+output.
-Dartfmt 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.
-If no file or directory is specified, dartfmt reads from standard input.
+Dartfmt 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. If no file or directory is specified, dartfmt reads from
+standard input.
By default, it formats each file and just prints the resulting code to stdout.
-If you pass `-w`, it overwrites your existing files with the
-formatted results.
+If you pass `-w`, it overwrites your existing files with the formatted results.
-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.
+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
@@ -115,6 +118,7 @@
The package also exposes a single dart_style library containing a programmatic
API for formatting code. Simple usage looks like this:
+
```dart
import 'package:dart_style/dart_style.dart';
@@ -134,6 +138,7 @@
}
}
```
+
## Other resources
* Before sending an email, see if you are asking a
diff --git a/analysis_options.yaml b/analysis_options.yaml
index f0079f0..e4b1b8f 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,5 +1,3 @@
-analyzer:
-
linter:
rules:
- unawaited_futures
diff --git a/bin/format.dart b/bin/format.dart
index e0de12d..45756a3 100644
--- a/bin/format.dart
+++ b/bin/format.dart
@@ -15,7 +15,7 @@
import 'package:dart_style/src/style_fix.dart';
// Note: The following line of code is modified by tool/grind.dart.
-const version = "1.1.2";
+const version = "1.1.3";
void main(List<String> args) {
var parser = new ArgParser(allowTrailingOptions: true);
diff --git a/lib/src/chunk_builder.dart b/lib/src/chunk_builder.dart
index 4bdd166..a192f21 100644
--- a/lib/src/chunk_builder.dart
+++ b/lib/src/chunk_builder.dart
@@ -171,9 +171,20 @@
/// If [nest] is `false`, ignores any current expression nesting. Otherwise,
/// uses the current nesting level. If unsplit, it expands to a space if
/// [space] is `true`.
- Chunk split({bool flushLeft, bool isDouble, bool nest, bool space}) =>
- _writeSplit(_rules.last,
- flushLeft: flushLeft, isDouble: isDouble, nest: nest, space: space);
+ Chunk split({bool flushLeft, bool isDouble, bool nest, bool space}) {
+ space ??= false;
+
+ // If we are not allowed to split at all, don't. Returning null for the
+ // chunk is safe since the rule that uses the chunk will itself get
+ // discarded because no chunk references it.
+ if (_preventSplitNesting > 0) {
+ if (space) _pendingWhitespace = Whitespace.space;
+ return null;
+ }
+
+ return _writeSplit(_rules.last,
+ flushLeft: flushLeft, isDouble: isDouble, nest: nest, space: space);
+ }
/// Outputs the series of [comments] and associated whitespace that appear
/// before [token] (which is not written by this).
@@ -512,10 +523,6 @@
///
/// Nested blocks are handled using their own independent [LineWriter].
ChunkBuilder startBlock(Chunk argumentChunk) {
- // If we are not allowed to split at all, don't create a new block. Instead,
- // the block contents will end up in the current chunk.
- if (_preventSplitNesting > 0) return this;
-
var chunk = _chunks.last;
chunk.makeBlock(argumentChunk);
@@ -538,11 +545,6 @@
///
/// Returns the previous writer for the surrounding block.
ChunkBuilder endBlock(Rule ignoredSplit, {bool forceSplit}) {
- // If we are not allowed to split at all, we didn't create a new block and
- // thus didn't create a new ChunkBuilder, so there is no builder to pop.
- // We are still in the current one.
- if (_preventSplitNesting > 0) return this;
-
_divideChunks();
// If we don't already know if the block is going to split, see if it
@@ -767,21 +769,6 @@
/// to be at column zero. Otherwise, it uses the normal indentation and
/// nesting behavior.
void _writeHardSplit({bool isDouble, bool flushLeft, bool nest: false}) {
- // If we are not allowed to split at all, simply write a space. Instead of:
- //
- // foo("${() {
- // a;
- // b;
- // }}");
- //
- // produces:
- //
- // foo("${() { a; b; }}");
- if (_preventSplitNesting > 0) {
- _writeText(" ");
- return;
- }
-
// A hard split overrides any other whitespace.
_pendingWhitespace = null;
_writeSplit(new Rule.hard(),
@@ -796,14 +783,6 @@
nest ??= true;
space ??= false;
- // If we are not allowed to split at all, don't. Returning null for the
- // chunk is safe since the rule that uses the chunk will itself get
- // discarded because no chunk references it.
- if (_preventSplitNesting > 0) {
- if (space) write(" ");
- return null;
- }
-
if (_chunks.isEmpty) {
if (flushLeft != null) _firstFlushLeft = flushLeft;
diff --git a/pubspec.lock b/pubspec.lock
index 01f0f31..9c24470 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -49,7 +49,7 @@
name: cli_util
url: "https://pub.dartlang.org"
source: hosted
- version: "0.1.3"
+ version: "0.1.3+2"
collection:
dependency: transitive
description:
@@ -77,7 +77,7 @@
name: csslib
url: "https://pub.dartlang.org"
source: hosted
- version: "0.14.4"
+ version: "0.14.4+1"
front_end:
dependency: transitive
description:
@@ -168,7 +168,7 @@
name: matcher
url: "https://pub.dartlang.org"
source: hosted
- version: "0.12.3"
+ version: "0.12.3+1"
meta:
dependency: transitive
description:
@@ -245,7 +245,7 @@
name: shelf
url: "https://pub.dartlang.org"
source: hosted
- version: "0.7.3+2"
+ version: "0.7.3+3"
shelf_packages_handler:
dependency: transitive
description:
@@ -322,7 +322,7 @@
name: test
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0"
+ version: "1.3.0"
test_descriptor:
dependency: "direct dev"
description:
@@ -350,7 +350,7 @@
name: utf
url: "https://pub.dartlang.org"
source: hosted
- version: "0.9.0+4"
+ version: "0.9.0+5"
vm_service_client:
dependency: transitive
description:
@@ -380,4 +380,4 @@
source: hosted
version: "2.1.14"
sdks:
- dart: ">=2.0.0-dev.62.0 <=2.0.0-dev.68.0"
+ dart: ">=2.0.0-dev.62.0 <=2.0.0-edge.69a15d20069891ed13e7c65a6810527b4a9f9e40"
diff --git a/pubspec.yaml b/pubspec.yaml
index e67dc0d..476b11c 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,9 +1,8 @@
name: dart_style
# Note: See tool/grind.dart for how to bump the version.
version: 1.1.3
-
-description: Opinionated, automatic Dart source code formatter.
author: Dart Team <misc@dartlang.org>
+description: Opinionated, automatic Dart source code formatter.
homepage: https://github.com/dart-lang/dart_style
environment:
diff --git a/test/regression/0700/0711.stmt b/test/regression/0700/0711.stmt
new file mode 100644
index 0000000..8fd2179
--- /dev/null
+++ b/test/regression/0700/0711.stmt
@@ -0,0 +1,12 @@
+>>>
+var str = '''${"""
+a
+b
+c
+"""}''';
+<<<
+var str = '''${"""
+a
+b
+c
+"""}''';
\ No newline at end of file
diff --git a/test/splitting/strings.stmt b/test/splitting/strings.stmt
index d3bdaab..5321b70 100644
--- a/test/splitting/strings.stmt
+++ b/test/splitting/strings.stmt
@@ -161,8 +161,84 @@
someMethod(
"some text that is ${pretty + 'long ${interpolate + a + thing} more'} text",
"another arg");
->>> hard splits are not split in interpolation
+>>> hard splits are split in interpolation
someMethod("before ${(){statement();statement();statement();}} after");
<<<
-someMethod(
- "before ${() { statement(); statement(); statement(); }} after");
\ No newline at end of file
+someMethod("before ${() {
+ statement();
+ statement();
+ statement();
+}} after");
+>>> collections split in interpolation if needed
+method(
+"b ${[1, 2, 3, 4, 5, 6]} a",
+"before ${[first, second, third, fourth, {fifth: sixth}]} after");
+<<<
+method(
+ "b ${[1, 2, 3, 4, 5, 6]} a",
+ "before ${[
+ first,
+ second,
+ third,
+ fourth,
+ {fifth: sixth}
+ ]} after");
+>>> nested multiline strings are not merged in interpolation
+"before ${"""a
+b"""} ${aft
++
+er}";
+<<<
+"before ${"""a
+b"""} ${aft + er}";
+>>> multiply-nested interpolation
+'''a
+${b +
+"""c
+${d
++ '''e
+f'''
++
+g}
+h"""
++ i}
+j ${k
++
+l}''';
+<<<
+'''a
+${b + """c
+${d + '''e
+f''' + g}
+h""" + i}
+j ${k + l}''';
+>>> nested interpolation inside function
+"before ${ () { a(); """b
+c"""; d(); }} after";
+<<<
+"before ${() {
+ a();
+ """b
+c""";
+ d();
+}} after";
+>>> comment inside interpolation
+"before ${// comment
+a
++
+b
++ // another
+c} after";
+<<<
+"before ${ // comment
+ a + b + // another
+ c} after";
+>>>
+function(
+ "long string long string ${interpolated + interpolated} long string",
+ longLongLongLongObject.longLongLongLongMethod());
+<<<
+function(
+ "long string long string ${interpolated + interpolated} long string",
+ longLongLongLongObject
+ .longLongLongLongMethod());
\ No newline at end of file
diff --git a/test/utils.dart b/test/utils.dart
index 74fa489..0d5f889 100644
--- a/test/utils.dart
+++ b/test/utils.dart
@@ -62,6 +62,8 @@
var entries = new Directory(p.join(testDir, name))
.listSync(recursive: true, followLinks: false);
+ entries.sort((a, b) => a.path.compareTo(b.path));
+
for (var entry in entries) {
if (!entry.path.endsWith(".stmt") && !entry.path.endsWith(".unit")) {
continue;
diff --git a/test/whitespace/strings.stmt b/test/whitespace/strings.stmt
new file mode 100644
index 0000000..b44f8bf
--- /dev/null
+++ b/test/whitespace/strings.stmt
@@ -0,0 +1,9 @@
+40 columns |
+>>>
+"a" "b" "c";
+<<<
+"a" "b" "c";
+>>> empty multi-line
+"""""" '''''';
+<<<
+"""""" '''''';
\ No newline at end of file