Latest analyzer, prepare release (#1783)

* Latest analyzer, prepare release
* bump sdk
* formatting the formatter
diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index 0ec1167..3138f1c 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -20,7 +20,7 @@
     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 @@
       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 9fb5922..8bad983 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-## 3.1.3-wip
+## 3.1.3
 
 * 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
@@ -12,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/benchmark/directory.dart b/benchmark/directory.dart
index 910aec2..42bf39a 100644
--- a/benchmark/directory.dart
+++ b/benchmark/directory.dart
@@ -63,10 +63,9 @@
 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 7d48ea5..53bc304 100644
--- a/benchmark/run.dart
+++ b/benchmark/run.dart
@@ -137,10 +137,9 @@
   );
 
   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 e610b3e..691874e 100644
--- a/lib/src/back_end/code_writer.dart
+++ b/lib/src/back_end/code_writer.dart
@@ -370,11 +370,10 @@
       // 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 217a130..9e92629 100644
--- a/lib/src/cli/format_command.dart
+++ b/lib/src/cli/format_command.dart
@@ -183,20 +183,18 @@
       return 0;
     }
 
-    var show =
-        const {
-          'all': Show.all,
-          'changed': Show.changed,
-          'none': Show.none,
-        }[argResults['show']]!;
+    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 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/cli/formatter_options.dart b/lib/src/cli/formatter_options.dart
index 487e133..4a5ffe4 100644
--- a/lib/src/cli/formatter_options.dart
+++ b/lib/src/cli/formatter_options.dart
@@ -13,7 +13,7 @@
 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 11b305d..dc28b37 100644
--- a/lib/src/dart_formatter.dart
+++ b/lib/src/dart_formatter.dart
@@ -140,10 +140,9 @@
         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 @@
     }
 
     // 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);
     }
@@ -200,7 +198,7 @@
           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/lib/src/front_end/ast_node_visitor.dart b/lib/src/front_end/ast_node_visitor.dart
index 816f70e..4193f13 100644
--- a/lib/src/front_end/ast_node_visitor.dart
+++ b/lib/src/front_end/ast_node_visitor.dart
@@ -1794,10 +1794,9 @@
     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 @@
     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 0a01906..9578e3d 100644
--- a/lib/src/front_end/delimited_list_builder.dart
+++ b/lib/src/front_end/delimited_list_builder.dart
@@ -269,7 +269,10 @@
       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 @@
       }
     }
 
-    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 8eb92fa..5202d59 100644
--- a/lib/src/front_end/piece_factory.dart
+++ b/lib/src/front_end/piece_factory.dart
@@ -856,10 +856,9 @@
         pieces.token(question);
       }
 
-      var returnTypeModifiers =
-          parameter != null
-              ? [parameter.requiredKeyword, parameter.covariantKeyword]
-              : const <Token?>[];
+      var returnTypeModifiers = parameter != null
+          ? [parameter.requiredKeyword, parameter.covariantKeyword]
+          : const <Token?>[];
 
       // 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 75300ef..b863311 100644
--- a/lib/src/front_end/piece_writer.dart
+++ b/lib/src/front_end/piece_writer.dart
@@ -208,10 +208,9 @@
     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 2232776..5fe9067 100644
--- a/lib/src/short/line_splitting/solve_state.dart
+++ b/lib/src/short/line_splitting/solve_state.dart
@@ -407,8 +407,9 @@
       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 c01b515..660347d 100644
--- a/lib/src/short/source_visitor.dart
+++ b/lib/src/short/source_visitor.dart
@@ -1251,12 +1251,12 @@
       return;
     }
 
-    var requiredParams =
-        node.parameters
-            .where((param) => param is! DefaultFormalParameter)
-            .toList();
-    var optionalParams =
-        node.parameters.whereType<DefaultFormalParameter>().toList();
+    var requiredParams = node.parameters
+        .where((param) => param is! DefaultFormalParameter)
+        .toList();
+    var optionalParams = node.parameters
+        .whereType<DefaultFormalParameter>()
+        .toList();
 
     if (nestExpression) builder.nestExpression();
     token(node.leftParenthesis);
diff --git a/lib/src/testing/benchmark.dart b/lib/src/testing/benchmark.dart
index ff5c1ca..49cb8bf 100644
--- a/lib/src/testing/benchmark.dart
+++ b/lib/src/testing/benchmark.dart
@@ -39,8 +39,9 @@
 
     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 7d0acce..9180897 100644
--- a/lib/src/testing/test_file.dart
+++ b/lib/src/testing/test_file.dart
@@ -27,10 +27,9 @@
 
 /// Get the absolute local file path to the dart_style package's root directory.
 Future<String> 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 @@
   /// 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/pubspec.yaml b/pubspec.yaml
index 31ef62e..180c73d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,15 +1,15 @@
 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.
 repository: https://github.com/dart-lang/dart_style
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.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
diff --git a/test/dart_formatter_test.dart b/test/dart_formatter_test.dart
index 192f092..5f5462a 100644
--- a/test/dart_formatter_test.dart
+++ b/test/dart_formatter_test.dart
@@ -23,10 +23,9 @@
     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 6fa20f8..099667d 100644
--- a/test/utils.dart
+++ b/test/utils.dart
@@ -112,10 +112,9 @@
     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 @@
         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 6c989e4..e356da7 100644
--- a/tool/update_tests.dart
+++ b/tool/update_tests.dart
@@ -185,10 +185,9 @@
   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,