From 26dd3a347c120515487aed8818eb6a07fcda37ce Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 11 Nov 2025 12:17:00 -0800 Subject: [PATCH 1/3] Latest analyzer, prepare release --- CHANGELOG.md | 3 ++- lib/src/cli/formatter_options.dart | 2 +- lib/src/dart_formatter.dart | 2 +- pubspec.yaml | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fb5922c..e67afe33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ -## 3.1.3-wip +## 3.1.3 +* Support `analyzer: '>=8.2.0 <10.0.0'`. * No longer format imports with configurations and a prefix in the wrong order. The parser used to accept this without error even though it violated the language spec. The parser is being fixed, so the formatter will no longer diff --git a/lib/src/cli/formatter_options.dart b/lib/src/cli/formatter_options.dart index 487e1336..4a5ffe46 100644 --- a/lib/src/cli/formatter_options.dart +++ b/lib/src/cli/formatter_options.dart @@ -13,7 +13,7 @@ import 'show.dart'; import 'summary.dart'; // Note: The following line of code is modified by tool/grind.dart. -const dartStyleVersion = '3.1.3-wip'; +const dartStyleVersion = '3.1.3'; /// Global options parsed from the command line that affect how the formatter /// produces and uses its outputs. diff --git a/lib/src/dart_formatter.dart b/lib/src/dart_formatter.dart index 11b305d0..d12e5211 100644 --- a/lib/src/dart_formatter.dart +++ b/lib/src/dart_formatter.dart @@ -200,7 +200,7 @@ final class DartFormatter { source: stringSource, offset: token.offset - inputOffset, length: math.max(token.length, 1), - diagnosticCode: ParserErrorCode.UNEXPECTED_TOKEN, + diagnosticCode: ParserErrorCode.unexpectedToken, arguments: [token.lexeme], ); throw FormatterException([error]); diff --git a/pubspec.yaml b/pubspec.yaml index 31ef62e2..04f2af71 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.3-wip +version: 3.1.3 description: >- Opinionated, automatic Dart source code formatter. Provides an API and a CLI tool. @@ -9,7 +9,7 @@ environment: sdk: ^3.7.0 dependencies: - analyzer: ^8.1.0 + analyzer: '>=8.2.0 <10.0.0' args: ^2.0.0 collection: ^1.19.0 package_config: ^2.1.0 From 3544abfcf1cf1b0ea30c048fffb62f33266ed4a0 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 11 Nov 2025 12:21:11 -0800 Subject: [PATCH 2/3] bump sdk --- .github/workflows/test-package.yml | 4 ++-- CHANGELOG.md | 4 +++- pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml index 0ec1167e..3138f1cf 100644 --- a/.github/workflows/test-package.yml +++ b/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - sdk: [3.7.0, dev] + sdk: [3.9.0, dev] steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c @@ -50,7 +50,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [3.7.0, dev] + sdk: [3.9.0, dev] steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c diff --git a/CHANGELOG.md b/CHANGELOG.md index e67afe33..8bad983b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,5 @@ ## 3.1.3 -* Support `analyzer: '>=8.2.0 <10.0.0'`. * No longer format imports with configurations and a prefix in the wrong order. The parser used to accept this without error even though it violated the language spec. The parser is being fixed, so the formatter will no longer @@ -13,6 +12,9 @@ * Don't force a space between `?` and `.` if a null-aware element contains a dot shorthand. +* Require `analyzer: '>=8.2.0 <10.0.0'`. +* Require `sdk: ^3.9.0` + ### Bug fixes * Respect `@dart=` version comments when determining which >3.7 style to apply. diff --git a/pubspec.yaml b/pubspec.yaml index 04f2af71..180c73dc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,7 +6,7 @@ description: >- Provides an API and a CLI tool. repository: https://github.com/dart-lang/dart_style environment: - sdk: ^3.7.0 + sdk: ^3.9.0 dependencies: analyzer: '>=8.2.0 <10.0.0' From ca47dde566541b336092ce8567c3f6f388b5ccbd Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 11 Nov 2025 12:23:11 -0800 Subject: [PATCH 3/3] formatting the formatter --- benchmark/directory.dart | 7 +++-- benchmark/run.dart | 7 +++-- lib/src/back_end/code_writer.dart | 9 +++---- lib/src/cli/format_command.dart | 26 +++++++++---------- lib/src/dart_formatter.dart | 14 +++++----- lib/src/front_end/ast_node_visitor.dart | 14 +++++----- lib/src/front_end/delimited_list_builder.dart | 11 ++++---- lib/src/front_end/piece_factory.dart | 7 +++-- lib/src/front_end/piece_writer.dart | 7 +++-- lib/src/short/line_splitting/solve_state.dart | 5 ++-- lib/src/short/source_visitor.dart | 12 ++++----- lib/src/testing/benchmark.dart | 5 ++-- lib/src/testing/test_file.dart | 14 +++++----- test/dart_formatter_test.dart | 7 +++-- test/utils.dart | 12 ++++----- tool/update_tests.dart | 7 +++-- 16 files changed, 76 insertions(+), 88 deletions(-) diff --git a/benchmark/directory.dart b/benchmark/directory.dart index 910aec25..42bf39aa 100644 --- a/benchmark/directory.dart +++ b/benchmark/directory.dart @@ -63,10 +63,9 @@ void main(List arguments) async { void _runFormatter(String source) { try { var formatter = DartFormatter( - languageVersion: - _isShort - ? DartFormatter.latestShortStyleLanguageVersion - : DartFormatter.latestLanguageVersion, + languageVersion: _isShort + ? DartFormatter.latestShortStyleLanguageVersion + : DartFormatter.latestLanguageVersion, ); var result = formatter.format(source); diff --git a/benchmark/run.dart b/benchmark/run.dart index 7d48ea53..53bc3042 100644 --- a/benchmark/run.dart +++ b/benchmark/run.dart @@ -137,10 +137,9 @@ List _runTrials(String verb, Benchmark benchmark, int trials) { ); var formatter = DartFormatter( - languageVersion: - _isShort - ? DartFormatter.latestShortStyleLanguageVersion - : DartFormatter.latestLanguageVersion, + languageVersion: _isShort + ? DartFormatter.latestShortStyleLanguageVersion + : DartFormatter.latestLanguageVersion, pageWidth: benchmark.pageWidth, lineEnding: '\n', ); diff --git a/lib/src/back_end/code_writer.dart b/lib/src/back_end/code_writer.dart index e610b3e4..691874ec 100644 --- a/lib/src/back_end/code_writer.dart +++ b/lib/src/back_end/code_writer.dart @@ -370,11 +370,10 @@ final class CodeWriter { // indication into account which may vary based on the surrounding pieces // when we get here. Profile.begin('CodeWriter try to bind by page width'); - isUnsolved = - !_solution.tryBindByPageWidth( - piece, - _pageWidth - _indentStack.first.spaces, - ); + isUnsolved = !_solution.tryBindByPageWidth( + piece, + _pageWidth - _indentStack.first.spaces, + ); Profile.end('CodeWriter try to bind by page width'); } diff --git a/lib/src/cli/format_command.dart b/lib/src/cli/format_command.dart index 217a1308..9e926295 100644 --- a/lib/src/cli/format_command.dart +++ b/lib/src/cli/format_command.dart @@ -183,20 +183,18 @@ final class FormatCommand extends Command { return 0; } - var show = - const { - 'all': Show.all, - 'changed': Show.changed, - 'none': Show.none, - }[argResults['show']]!; - - var output = - const { - 'write': Output.write, - 'show': Output.show, - 'none': Output.none, - 'json': Output.json, - }[argResults['output']]!; + var show = const { + 'all': Show.all, + 'changed': Show.changed, + 'none': Show.none, + }[argResults['show']]!; + + var output = const { + 'write': Output.write, + 'show': Output.show, + 'none': Output.none, + 'json': Output.json, + }[argResults['output']]!; var summary = Summary.none; switch (argResults['summary'] as String) { diff --git a/lib/src/dart_formatter.dart b/lib/src/dart_formatter.dart index d12e5211..dc28b372 100644 --- a/lib/src/dart_formatter.dart +++ b/lib/src/dart_formatter.dart @@ -140,10 +140,9 @@ final class DartFormatter { text, uri: source.uri, isCompilationUnit: false, - selectionStart: - source.selectionStart != null - ? source.selectionStart! + inputOffset - : null, + selectionStart: source.selectionStart != null + ? source.selectionStart! + inputOffset + : null, selectionLength: source.selectionLength, ); } @@ -176,10 +175,9 @@ final class DartFormatter { } // Throw if there are syntactic errors. - var syntacticErrors = - parseResult.errors.where((error) { - return error.diagnosticCode.type == DiagnosticType.SYNTACTIC_ERROR; - }).toList(); + var syntacticErrors = parseResult.errors.where((error) { + return error.diagnosticCode.type == DiagnosticType.SYNTACTIC_ERROR; + }).toList(); if (syntacticErrors.isNotEmpty) { throw FormatterException(syntacticErrors); } diff --git a/lib/src/front_end/ast_node_visitor.dart b/lib/src/front_end/ast_node_visitor.dart index 816f70ea..4193f134 100644 --- a/lib/src/front_end/ast_node_visitor.dart +++ b/lib/src/front_end/ast_node_visitor.dart @@ -1794,10 +1794,9 @@ final class AstNodeVisitor extends ThrowingAstVisitor with PieceFactory { var isSinglePositional = positionalFields.length == 1 && namedFields == null; - var listStyle = - isSinglePositional - ? const ListStyle(commas: Commas.alwaysTrailing) - : const ListStyle(commas: Commas.trailing); + var listStyle = isSinglePositional + ? const ListStyle(commas: Commas.alwaysTrailing) + : const ListStyle(commas: Commas.trailing); var builder = DelimitedListBuilder(this, listStyle); // If all parameters are optional, put the `{` right after `(`. @@ -1963,10 +1962,9 @@ final class AstNodeVisitor extends ThrowingAstVisitor with PieceFactory { for (var element in node.elements) { pieces.visit( element, - context: - node.isMultiline - ? NodeContext.multilineStringInterpolation - : NodeContext.none, + context: node.isMultiline + ? NodeContext.multilineStringInterpolation + : NodeContext.none, ); } } diff --git a/lib/src/front_end/delimited_list_builder.dart b/lib/src/front_end/delimited_list_builder.dart index 0a019062..9578e3d8 100644 --- a/lib/src/front_end/delimited_list_builder.dart +++ b/lib/src/front_end/delimited_list_builder.dart @@ -269,7 +269,10 @@ final class DelimitedListBuilder { hanging: hangingComments, separate: separateComments, leading: leadingComments, - ) = _splitCommaComments(comments, hasElementAfter: hasElementAfter); + ) = _splitCommaComments( + comments, + hasElementAfter: hasElementAfter, + ); // Add any hanging inline block comments to the previous element before the // subsequent ",". @@ -401,10 +404,8 @@ final class DelimitedListBuilder { } } - var ( - hangingComments, - separateCommentsBeforeComma, - ) = remainingCommentsBeforeComma.splitAt(hangingCommentCount); + var (hangingComments, separateCommentsBeforeComma) = + remainingCommentsBeforeComma.splitAt(hangingCommentCount); // Inline block comments on the same line as the next element lead at the // beginning of that line, as in: diff --git a/lib/src/front_end/piece_factory.dart b/lib/src/front_end/piece_factory.dart index 8eb92fa1..5202d597 100644 --- a/lib/src/front_end/piece_factory.dart +++ b/lib/src/front_end/piece_factory.dart @@ -856,10 +856,9 @@ mixin PieceFactory { pieces.token(question); } - var returnTypeModifiers = - parameter != null - ? [parameter.requiredKeyword, parameter.covariantKeyword] - : const []; + var returnTypeModifiers = parameter != null + ? [parameter.requiredKeyword, parameter.covariantKeyword] + : const []; // If the type is a function-typed parameter with a default value, then // grab the default value from the parent node and attach it to the diff --git a/lib/src/front_end/piece_writer.dart b/lib/src/front_end/piece_writer.dart index 75300ef8..b863311c 100644 --- a/lib/src/front_end/piece_writer.dart +++ b/lib/src/front_end/piece_writer.dart @@ -208,10 +208,9 @@ final class PieceWriter { var builtPieces = _pieces.removeLast(); assert(builtPieces.isNotEmpty); - var builtPiece = - builtPieces.length == 1 - ? builtPieces.first - : AdjacentPiece(builtPieces); + var builtPiece = builtPieces.length == 1 + ? builtPieces.first + : AdjacentPiece(builtPieces); if (leadingPieces.isEmpty) { // No metadata, so return the content piece directly. diff --git a/lib/src/short/line_splitting/solve_state.dart b/lib/src/short/line_splitting/solve_state.dart index 22327765..5fe9067d 100644 --- a/lib/src/short/line_splitting/solve_state.dart +++ b/lib/src/short/line_splitting/solve_state.dart @@ -407,8 +407,9 @@ final class SolveState { if (chunk is BlockChunk) { if (_splits.shouldSplitAt(i)) { // Include the cost of the nested block. - cost += - _splitter.writer.formatBlock(chunk, _splits.getColumn(i)).cost; + cost += _splitter.writer + .formatBlock(chunk, _splits.getColumn(i)) + .cost; } else { // Include the nested block inline, if any. length += chunk.unsplitBlockLength; diff --git a/lib/src/short/source_visitor.dart b/lib/src/short/source_visitor.dart index c01b5159..660347dc 100644 --- a/lib/src/short/source_visitor.dart +++ b/lib/src/short/source_visitor.dart @@ -1251,12 +1251,12 @@ final class SourceVisitor extends ThrowingAstVisitor { return; } - var requiredParams = - node.parameters - .where((param) => param is! DefaultFormalParameter) - .toList(); - var optionalParams = - node.parameters.whereType().toList(); + var requiredParams = node.parameters + .where((param) => param is! DefaultFormalParameter) + .toList(); + var optionalParams = node.parameters + .whereType() + .toList(); if (nestExpression) builder.nestExpression(); token(node.leftParenthesis); diff --git a/lib/src/testing/benchmark.dart b/lib/src/testing/benchmark.dart index ff5c1ca7..49cb8bf8 100644 --- a/lib/src/testing/benchmark.dart +++ b/lib/src/testing/benchmark.dart @@ -39,8 +39,9 @@ final class Benchmark { var input = inputLines.join('\n'); - var shortOutput = - File(p.setExtension(path, '.expect_short')).readAsStringSync(); + var shortOutput = File( + p.setExtension(path, '.expect_short'), + ).readAsStringSync(); var tallOutput = File(p.setExtension(path, '.expect')).readAsStringSync(); return Benchmark( diff --git a/lib/src/testing/test_file.dart b/lib/src/testing/test_file.dart index 7d0accef..9180897b 100644 --- a/lib/src/testing/test_file.dart +++ b/lib/src/testing/test_file.dart @@ -27,10 +27,9 @@ final _outputPattern = RegExp(r'<<<( (\d+)\.(\d+))?(.*)'); /// Get the absolute local file path to the dart_style package's root directory. Future findPackageDirectory() async { - var libraryPath = - (await Isolate.resolvePackageUri( - Uri.parse('package:dart_style/src/testing/test_file.dart'), - ))?.toFilePath(); + var libraryPath = (await Isolate.resolvePackageUri( + Uri.parse('package:dart_style/src/testing/test_file.dart'), + ))?.toFilePath(); // Fallback, if we can't resolve the package URI because we're running in an // AOT snapshot, just assume we're running from the root directory of the @@ -299,10 +298,9 @@ final class TestFile { /// If [version] is given, then it specifies the language version to run the /// test at. Otherwise, the test's default version is used. DartFormatter formatterForTest(FormatTest test, [Version? version]) { - var defaultLanguageVersion = - isTall - ? DartFormatter.latestLanguageVersion - : DartFormatter.latestShortStyleLanguageVersion; + var defaultLanguageVersion = isTall + ? DartFormatter.latestLanguageVersion + : DartFormatter.latestShortStyleLanguageVersion; return DartFormatter( languageVersion: version ?? defaultLanguageVersion, diff --git a/test/dart_formatter_test.dart b/test/dart_formatter_test.dart index 192f092a..5f5462a9 100644 --- a/test/dart_formatter_test.dart +++ b/test/dart_formatter_test.dart @@ -23,10 +23,9 @@ void _runTests({required bool isTall}) { int? indent, String? lineEnding, }) { - languageVersion ??= - isTall - ? DartFormatter.latestLanguageVersion - : DartFormatter.latestShortStyleLanguageVersion; + languageVersion ??= isTall + ? DartFormatter.latestLanguageVersion + : DartFormatter.latestShortStyleLanguageVersion; return DartFormatter( languageVersion: languageVersion, diff --git a/test/utils.dart b/test/utils.dart index 6fa20f85..099667de 100644 --- a/test/utils.dart +++ b/test/utils.dart @@ -112,10 +112,9 @@ Future testBenchmarks({required bool useTallStyle}) async { for (var benchmark in benchmarks) { test(benchmark.name, () { var formatter = DartFormatter( - languageVersion: - useTallStyle - ? DartFormatter.latestLanguageVersion - : DartFormatter.latestShortStyleLanguageVersion, + languageVersion: useTallStyle + ? DartFormatter.latestLanguageVersion + : DartFormatter.latestShortStyleLanguageVersion, pageWidth: benchmark.pageWidth, ); @@ -127,8 +126,9 @@ Future testBenchmarks({required bool useTallStyle}) async { var actualText = actual.text; if (!benchmark.isCompilationUnit) actualText += '\n'; - var expected = - useTallStyle ? benchmark.tallOutput : benchmark.shortOutput; + var expected = useTallStyle + ? benchmark.tallOutput + : benchmark.shortOutput; // Fail with an explicit message because it's easier to read than // the matcher output. diff --git a/tool/update_tests.dart b/tool/update_tests.dart index 6c989e49..e356da71 100644 --- a/tool/update_tests.dart +++ b/tool/update_tests.dart @@ -185,10 +185,9 @@ bool _writeOutput( buffer.writeln('<<< $outputDescription'.trim()); _writeComments(buffer, output.comments); - var defaultVersion = - testFile.isTall - ? DartFormatter.latestLanguageVersion - : DartFormatter.latestShortStyleLanguageVersion; + var defaultVersion = testFile.isTall + ? DartFormatter.latestLanguageVersion + : DartFormatter.latestShortStyleLanguageVersion; var formatter = testFile.formatterForTest( formatTest,