Require analyzer 10.0.0, stop using deprecated nodes and properties. (#1795)
* Require analyzer 10.0.0, stop using deprecated nodes and properties.
* Prepare for publishing 3.1.4, remove -wip.
* Fixes for review comments.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3dc28ca..64a83db 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
-## 3.1.4-wip
+## 3.1.4
* Remove dependencies on analyzer internal implementation.
+* Require `analyzer: '^10.0.0'`.
## 3.1.3
diff --git a/lib/src/front_end/ast_node_visitor.dart b/lib/src/front_end/ast_node_visitor.dart
index 4193f13..eb9729e 100644
--- a/lib/src/front_end/ast_node_visitor.dart
+++ b/lib/src/front_end/ast_node_visitor.dart
@@ -293,15 +293,17 @@
node.mixinKeyword,
node.classKeyword,
],
- node.name,
- typeParameters: node.typeParameters,
+ name: node.namePart.typeName,
+ typeParameters: node.namePart.typeParameters,
extendsClause: node.extendsClause,
withClause: node.withClause,
implementsClause: node.implementsClause,
nativeClause: node.nativeClause,
body: () {
+ // TODO(scheglov): support for EmptyBody
+ var body = node.body as BlockClassBody;
return pieces.build(() {
- writeBody(node.leftBracket, node.members, node.rightBracket);
+ writeBody(body.leftBracket, body.members, body.rightBracket);
});
},
);
@@ -320,10 +322,10 @@
node.mixinKeyword,
node.typedefKeyword,
],
- node.name,
+ name: node.name,
+ typeParameters: node.typeParameters,
equals: node.equals,
superclass: node.superclass,
- typeParameters: node.typeParameters,
withClause: node.withClause,
implementsClause: node.implementsClause,
bodyType: TypeBodyType.semicolon,
@@ -455,8 +457,9 @@
var header = pieces.build(() {
pieces.modifier(node.externalKeyword);
pieces.modifier(node.constKeyword);
+ pieces.modifier(node.newKeyword);
pieces.modifier(node.factoryKeyword);
- pieces.visit(node.returnType);
+ pieces.visit(node.typeName);
pieces.token(node.period);
pieces.token(node.name);
});
@@ -634,13 +637,15 @@
writeType(
node.metadata,
[node.enumKeyword],
- node.name,
- typeParameters: node.typeParameters,
+ name: node.namePart.typeName,
+ typeParameters: node.namePart.typeParameters,
withClause: node.withClause,
implementsClause: node.implementsClause,
- bodyType: node.members.isEmpty ? TypeBodyType.list : TypeBodyType.block,
+ bodyType: node.body.members.isEmpty
+ ? TypeBodyType.list
+ : TypeBodyType.block,
body: () {
- if (node.members.isEmpty) {
+ if (node.body.members.isEmpty) {
// If there are no members, format the constants like a list. This
// keeps the enum declaration on one line if it fits.
var builder = DelimitedListBuilder(
@@ -648,19 +653,22 @@
const ListStyle(spaceWhenUnsplit: true),
);
- builder.leftBracket(node.leftBracket);
- node.constants.forEach(builder.visit);
- builder.rightBracket(semicolon: node.semicolon, node.rightBracket);
+ builder.leftBracket(node.body.leftBracket);
+ node.body.constants.forEach(builder.visit);
+ builder.rightBracket(
+ semicolon: node.body.semicolon,
+ node.body.rightBracket,
+ );
return builder.build(
forceSplit: style.preserveTrailingCommaBefore(
- node.semicolon ?? node.rightBracket,
+ node.body.semicolon ?? node.body.rightBracket,
),
);
} else {
// If there are members, format it like a block where each constant
// and member is on its own line.
var builder = SequenceBuilder(this);
- builder.leftBracket(node.leftBracket);
+ builder.leftBracket(node.body.leftBracket);
// In 3.10 and later, preserved trailing commas will also preserve a
// trailing comma in an enum with members. That in turn forces the
@@ -668,15 +676,15 @@
// behavior is the same as when preserved trailing commas is off
// where the last constant's comma is removed and the `;` is placed
// there instead.
- for (var constant in node.constants) {
- var isLast = constant == node.constants.last;
+ for (var constant in node.body.constants) {
+ var isLast = constant == node.body.constants.last;
builder.addCommentsBefore(constant.firstNonCommentToken);
builder.add(
createEnumConstant(
constant,
commaAfter:
!isLast || style.preserveTrailingCommaAfterEnumValues,
- semicolon: isLast ? node.semicolon : null,
+ semicolon: isLast ? node.body.semicolon : null,
),
);
}
@@ -684,13 +692,13 @@
// If we are preserving the trailing comma, then put the `;` on its
// own line after the last constant.
if (style.preserveTrailingCommaAfterEnumValues) {
- builder.add(tokenPiece(node.semicolon!));
+ builder.add(tokenPiece(node.body.semicolon!));
}
// Insert a blank line between the constants and members.
builder.addBlank();
- for (var node in node.members) {
+ for (var node in node.body.members) {
builder.visit(node);
// If the node has a non-empty braced body, then require a blank
@@ -698,7 +706,7 @@
if (node.hasNonEmptyBody) builder.addBlank();
}
- builder.rightBracket(node.rightBracket);
+ builder.rightBracket(node.body.rightBracket);
return builder.build();
}
},
@@ -785,12 +793,16 @@
writeType(
node.metadata,
[node.extensionKeyword],
- node.name,
+ name: node.name,
typeParameters: node.typeParameters,
onType: onType,
body: () {
return pieces.build(() {
- writeBody(node.leftBracket, node.members, node.rightBracket);
+ writeBody(
+ node.body.leftBracket,
+ node.body.members,
+ node.body.rightBracket,
+ );
});
},
);
@@ -800,18 +812,14 @@
void visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) {
writeType(
node.metadata,
- [
- node.extensionKeyword,
- node.typeKeyword,
- if (node.constKeyword case var keyword?) keyword,
- ],
- node.name,
- typeParameters: node.typeParameters,
- representation: node.representation,
+ [node.extensionKeyword, node.typeKeyword],
+ primaryConstructor: node.primaryConstructor,
implementsClause: node.implementsClause,
body: () {
return pieces.build(() {
- writeBody(node.leftBracket, node.members, node.rightBracket);
+ // TODO(scheglov): support for EmptyBody
+ var body = node.body as BlockClassBody;
+ writeBody(body.leftBracket, body.members, body.rightBracket);
});
},
);
@@ -1532,13 +1540,17 @@
writeType(
node.metadata,
[node.baseKeyword, node.mixinKeyword],
- node.name,
+ name: node.name,
typeParameters: node.typeParameters,
onClause: node.onClause,
implementsClause: node.implementsClause,
body: () {
return pieces.build(() {
- writeBody(node.leftBracket, node.members, node.rightBracket);
+ writeBody(
+ node.body.leftBracket,
+ node.body.members,
+ node.body.rightBracket,
+ );
});
},
);
@@ -1747,6 +1759,62 @@
}
@override
+ void visitPrimaryConstructorBody(PrimaryConstructorBody node) {
+ pieces.withMetadata(node.metadata, () {
+ pieces.token(node.thisKeyword);
+
+ if (node.initializers.isNotEmpty) {
+ pieces.space();
+ pieces.token(node.colon);
+ pieces.space();
+ pieces.add(createCommaSeparated(node.initializers));
+ }
+
+ pieces.visit(node.body);
+ });
+ }
+
+ @override
+ void visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node) {
+ pieces.modifier(node.constKeyword);
+ pieces.token(node.typeName);
+ pieces.visit(node.typeParameters);
+ pieces.visit(node.constructorName);
+
+ if (node.parent is ExtensionTypeDeclaration) {
+ var formalParameters = node.formalParameters;
+ var builder = DelimitedListBuilder(
+ this,
+ const ListStyle(commas: Commas.nonTrailing),
+ );
+ builder.leftBracket(formalParameters.leftParenthesis);
+ for (var formalParameter in formalParameters.parameters) {
+ // TODO(scheglov): support for optional formal parameters
+ formalParameter as SimpleFormalParameter;
+ builder.add(
+ pieces.build(() {
+ writeParameter(
+ metadata: formalParameter.metadata,
+ formalParameter.type,
+ formalParameter.name,
+ );
+ }),
+ );
+ }
+ builder.rightBracket(formalParameters.rightParenthesis);
+ pieces.add(builder.build());
+ } else {
+ pieces.visit(node.formalParameters);
+ }
+ }
+
+ @override
+ void visitPrimaryConstructorName(PrimaryConstructorName node) {
+ pieces.token(node.period);
+ pieces.token(node.name);
+ }
+
+ @override
void visitPropertyAccess(PropertyAccess node) {
// If there's no target, this is a section in a cascade.
if (node.target == null) {
@@ -1861,34 +1929,6 @@
}
@override
- void visitRepresentationConstructorName(RepresentationConstructorName node) {
- pieces.token(node.period);
- pieces.token(node.name);
- }
-
- @override
- void visitRepresentationDeclaration(RepresentationDeclaration node) {
- pieces.visit(node.constructorName);
-
- var builder = DelimitedListBuilder(
- this,
- const ListStyle(commas: Commas.nonTrailing),
- );
- builder.leftBracket(node.leftParenthesis);
- builder.add(
- pieces.build(() {
- writeParameter(
- metadata: node.fieldMetadata,
- node.fieldType,
- node.fieldName,
- );
- }),
- );
- builder.rightBracket(node.rightParenthesis);
- pieces.add(builder.build());
- }
-
- @override
void visitRethrowExpression(RethrowExpression node) {
pieces.token(node.rethrowKeyword);
}
diff --git a/lib/src/front_end/piece_factory.dart b/lib/src/front_end/piece_factory.dart
index 5202d59..1bc8aba 100644
--- a/lib/src/front_end/piece_factory.dart
+++ b/lib/src/front_end/piece_factory.dart
@@ -1437,16 +1437,16 @@
/// If the type is an extension, then [onType] is a record containing the
/// `on` keyword and the on type.
///
- /// If the type is an extension type, then [representation] is the primary
- /// constructor for it.
+ /// If the type has a primary constructor, e.g. an extension type, then
+ /// [primaryConstructor] is not `null`.
void writeType(
NodeList<Annotation> metadata,
- List<Token?> keywords,
- Token? name, {
+ List<Token?> keywords, {
+ Token? name,
TypeParameterList? typeParameters,
Token? equals,
NamedType? superclass,
- RepresentationDeclaration? representation,
+ PrimaryConstructorDeclaration? primaryConstructor,
ExtendsClause? extendsClause,
MixinOnClause? onClause,
WithClause? withClause,
@@ -1481,9 +1481,8 @@
pieces.visit(superclass!);
}
- // Extension types have a representation type.
- if (representation != null) {
- pieces.visit(representation);
+ if (primaryConstructor != null) {
+ pieces.visit(primaryConstructor, spaceBefore: true);
}
});
diff --git a/lib/src/short/source_visitor.dart b/lib/src/short/source_visitor.dart
index 660347d..63973c5 100644
--- a/lib/src/short/source_visitor.dart
+++ b/lib/src/short/source_visitor.dart
@@ -599,15 +599,17 @@
modifier(node.mixinKeyword);
token(node.classKeyword);
space();
- token(node.name);
- visit(node.typeParameters);
+ token(node.namePart.typeName);
+ visit(node.namePart.typeParameters);
visit(node.extendsClause);
_visitClauses(node.withClause, node.implementsClause);
visit(node.nativeClause, before: space);
space();
builder.unnest();
- _visitBody(node.leftBracket, node.members, node.rightBracket);
+ // TODO(scheglov): support for EmptyBody
+ var body = node.body as BlockClassBody;
+ _visitBody(body.leftBracket, body.members, body.rightBracket);
}
@override
@@ -774,8 +776,9 @@
modifier(node.externalKeyword);
modifier(node.constKeyword);
+ modifier(node.newKeyword);
modifier(node.factoryKeyword);
- visit(node.returnType);
+ visit(node.typeName);
token(node.period);
token(node.name);
@@ -1017,28 +1020,28 @@
builder.nestExpression();
token(node.enumKeyword);
space();
- token(node.name);
- visit(node.typeParameters);
+ token(node.namePart.typeName);
+ visit(node.namePart.typeParameters);
_visitClauses(node.withClause, node.implementsClause);
space();
builder.unnest();
- _beginBody(node.leftBracket, space: true);
+ _beginBody(node.body.leftBracket, space: true);
- visitCommaSeparatedNodes(node.constants, between: splitOrTwoNewlines);
+ visitCommaSeparatedNodes(node.body.constants, between: splitOrTwoNewlines);
// If there is a trailing comma, always force the constants to split.
- var trailingComma = node.constants.last.commaAfter;
+ var trailingComma = node.body.constants.last.commaAfter;
if (trailingComma != null) {
builder.forceRules();
}
// The ";" after the constants, which may occur after a trailing comma.
- var afterConstants = node.constants.last.endToken.next!;
+ var afterConstants = node.body.constants.last.endToken.next!;
Token? semicolon;
if (afterConstants.type == TokenType.SEMICOLON) {
- semicolon = node.constants.last.endToken.next!;
+ semicolon = node.body.constants.last.endToken.next!;
} else if (trailingComma != null &&
trailingComma.next!.type == TokenType.SEMICOLON) {
semicolon = afterConstants.next!;
@@ -1055,23 +1058,23 @@
token(semicolon);
// Put a blank line between the constants and members.
- if (node.members.isNotEmpty) twoNewlines();
+ if (node.body.members.isNotEmpty) twoNewlines();
}
- _visitBodyContents(node.members);
+ _visitBodyContents(node.body.members);
_endBody(
- node.rightBracket,
+ node.body.rightBracket,
forceSplit:
semicolon != null ||
trailingComma != null ||
- node.members.isNotEmpty ||
+ node.body.members.isNotEmpty ||
// If there is a line comment after an enum constant, it won't
// automatically force the enum body to split since the rule for
// the constants is the hard rule used by the entire block and its
// hardening state doesn't actually change. Instead, look
// explicitly for a line comment here.
- node.constants.containsLineComments(),
+ node.body.constants.containsLineComments(),
);
}
@@ -1168,7 +1171,11 @@
}
space();
builder.unnest();
- _visitBody(node.leftBracket, node.members, node.rightBracket);
+ _visitBody(
+ node.body.leftBracket,
+ node.body.members,
+ node.body.rightBracket,
+ );
}
@override
@@ -1179,14 +1186,8 @@
token(node.extensionKeyword);
space();
token(node.typeKeyword);
- token(node.constKeyword, before: space);
- space();
- token(node.name);
- builder.nestExpression();
- visit(node.typeParameters);
- visit(node.representation);
- builder.unnest();
+ visit(node.primaryConstructor, before: space);
builder.startRule(CombinatorRule());
visit(node.implementsClause);
@@ -1194,7 +1195,9 @@
space();
builder.unnest();
- _visitBody(node.leftBracket, node.members, node.rightBracket);
+ // TODO(scheglov): support for EmptyBody
+ var body = node.body as BlockClassBody;
+ _visitBody(body.leftBracket, body.members, body.rightBracket);
}
@override
@@ -2152,7 +2155,11 @@
space();
builder.unnest();
- _visitBody(node.leftBracket, node.members, node.rightBracket);
+ _visitBody(
+ node.body.leftBracket,
+ node.body.members,
+ node.body.rightBracket,
+ );
}
@override
@@ -2366,6 +2373,41 @@
}
@override
+ void visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node) {
+ modifier(node.constKeyword);
+ token(node.typeName);
+ visit(node.typeParameters);
+ visit(node.constructorName);
+ visit(node.formalParameters);
+ }
+
+ @override
+ void visitPrimaryConstructorBody(PrimaryConstructorBody node) {
+ visitMetadata(node.metadata);
+ token(node.thisKeyword);
+
+ // TODO(scheglov): unify with `visitConstructorDeclaration`.
+ if (node.initializers.isNotEmpty) {
+ builder.startRule();
+ builder.indent(Indent.constructorInitializer);
+ split();
+ token(node.colon);
+ space();
+ visitCommaSeparatedNodes(node.initializers);
+ builder.unindent();
+ builder.endRule();
+ }
+
+ visit(node.body);
+ }
+
+ @override
+ void visitPrimaryConstructorName(PrimaryConstructorName node) {
+ token(node.period);
+ token(node.name);
+ }
+
+ @override
void visitPropertyAccess(PropertyAccess node) {
if (node.isCascaded) {
token(node.operator);
@@ -2518,46 +2560,6 @@
}
@override
- void visitRepresentationConstructorName(RepresentationConstructorName node) {
- token(node.period);
- token(node.name);
- }
-
- @override
- void visitRepresentationDeclaration(RepresentationDeclaration node) {
- visit(node.constructorName);
-
- token(node.leftParenthesis);
-
- var rule = PositionalRule(null, argumentCount: 1);
-
- builder.startRule(rule);
- rule.beforeArgument(zeroSplit());
-
- // Make sure record and function type parameter lists are indented.
- builder.startBlockArgumentNesting();
- builder.startSpan();
-
- visitParameterMetadata(node.fieldMetadata, () {
- builder.startLazyRule(Rule(Cost.parameterType));
- builder.nestExpression();
-
- visit(node.fieldType);
- _separatorBetweenTypeAndVariable(node.fieldType);
- token(node.fieldName);
-
- builder.unnest();
- builder.endRule();
- });
-
- builder.endBlockArgumentNesting();
- builder.endSpan();
- builder.endRule();
-
- token(node.rightParenthesis);
- }
-
- @override
void visitRethrowExpression(RethrowExpression node) {
token(node.rethrowKeyword);
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 933209e..ee195f6 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: dart_style
# Note: See tool/grind.dart for how to bump the version.
-version: 3.1.4-wip
+version: 3.1.4
description: >-
Opinionated, automatic Dart source code formatter.
Provides an API and a CLI tool.
@@ -9,7 +9,7 @@
sdk: ^3.9.0
dependencies:
- analyzer: '>=8.2.0 <10.0.0'
+ analyzer: ^10.0.0
args: ^2.5.0
collection: ^1.19.0
package_config: ^2.1.0
diff --git a/test/short/whitespace/extension_types.unit b/test/short/whitespace/extension_types.unit
index c597597..6011c95 100644
--- a/test/short/whitespace/extension_types.unit
+++ b/test/short/whitespace/extension_types.unit
@@ -95,11 +95,11 @@
const // d
A // e
< // f
- T // g
- > // h
- . // i
- name // j
- (
+ T // g
+ > // h
+ . // i
+ name // j
+ (
// k
@ // l
required // m