@@ -379,6 +379,59 @@ final class SourceVisitor extends ThrowingAstVisitor {
379379 _visitBody (node.leftBracket, node.statements, node.rightBracket);
380380 }
381381
382+ @override
383+ void visitBlockClassBody (BlockClassBody node) {
384+ _visitBody (node.leftBracket, node.members, node.rightBracket);
385+ }
386+
387+ @override
388+ void visitBlockEnumBody (BlockEnumBody node) {
389+ _beginBody (node.leftBracket, space: true );
390+
391+ visitCommaSeparatedNodes (node.constants, between: splitOrTwoNewlines);
392+
393+ // If there is a trailing comma, always force the constants to split.
394+ var trailingComma = node.constants.last.commaAfter;
395+ if (trailingComma != null ) {
396+ builder.forceRules ();
397+ }
398+
399+ // The ";" after the constants, which may occur after a trailing comma.
400+ var afterConstants = node.constants.last.endToken.next! ;
401+ Token ? semicolon;
402+ if (afterConstants.type == TokenType .SEMICOLON ) {
403+ semicolon = node.constants.last.endToken.next! ;
404+ } else if (trailingComma != null &&
405+ trailingComma.next! .type == TokenType .SEMICOLON ) {
406+ semicolon = afterConstants.next! ;
407+ }
408+
409+ if (semicolon != null ) {
410+ // If there is both a trailing comma and a semicolon, move the semicolon
411+ // to the next line. This doesn't look great but it's less bad than being
412+ // next to the comma.
413+ // TODO(rnystrom): If the formatter starts making non-whitespace changes
414+ // like adding/removing trailing commas, then it should fix this too.
415+ if (trailingComma != null ) newline ();
416+
417+ token (semicolon);
418+
419+ // Put a blank line between the constants and members.
420+ if (node.members.isNotEmpty) twoNewlines ();
421+ }
422+
423+ _visitBodyContents (node.members);
424+
425+ _endBody (
426+ node.rightBracket,
427+ forceSplit:
428+ semicolon != null ||
429+ trailingComma != null ||
430+ node.members.isNotEmpty ||
431+ node.constants.containsLineComments (),
432+ );
433+ }
434+
382435 @override
383436 void visitBlockFunctionBody (BlockFunctionBody node) {
384437 // Space after the parameter list.
@@ -599,17 +652,14 @@ final class SourceVisitor extends ThrowingAstVisitor {
599652 modifier (node.mixinKeyword);
600653 token (node.classKeyword);
601654 space ();
602- token (node.namePart.typeName);
603- visit (node.namePart.typeParameters);
655+ visit (node.namePart);
604656 visit (node.extendsClause);
605657 _visitClauses (node.withClause, node.implementsClause);
606658 visit (node.nativeClause, before: space);
607- space ();
608-
659+ if (node.body is ! EmptyClassBody ) space ();
609660 builder.unnest ();
610- // TODO(scheglov): support for EmptyBody
611- var body = node.body as BlockClassBody ;
612- _visitBody (body.leftBracket, body.members, body.rightBracket);
661+
662+ visit (node.body);
613663 }
614664
615665 @override
@@ -977,6 +1027,16 @@ final class SourceVisitor extends ThrowingAstVisitor {
9771027 token (node.literal);
9781028 }
9791029
1030+ @override
1031+ void visitEmptyClassBody (EmptyClassBody node) {
1032+ token (node.semicolon);
1033+ }
1034+
1035+ @override
1036+ void visitEmptyEnumBody (EmptyEnumBody node) {
1037+ token (node.semicolon);
1038+ }
1039+
9801040 @override
9811041 void visitEmptyFunctionBody (EmptyFunctionBody node) {
9821042 token (node.semicolon);
@@ -1015,64 +1075,13 @@ final class SourceVisitor extends ThrowingAstVisitor {
10151075 builder.nestExpression ();
10161076 token (node.enumKeyword);
10171077 space ();
1018- token (node.namePart.typeName);
1019- visit (node.namePart.typeParameters);
1078+ visit (node.namePart);
10201079 _visitClauses (node.withClause, node.implementsClause);
1021- space ();
10221080
1081+ if (node.body is ! EmptyEnumBody ) space ();
10231082 builder.unnest ();
10241083
1025- // TODO(scheglov): support for EmptyEnumBody
1026- var body = node.body as BlockEnumBody ;
1027- _beginBody (body.leftBracket, space: true );
1028-
1029- visitCommaSeparatedNodes (body.constants, between: splitOrTwoNewlines);
1030-
1031- // If there is a trailing comma, always force the constants to split.
1032- var trailingComma = body.constants.last.commaAfter;
1033- if (trailingComma != null ) {
1034- builder.forceRules ();
1035- }
1036-
1037- // The ";" after the constants, which may occur after a trailing comma.
1038- var afterConstants = body.constants.last.endToken.next! ;
1039- Token ? semicolon;
1040- if (afterConstants.type == TokenType .SEMICOLON ) {
1041- semicolon = body.constants.last.endToken.next! ;
1042- } else if (trailingComma != null &&
1043- trailingComma.next! .type == TokenType .SEMICOLON ) {
1044- semicolon = afterConstants.next! ;
1045- }
1046-
1047- if (semicolon != null ) {
1048- // If there is both a trailing comma and a semicolon, move the semicolon
1049- // to the next line. This doesn't look great but it's less bad than being
1050- // next to the comma.
1051- // TODO(rnystrom): If the formatter starts making non-whitespace changes
1052- // like adding/removing trailing commas, then it should fix this too.
1053- if (trailingComma != null ) newline ();
1054-
1055- token (semicolon);
1056-
1057- // Put a blank line between the constants and members.
1058- if (body.members.isNotEmpty) twoNewlines ();
1059- }
1060-
1061- _visitBodyContents (body.members);
1062-
1063- _endBody (
1064- body.rightBracket,
1065- forceSplit:
1066- semicolon != null ||
1067- trailingComma != null ||
1068- body.members.isNotEmpty ||
1069- // If there is a line comment after an enum constant, it won't
1070- // automatically force the enum body to split since the rule for
1071- // the constants is the hard rule used by the entire block and its
1072- // hardening state doesn't actually change. Instead, look
1073- // explicitly for a line comment here.
1074- body.constants.containsLineComments (),
1075- );
1084+ visit (node.body);
10761085 }
10771086
10781087 @override
@@ -1166,12 +1175,10 @@ final class SourceVisitor extends ThrowingAstVisitor {
11661175 space ();
11671176 visit (onClause.extendedType);
11681177 }
1169- space ();
1178+ if (node.body is ! EmptyClassBody ) space ();
11701179 builder.unnest ();
11711180
1172- // TODO(scheglov): support for EmptyBody
1173- var body = node.body as BlockClassBody ;
1174- _visitBody (body.leftBracket, body.members, body.rightBracket);
1181+ visit (node.body);
11751182 }
11761183
11771184 @override
@@ -1189,11 +1196,10 @@ final class SourceVisitor extends ThrowingAstVisitor {
11891196 visit (node.implementsClause);
11901197 builder.endRule ();
11911198
1192- space ();
1199+ if (node.body is ! EmptyClassBody ) space ();
11931200 builder.unnest ();
1194- // TODO(scheglov): support for EmptyBody
1195- var body = node.body as BlockClassBody ;
1196- _visitBody (body.leftBracket, body.members, body.rightBracket);
1201+
1202+ visit (node.body);
11971203 }
11981204
11991205 @override
@@ -2139,13 +2145,16 @@ final class SourceVisitor extends ThrowingAstVisitor {
21392145 visit (node.implementsClause);
21402146 builder.endRule ();
21412147
2142- space ();
2143-
2148+ if (node.body is ! EmptyClassBody ) space ();
21442149 builder.unnest ();
21452150
2146- // TODO(scheglov): support for EmptyBody
2147- var body = node.body as BlockClassBody ;
2148- _visitBody (body.leftBracket, body.members, body.rightBracket);
2151+ visit (node.body);
2152+ }
2153+
2154+ @override
2155+ void visitNameWithTypeParameters (NameWithTypeParameters node) {
2156+ token (node.typeName);
2157+ visit (node.typeParameters);
21492158 }
21502159
21512160 @override
0 commit comments