Format extensions. (#1318)
This was trivial thanks to `createType()`.
diff --git a/lib/src/front_end/ast_node_visitor.dart b/lib/src/front_end/ast_node_visitor.dart
index d942085..5fa2060 100644
--- a/lib/src/front_end/ast_node_visitor.dart
+++ b/lib/src/front_end/ast_node_visitor.dart
@@ -433,7 +433,14 @@
@override
void visitExtensionDeclaration(ExtensionDeclaration node) {
- throw UnimplementedError();
+ createType(node.metadata, const [], node.extensionKeyword, node.name,
+ typeParameters: node.typeParameters,
+ onType: (node.onKeyword, node.extendedType),
+ body: (
+ leftBracket: node.leftBracket,
+ members: node.members,
+ rightBracket: node.rightBracket
+ ));
}
@override
diff --git a/lib/src/front_end/piece_factory.dart b/lib/src/front_end/piece_factory.dart
index c9a554a..c0f42b0 100644
--- a/lib/src/front_end/piece_factory.dart
+++ b/lib/src/front_end/piece_factory.dart
@@ -450,8 +450,11 @@
///
/// For mixin application classes, [body] is `null` and instead [equals],
/// [superclass], and [semicolon] are provided.
+ ///
+ /// If the type is an extension, then [onType] is a record containing the
+ /// `on` keyword and the on type.
void createType(NodeList<Annotation> metadata, List<Token?> modifiers,
- Token keyword, Token name,
+ Token keyword, Token? name,
{TypeParameterList? typeParameters,
Token? equals,
NamedType? superclass,
@@ -460,14 +463,14 @@
WithClause? withClause,
ImplementsClause? implementsClause,
NativeClause? nativeClause,
+ (Token, TypeAnnotation)? onType,
({Token leftBracket, List<AstNode> members, Token rightBracket})? body,
Token? semicolon}) {
if (metadata.isNotEmpty) throw UnimplementedError('Type metadata.');
modifiers.forEach(modifier);
token(keyword);
- space();
- token(name);
+ token(name, before: space);
visit(typeParameters);
// Mixin application classes have ` = Superclass` after the declaration
@@ -514,6 +517,10 @@
implementsClause.implementsKeyword, implementsClause.interfaces);
}
+ if (onType case (var onKeyword, var onType)?) {
+ typeClause(onKeyword, [onType]);
+ }
+
ClausesPiece? clausesPiece;
if (clauses.isNotEmpty) {
clausesPiece = ClausesPiece(clauses,
diff --git a/test/declaration/extension.unit b/test/declaration/extension.unit
new file mode 100644
index 0000000..bf59c84
--- /dev/null
+++ b/test/declaration/extension.unit
@@ -0,0 +1,69 @@
+40 columns |
+>>> Empty body.
+extension A on B {
+
+
+ }
+<<<
+extension A on B {}
+>>> Members.
+extension A on B{z() => 0;f() { body; }}
+<<<
+extension A on B {
+ z() => 0;
+ f() {
+ body;
+ }
+}
+>>> Insert blank line before and after extension.
+var x = 1;
+extension A on B {}
+var y = 2;
+<<<
+var x = 1;
+
+extension A on B {}
+
+var y = 2;
+>>> Unsplit type parameters.
+extension A < T , S > on B {}
+<<<
+extension A<T, S> on B {}
+>>> Split type parameters.
+extension Extension<LongTypeParameter, Another> on BaseClass {}
+<<<
+extension Extension<
+ LongTypeParameter,
+ Another
+> on BaseClass {}
+>>> Unnamed.
+extension on String {}
+<<<
+extension on String {}
+>>> Unnamed with type parameters.
+extension < T , S > on B {}
+<<<
+extension<T, S> on B {}
+>>> Split at `on`.
+extension SomeExtension on VeryLongClass {}
+<<<
+extension SomeExtension
+ on VeryLongClass {}
+>>> Unsplit generic on type.
+extension SomeExtension on C<int> {}
+<<<
+extension SomeExtension on C<int> {}
+>>> Split before `on` on generic on type.
+extension SomeExtension on C<SomeLongClass> {}
+<<<
+extension SomeExtension
+ on C<SomeLongClass> {}
+>>> Split in generic on type.
+extension SomeExtension on C<VeryLongType, AnotherLongType> {}
+<<<
+extension SomeExtension
+ on
+ C<
+ VeryLongType,
+ AnotherLongType
+ > {}
\ No newline at end of file