Support new generic function typedef syntax. (#610)
Fix #563.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 28c4d4c..4c0caf2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 1.0.2
+
+* Support new generic function typedef syntax (#563).
+
# 1.0.1
* Ensure space between `-` and `--` (#170).
diff --git a/lib/src/source_visitor.dart b/lib/src/source_visitor.dart
index faab9e8..60f5620 100644
--- a/lib/src/source_visitor.dart
+++ b/lib/src/source_visitor.dart
@@ -1181,6 +1181,25 @@
});
}
+ visitGenericFunctionType(GenericFunctionType node) {
+ visit(node.returnType, after: space);
+ token(node.functionKeyword);
+ _visitParameterSignature(node.typeParameters, node.parameters);
+ }
+
+ visitGenericTypeAlias(GenericTypeAlias node) {
+ visitNodes(node.metadata, between: newline, after: newline);
+ _simpleStatement(node, () {
+ token(node.typedefKeyword);
+ space();
+ visit(node.name);
+ space();
+ token(node.equals);
+ space();
+ visit(node.functionType);
+ });
+ }
+
visitHideCombinator(HideCombinator node) {
_visitCombinator(node.keyword, node.hiddenNames);
}
@@ -1555,7 +1574,14 @@
builder.nestExpression();
modifier(node.covariantKeyword);
modifier(node.keyword);
- visit(node.type, after: split);
+
+ visit(node.type);
+
+ // In function declarations and the old typedef syntax, you can have a
+ // parameter name without a type. In the new syntax, you can have a type
+ // without a name. Handle both cases.
+ if (node.type != null && node.identifier != null) split();
+
visit(node.identifier);
builder.unnest();
builder.endRule();
@@ -2016,6 +2042,18 @@
builder.startLazyRule(new Rule(Cost.arrow));
}
+ _visitParameterSignature(typeParameters, parameters);
+
+ if (beforeBody != null) beforeBody();
+ visit(body);
+
+ if (body is ExpressionFunctionBody) builder.unnest();
+ }
+
+ /// Visits the type parameters (if any) and formal parameters of a method
+ /// declaration, function declaration, or generic function type.
+ void _visitParameterSignature(TypeParameterList typeParameters,
+ FormalParameterList parameters) {
// Start the nesting for the parameters here, so they wrap around the
// type parameters too, if any.
builder.nestExpression();
@@ -2026,11 +2064,6 @@
}
builder.unnest();
-
- if (beforeBody != null) beforeBody();
- visit(body);
-
- if (body is ExpressionFunctionBody) builder.unnest();
}
/// Visits the body statement of a `for`, `for in`, or `while` loop.
diff --git a/pubspec.lock b/pubspec.lock
index 2a59357..5ff28ee 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -6,7 +6,7 @@
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
- version: "0.29.8"
+ version: "0.29.9"
ansicolor:
description:
name: ansicolor
diff --git a/pubspec.yaml b/pubspec.yaml
index b6d7c02..c48ef27 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,13 +1,13 @@
name: dart_style
# Note: See tool/grind.dart for how to bump the version.
-version: 1.0.1
+version: 1.0.2-dev
author: Dart Team <misc@dartlang.org>
description: Opinionated, automatic Dart source code formatter.
homepage: https://github.com/dart-lang/dart_style
environment:
sdk: ">=1.8.0 <2.0.0"
dependencies:
- analyzer: '^0.29.5'
+ analyzer: '^0.29.9'
args: '>=0.12.1 <0.14.0'
path: '>=1.0.0 <2.0.0'
source_span: '>=1.1.1 <2.0.0'
diff --git a/test/splitting/function_types.unit b/test/splitting/function_types.unit
new file mode 100644
index 0000000..130b45f
--- /dev/null
+++ b/test/splitting/function_types.unit
@@ -0,0 +1,22 @@
+40 columns |
+>>> split type parameters (skip: published version of analyzer doesn't support function types yet)
+typedef G = T Function<TypeOne, TypeTwo, TypeThree>();
+<<<
+typedef G = T Function<TypeOne, TypeTwo,
+ TypeThree>();
+>>> split all type parameters (skip: published version of analyzer doesn't support function types yet)
+typedef G = T Function<TypeOne, TypeTwo, TypeThree, TypeFour, TypeFive, TypeSix>();
+<<<
+typedef G = T Function<
+ TypeOne,
+ TypeTwo,
+ TypeThree,
+ TypeFour,
+ TypeFive,
+ TypeSix>();
+>>> split type and value parameters (skip: published version of analyzer doesn't support function types yet)
+typedef G = T Function<TypeOne, TypeTwo, TypeThree>(TypeOne one, TypeTwo two, TypeThree three);
+<<<
+typedef G = T Function<TypeOne, TypeTwo,
+ TypeThree>(TypeOne one,
+ TypeTwo two, TypeThree three);
\ No newline at end of file
diff --git a/test/whitespace/function_types.unit b/test/whitespace/function_types.unit
new file mode 100644
index 0000000..4d92ad3
--- /dev/null
+++ b/test/whitespace/function_types.unit
@@ -0,0 +1,28 @@
+40 columns |
+>>> non-generic in typedef (skip: published version of analyzer doesn't support function types yet)
+typedef SomeFunc=ReturnType Function(int param, double other);
+<<<
+typedef SomeFunc = ReturnType Function(
+ int param, double other);
+>>> generic in typedef (skip: published version of analyzer doesn't support function types yet)
+typedef Generic = T Function<T>(T param, double other);
+<<<
+typedef Generic = T Function<T>(
+ T param, double other);
+>>> no return type (skip: published version of analyzer doesn't support function types yet)
+typedef SomeFunc = Function();
+<<<
+typedef SomeFunc = Function();
+>>> nested (skip: published version of analyzer doesn't support function types yet)
+typedef SomeFunc = Function(int first, Function(int first, bool second, String third) second, String third);
+<<<
+typedef SomeFunc = Function(
+ int first,
+ Function(int first, bool second,
+ String third)
+ second,
+ String third);
+>>> without param names (skip: published version of analyzer doesn't support function types yet)
+typedef F = Function(int, bool, String);
+<<<
+typedef F = Function(int, bool, String);
\ No newline at end of file
diff --git a/test/whitespace/metadata.unit b/test/whitespace/metadata.unit
index 7f70cf7..ce92c11 100644
--- a/test/whitespace/metadata.unit
+++ b/test/whitespace/metadata.unit
@@ -253,4 +253,9 @@
function(
@Annotation
@VeryLongMetadataAnnotation
- covariant longParameter) {}
\ No newline at end of file
+ covariant longParameter) {}
+>>> metadata on function typedef (skip: published version of analyzer doesn't support function types yet)
+@foo typedef Fn = Function();
+<<<
+@foo
+typedef Fn = Function();
\ No newline at end of file