Skip to content

Commit 6753ab4

Browse files
authored
Make "// @Dart=" version comments affect the applied style. (#1600)
The formatter uses an incoming language version to control how the formatted code is parsed. The langauge version is also used to determine whether you get the short or tall style. Prior to this PR, a "// @Dart=" version comment in the formatted code would affect the language version the code is parsed at. But it wouldn't use that comment to determine whether you get the short or tall style. This fixes that. Fix #1599.
1 parent 02957e6 commit 6753ab4

File tree

3 files changed

+120
-1
lines changed

3 files changed

+120
-1
lines changed

lib/src/dart_formatter.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,15 @@ final class DartFormatter {
193193
// Format it.
194194
var lineInfo = parseResult.lineInfo;
195195

196+
// If the code has an `@dart=` comment, use that to determine the style.
197+
var sourceLanguageVersion = languageVersion;
198+
if (parseResult.unit.languageVersionToken case var token?) {
199+
sourceLanguageVersion = Version(token.major, token.minor, 0);
200+
}
201+
196202
// Use language version to determine what formatting style to apply.
197203
SourceCode output;
198-
if (languageVersion > latestShortStyleLanguageVersion) {
204+
if (sourceLanguageVersion > latestShortStyleLanguageVersion) {
199205
// Look for a page width comment before the code.
200206
int? pageWidthFromComment;
201207
for (Token? comment = node.beginToken.precedingComments;

test/cli/language_version_test.dart

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,5 +266,62 @@ main() {
266266

267267
await d.dir('code', [d.file('a.dart', after)]).validate();
268268
});
269+
270+
test('language version comment override opts into short style', () async {
271+
const before = '''
272+
// @dart=3.6
273+
main() { f(argument, // comment
274+
another);}
275+
''';
276+
const after = '''
277+
// @dart=3.6
278+
main() {
279+
f(
280+
argument, // comment
281+
another);
282+
}
283+
''';
284+
285+
await d.dir('code', [d.file('a.dart', before)]).create();
286+
287+
var process = await runFormatterOnDir(['--language-version=3.7']);
288+
await process.shouldExit(0);
289+
290+
await d.dir('code', [d.file('a.dart', after)]).validate();
291+
});
292+
293+
test('language version comment override opts into tall style', () async {
294+
// Note that in real-world code it doesn't make sense for a language
295+
// version comment to be *higher* than the specified default language
296+
// version before you can't use a comment that's higher than the minimum
297+
// version in the package's SDK constraint. (Otherwise, you could end up
298+
// trying to run a library whose language version isn't supported by the
299+
// SDK you are running it in.)
300+
//
301+
// But we support it in the formatter since it's possible to specify a
302+
// default language version using mechanisms other than the pubspec SDK
303+
// constraint.
304+
const before = '''
305+
// @dart=3.7
306+
main() { f(argument, // comment
307+
another);}
308+
''';
309+
const after = '''
310+
// @dart=3.7
311+
main() {
312+
f(
313+
argument, // comment
314+
another,
315+
);
316+
}
317+
''';
318+
319+
await d.dir('code', [d.file('a.dart', before)]).create();
320+
321+
var process = await runFormatterOnDir(['--language-version=3.6']);
322+
await process.shouldExit(0);
323+
324+
await d.dir('code', [d.file('a.dart', after)]).validate();
325+
});
269326
});
270327
}

test/dart_formatter_test.dart

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,62 @@ main() {
8181
});
8282
});
8383

84+
test('language version comment override opts into short style', () async {
85+
// Use a language version with tall style.
86+
var formatter = makeFormatter(languageVersion: Version(3, 7, 0));
87+
88+
// But the code has a comment to opt into the short style.
89+
const before = '''
90+
// @dart=3.6
91+
main() { f(argument, // comment
92+
another);}
93+
''';
94+
const after = '''
95+
// @dart=3.6
96+
main() {
97+
f(
98+
argument, // comment
99+
another);
100+
}
101+
''';
102+
103+
expect(formatter.format(before), after);
104+
});
105+
106+
test('language version comment override opts into tall style', () async {
107+
// Use a language version with short style.
108+
var formatter = makeFormatter(languageVersion: Version(3, 6, 0));
109+
110+
// But the code has a comment to opt into the tall style.
111+
//
112+
// Note that in real-world code it doesn't make sense for a language
113+
// version comment to be *higher* than the specified default language
114+
// version before you can't use a comment that's higher than the minimum
115+
// version in the package's SDK constraint. (Otherwise, you could end up
116+
// trying to run a library whose language version isn't supported by the
117+
// SDK you are running it in.)
118+
//
119+
// But we support it in the formatter since it's possible to specify a
120+
// default language version using mechanisms other than the pubspec SDK
121+
// constraint.
122+
const before = '''
123+
// @dart=3.7
124+
main() { f(argument, // comment
125+
another);}
126+
''';
127+
const after = '''
128+
// @dart=3.7
129+
main() {
130+
f(
131+
argument, // comment
132+
another,
133+
);
134+
}
135+
''';
136+
137+
expect(formatter.format(before), after);
138+
});
139+
84140
test('throws a FormatterException on failed parse', () {
85141
var formatter = makeFormatter();
86142
expect(() => formatter.format('wat?!'), throwsA(isA<FormatterException>()));

0 commit comments

Comments
 (0)