Skip to content

Commit

Permalink
Format mixin declarations. (#1315)
Browse files Browse the repository at this point in the history
Format mixin declarations.

Almost nothing interesting here. The clauses are all handled the same
way we handle clauses in a class declaration. We treat the `on` clause
like the `extends` clause in a class, which means the other clauses can
split while allowing the on clause to stay on the top line if it fits.

Mixin classes (and their various modifiers) were already handled because
those are class declarations with a mixin modifier. Now there are tests
for them.
  • Loading branch information
munificent authored Nov 8, 2023
1 parent e860fda commit cf1c1c2
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 4 deletions.
12 changes: 10 additions & 2 deletions lib/src/front_end/ast_node_visitor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,15 @@ class AstNodeVisitor extends ThrowingAstVisitor<void>

@override
void visitMixinDeclaration(MixinDeclaration node) {
throw UnimplementedError();
createType(node.metadata, [node.baseKeyword], node.mixinKeyword, node.name,
typeParameters: node.typeParameters,
onClause: node.onClause,
implementsClause: node.implementsClause,
body: (
leftBracket: node.leftBracket,
members: node.members,
rightBracket: node.rightBracket
));
}

@override
Expand Down Expand Up @@ -885,7 +893,7 @@ class AstNodeVisitor extends ThrowingAstVisitor<void>

@override
void visitOnClause(OnClause node) {
throw UnimplementedError();
assert(false, 'This node is handled by PieceFactory.createType().');
}

@override
Expand Down
9 changes: 7 additions & 2 deletions lib/src/front_end/piece_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ mixin PieceFactory implements CommentWriter {
Token? equals,
NamedType? superclass,
ExtendsClause? extendsClause,
OnClause? onClause,
WithClause? withClause,
ImplementsClause? implementsClause,
NativeClause? nativeClause,
Expand Down Expand Up @@ -500,6 +501,10 @@ mixin PieceFactory implements CommentWriter {
typeClause(extendsClause.extendsKeyword, [extendsClause.superclass]);
}

if (onClause != null) {
typeClause(onClause.onKeyword, onClause.superclassConstraints);
}

if (withClause != null) {
typeClause(withClause.withKeyword, withClause.mixinTypes);
}
Expand All @@ -511,8 +516,8 @@ mixin PieceFactory implements CommentWriter {

ClausesPiece? clausesPiece;
if (clauses.isNotEmpty) {
clausesPiece =
ClausesPiece(clauses, allowLeadingClause: extendsClause != null);
clausesPiece = ClausesPiece(clauses,
allowLeadingClause: extendsClause != null || onClause != null);
}

visit(nativeClause);
Expand Down
54 changes: 54 additions & 0 deletions test/declaration/mixin.unit
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
40 columns |
>>> Empty body.
mixin M { }
<<<
mixin M {}
>>> Members.
### These are formatted the same as classes, so most of the member tests are
### covered there. This just ensures that the formatter handles all members in
### a mixin declaration.
mixin M {
static const int c = 1;
static final int f = 1;
static late final int l;
static var v;
static int get g => c;
static set g(int i) {}
static int m<X>(X x) => c;
int x;
int get pr => 0;
set pr(int x) {}
int me(int x) => x;
int operator+(int x) => x;
}
<<<
mixin M {
static const int c = 1;
static final int f = 1;
static late final int l;
static var v;
static int get g => c;
static set g(int i) {}
static int m<X>(X x) => c;
int x;
int get pr => 0;
set pr(int x) {}
int me(int x) => x;
int operator +(int x) => x;
}
>>> Modifiers.
mixin class M1 { }
base mixin class M2 { }
abstract mixin class M3 { }
abstract base mixin class M4 { }
base mixin M5 { }
<<<
mixin class M1 {}

base mixin class M2 {}

abstract mixin class M3 {}

abstract base mixin class M4 {}

base mixin M5 {}
124 changes: 124 additions & 0 deletions test/declaration/mixin_clause.unit
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
40 columns |
>>> Unsplit on clause.
mixin A on B {}
<<<
mixin A on B {}
>>> Multiple unsplit types in on clause.
mixin M2 on A , B , C { }
<<<
mixin M2 on A, B, C {}
>>> Split at `on`.
mixin SomeLongMixin on VeryLongBaseMixin {}
<<<
mixin SomeLongMixin
on VeryLongBaseMixin {}
>>> Split multiple at `on`.
mixin LongMixin on SupertypeA , SupertypeB { }
<<<
mixin LongMixin
on SupertypeA, SupertypeB {}
>>> Split multiple on clause.
mixin M2 on SupertypeA , SupertypeB , SupertypeC { }
<<<
mixin M2
on
SupertypeA,
SupertypeB,
SupertypeC {}
>>> Unsplit implements clause.
mixin A implements B {}
<<<
mixin A implements B {}
>>> Unsplit multiple clauses.
mixin A on B implements D {}
<<<
mixin A on B implements D {}
>>> Split at `implements`.
mixin SomeMixin implements VeryLongBaseMixin {}
<<<
mixin SomeMixin
implements VeryLongBaseMixin {}
>>> Split at `implements` but not between interfaces.
mixin SomeMixin implements Interface, AnotherOne {}
<<<
mixin SomeMixin
implements Interface, AnotherOne {}
>>> Split at `implements` and interfaces.
mixin SomeMixin implements Interface, Another, Third {}
<<<
mixin SomeMixin
implements
Interface,
Another,
Third {}
>>> Split at `on` splits `implements` too.
mixin AVeryLongSomeMixin on LongBaseMixin implements I {}
<<<
mixin AVeryLongSomeMixin
on LongBaseMixin
implements I {}
>>>
mixin AVeryLongSomeMixin on LongBaseMixin implements Interface {}
<<<
mixin AVeryLongSomeMixin
on LongBaseMixin
implements Interface {}
>>> Can split `implements` clause without splitting `on`.
mixin SomeMixin on A implements Type, Another {}
<<<
mixin SomeMixin on A
implements Type, Another {}
>>>
mixin SomeMixin on A implements Type, Another, Third, Fourth {}
<<<
mixin SomeMixin on A
implements
Type,
Another,
Third,
Fourth {}
>>> Unsplit generic supermixin.
mixin SomeMixin on C<int> {}
<<<
mixin SomeMixin on C<int> {}
>>> Split before `on` on generic supermixin.
mixin SomeMixin on Superclass<SomeLongmixin> {}
<<<
mixin SomeMixin
on Superclass<SomeLongmixin> {}
>>> Split in generic supermixin.
mixin SomeMixin on C<VeryLongType, AnotherLongType> {}
<<<
mixin SomeMixin
on
C<
VeryLongType,
AnotherLongType
> {}
>>> Unsplit generic superinterface.
mixin SomeMixin implements C<int> {}
<<<
mixin SomeMixin implements C<int> {}
>>> Split before `implements` on generic superinterface.
mixin SomeMixin implements C<SomeLongmixin> {}
<<<
mixin SomeMixin
implements C<SomeLongmixin> {}
>>> Split in generic superinterface.
mixin SomeMixin implements C<VeryLongType, AnotherLongType> {}
<<<
mixin SomeMixin
implements
C<
VeryLongType,
AnotherLongType
> {}
>>> Split in generic `implements` clause does not force `on` clause to split.
mixin C on A implements B<LongTypeArgument, AnotherLongType> {}
<<<
mixin C on A
implements
B<
LongTypeArgument,
AnotherLongType
> {}

0 comments on commit cf1c1c2

Please sign in to comment.