Skip to content

Commit 93fda3e

Browse files
DanTupCommit Queue
authored andcommitted
[analysis_server] Use the correct language version for formatting in the LSP server
Fixes #56941 Change-Id: I675e732ceba98ab88904906c8076e805fcc9ca2d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391663 Commit-Queue: Brian Wilkerson <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Phil Quitslund <[email protected]>
1 parent 03d7cc4 commit 93fda3e

File tree

2 files changed

+82
-4
lines changed

2 files changed

+82
-4
lines changed

pkg/analysis_server/lib/src/lsp/source_edits.dart

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ import 'package:analyzer/dart/ast/token.dart';
1313
import 'package:analyzer/error/listener.dart';
1414
import 'package:analyzer/source/line_info.dart';
1515
import 'package:analyzer/source/source.dart';
16+
import 'package:analyzer/src/dart/analysis/results.dart';
1617
import 'package:analyzer/src/dart/scanner/reader.dart';
1718
import 'package:analyzer/src/dart/scanner/scanner.dart';
1819
import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
1920
import 'package:dart_style/dart_style.dart';
21+
import 'package:pub_semver/pub_semver.dart';
2022

2123
/// Checks whether a string contains only characters that are allowed to differ
2224
/// between unformattedformatted code (such as whitespace, commas, semicolons).
@@ -97,17 +99,20 @@ ErrorOr<List<TextEdit>?> generateEditsForFormatting(
9799
var effectivePageWidth =
98100
result.analysisOptions.formatterOptions.pageWidth ?? defaultPageWidth;
99101

102+
var effectiveLanguageVersion = switch (result.unit.languageVersionToken) {
103+
var token? => Version(token.major, token.minor, 0),
104+
_ => (result as ParsedUnitResultImpl).fileState.packageLanguageVersion,
105+
};
106+
100107
var code = SourceCode(unformattedSource);
101108
SourceCode formattedResult;
102109
try {
103110
// Create a new formatter on every request because it may contain state that
104111
// affects repeated formats.
105112
// https://github.com/dart-lang/dart_style/issues/1337
106-
var languageVersion =
107-
result.unit.declaredElement?.library.languageVersion.effective ??
108-
DartFormatter.latestLanguageVersion;
109113
var formatter = DartFormatter(
110-
pageWidth: effectivePageWidth, languageVersion: languageVersion);
114+
pageWidth: effectivePageWidth,
115+
languageVersion: effectiveLanguageVersion);
111116
formattedResult = formatter.formatSource(code);
112117
} on FormatterException {
113118
// If the document fails to parse, just return no edits to avoid the

pkg/analysis_server/test/lsp/source_edits_test.dart

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,52 @@ void main() {
2121

2222
@reflectiveTest
2323
class SourceEditsTest extends AbstractSingleUnitTest with LspEditHelpersMixin {
24+
Future<void> test_format_version_defaultsToLatest() async {
25+
// Latest version should parse and format records.
26+
const startContent = '''
27+
var a = (1, 2);
28+
''';
29+
const endContent = '''
30+
var a = (1, 2);
31+
''';
32+
const expectedEdits = r'''
33+
Delete 1:5-1:8
34+
''';
35+
36+
await _assertFormatEdits(startContent, endContent, expectedEdits);
37+
}
38+
39+
Future<void> test_format_version_languageVersionToken() async {
40+
// 2.19 will not parse/format records.
41+
const content = '''
42+
// @dart = 2.19
43+
var a = (1, 2);
44+
''';
45+
46+
await _assertNoFormatEdits(content);
47+
}
48+
49+
Future<void> test_format_version_packageConfig() async {
50+
// 2.19 will not parse/format records.
51+
writeTestPackageConfig(languageVersion: '2.19');
52+
const content = '''
53+
var a = (1, 2);
54+
''';
55+
56+
await _assertNoFormatEdits(content);
57+
}
58+
59+
Future<void> test_format_version_versionToken_overridesPackageConfig() async {
60+
// 2.19 will not parse/format records.
61+
writeTestPackageConfig(languageVersion: '3.0');
62+
const content = '''
63+
// @dart = 2.19
64+
var a = (1, 2);
65+
''';
66+
67+
await _assertNoFormatEdits(content);
68+
}
69+
2470
Future<void> test_minimalEdits_comma_delete() async {
2571
const startContent = '''
2672
void f(int a,) {}
@@ -572,6 +618,26 @@ void g() {
572618
);
573619
}
574620

621+
/// Assert that generating edits to format [start] match those described
622+
/// in [expected] and when applied, result in [end].
623+
///
624+
/// Edits will be automatically applied and verified. [expected] is to ensure
625+
/// the edits are minimal and we didn't accidentally produces a single edit
626+
/// replacing the entire file.
627+
Future<void> _assertFormatEdits(
628+
String start,
629+
String end,
630+
String expected, {
631+
String? expectedFormatResult,
632+
Range? range,
633+
}) async {
634+
await parseTestCode(start);
635+
var edits =
636+
generateEditsForFormatting(testParsedResult, range: range).result!;
637+
expect(edits.toText().trim(), expected.trim());
638+
expect(applyTextEdits(start, edits), expectedFormatResult ?? end);
639+
}
640+
575641
/// Assert that computing minimal edits to convert [start] to [end] produces
576642
/// the set of edits described in [expected].
577643
///
@@ -595,6 +661,13 @@ void g() {
595661
expect(edits.toText().trim(), expected);
596662
expect(applyTextEdits(start, edits.result), expectedFormatResult ?? end);
597663
}
664+
665+
/// Assert that formatting [content] produces no edits.
666+
Future<void> _assertNoFormatEdits(String content) async {
667+
await parseTestCode(content);
668+
var edits = generateEditsForFormatting(testParsedResult).result;
669+
expect(edits, isNull);
670+
}
598671
}
599672

600673
/// Helpers for building simple text representations of edits to verify that

0 commit comments

Comments
 (0)