Skip to content

Commit 618883f

Browse files
authored
Use the latest language version if we can't find a package. (#1573)
Use the latest language version if we can't find a package. In the new tall-style behavior where we look for a surrounding package config to infer the language version of each file, we have to decide what to do when that look-up process fails (either because there is no package config, or it's malformed). Initially, I had it error out on that file. That's consistent with the library API where the formatter *requires* a language version before it will do anything. But it's not consistent with the language spec and our other tools. For them, if there is no valid surrounding package config, the file should be treated as the latest language version. This PR does that. It also fixes the catastrophic UX that the current code has which is that when a file can't have its language version inferred... it is silently skipped without telling the user anything. Oops. Now it just formats the file as expected.
1 parent 9c17d3b commit 618883f

File tree

3 files changed

+47
-34
lines changed

3 files changed

+47
-34
lines changed

lib/src/io.dart

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,10 @@ Future<void> formatStdin(
3535
if (languageVersion == null && path != null && cache != null) {
3636
// We have a stdin-name, so look for a surrounding package config.
3737
languageVersion = await cache.findLanguageVersion(File(path), path);
38-
39-
// If the lookup failed, don't try to parse the code.
40-
if (languageVersion == null) return;
4138
}
4239

43-
// If they didn't specify a version or a path, default to the latest.
40+
// If they didn't specify a version or a path, or couldn't find a package
41+
// surrounding the path, then default to the latest version.
4442
languageVersion ??= DartFormatter.latestLanguageVersion;
4543

4644
// Determine the page width.
@@ -164,14 +162,12 @@ Future<bool> _processFile(
164162
var languageVersion = options.languageVersion;
165163
if (languageVersion == null && cache != null) {
166164
languageVersion = await cache.findLanguageVersion(file, displayPath);
167-
168-
// If the lookup failed, don't try to parse the file.
169-
if (languageVersion == null) return false;
170-
} else {
171-
// If they didn't specify a version or a path, default to the latest.
172-
languageVersion ??= DartFormatter.latestLanguageVersion;
173165
}
174166

167+
// If they didn't specify a version and we couldn't find a surrounding
168+
// package, then default to the latest version.
169+
languageVersion ??= DartFormatter.latestLanguageVersion;
170+
175171
// Determine the page width.
176172
var pageWidth = options.pageWidth;
177173
if (pageWidth == null && cache != null) {

lib/src/testing/test_file_system.dart

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,29 @@ final class TestFileSystem implements FileSystem {
1818
}
1919

2020
@override
21-
Future<bool> fileExists(FileSystemPath path) async =>
22-
_files.containsKey(path.testPath);
21+
Future<bool> fileExists(covariant TestFileSystemPath path) async =>
22+
_files.containsKey(path._path);
2323

2424
@override
25-
Future<FileSystemPath> join(FileSystemPath from, String to) async {
25+
Future<FileSystemPath> join(
26+
covariant TestFileSystemPath from, String to) async {
2627
// If it's an absolute path, discard [from].
2728
if (to.startsWith('|')) return TestFileSystemPath(to);
28-
return TestFileSystemPath('${from.testPath}|$to');
29+
return TestFileSystemPath('${from._path}|$to');
2930
}
3031

3132
@override
32-
Future<FileSystemPath?> parentDirectory(FileSystemPath path) async {
33-
var parts = path.testPath.split('|');
33+
Future<FileSystemPath?> parentDirectory(
34+
covariant TestFileSystemPath path) async {
35+
var parts = path._path.split('|');
3436
if (parts.length == 1) return null;
3537

3638
return TestFileSystemPath(parts.sublist(0, parts.length - 1).join('|'));
3739
}
3840

3941
@override
40-
Future<String> readFile(FileSystemPath path) async {
41-
if (_files[path.testPath] case var contents?) return contents;
42+
Future<String> readFile(covariant TestFileSystemPath path) async {
43+
if (_files[path._path] case var contents?) return contents;
4244
throw Exception('No file at "$path".');
4345
}
4446
}
@@ -51,7 +53,3 @@ final class TestFileSystemPath implements FileSystemPath {
5153
@override
5254
String toString() => _path;
5355
}
54-
55-
extension on FileSystemPath {
56-
String get testPath => (this as TestFileSystemPath)._path;
57-
}

test/cli/language_version_test.dart

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ extension type Meters(int value) {
2626
}
2727
''';
2828

29-
test('defaults to latest language version if omitted', () async {
29+
test('uses latest language version if no surrounding package', () async {
3030
await d.dir('code', [d.file('a.dart', extensionTypeBefore)]).create();
3131

32-
var process = await runFormatterOnDir();
32+
// Enable the experiment to be sure that we're opting in to the new
33+
// package config search.
34+
var process = await runFormatterOnDir(['--enable-experiment=tall-style']);
3335
await process.shouldExit(0);
3436

3537
await d.dir('code', [d.file('a.dart', extensionTypeAfter)]).validate();
@@ -160,24 +162,26 @@ main() {
160162
]).validate();
161163
});
162164

163-
test('malformed', () async {
165+
test('use the latest version if the package config is malformed', () async {
164166
await d.dir('foo', [
165167
d.dir('.dart_tool', [
166168
d.file('package_config.json', 'this no good json is bad json'),
167169
]),
168-
d.file('main.dart', 'main() {}'),
170+
d.file('main.dart', 'main() {var (a,b)=(1,2);}'),
169171
]).create();
170172

171-
var path = p.join(d.sandbox, 'foo', 'main.dart');
172173
// TODO(rnystrom): Remove experiment flag when it ships.
173-
var process =
174-
await runFormatter([path, '--enable-experiment=tall-style']);
174+
var process = await runFormatterOnDir(['--enable-experiment=tall-style']);
175+
await process.shouldExit(0);
175176

176-
expect(
177-
await process.stderr.next,
178-
allOf(startsWith('Could not read package configuration for'),
179-
contains(p.join('foo', 'main.dart'))));
180-
await process.shouldExit(65);
177+
// Formats the file.
178+
await d.dir('foo', [
179+
d.file('main.dart', '''
180+
main() {
181+
var (a, b) = (1, 2);
182+
}
183+
''')
184+
]).validate();
181185
});
182186
});
183187

@@ -235,5 +239,20 @@ main() {
235239
expect(await process.stdout.next, '}');
236240
await process.shouldExit(0);
237241
});
242+
243+
test('use latest language version if no surrounding package', () async {
244+
await d.dir('foo', []).create();
245+
246+
var process = await runFormatter(
247+
['--enable-experiment=tall-style', '--stdin-name=foo/main.dart']);
248+
// Use some relatively recent syntax.
249+
process.stdin.writeln('main() {var (a,b)=(1,2);}');
250+
await process.stdin.close();
251+
252+
expect(await process.stdout.next, 'main() {');
253+
expect(await process.stdout.next, ' var (a, b) = (1, 2);');
254+
expect(await process.stdout.next, '}');
255+
await process.shouldExit(0);
256+
});
238257
});
239258
}

0 commit comments

Comments
 (0)