chore: adopt Dart 3.9 toolchain — honest floor + tall-style reformat (T-353)

Raise the declared minimums in pubspec.yaml to what our deps already
require: Flutter >=3.35.0 / Dart >=3.9.0 (was 3.19.0 / 3.5.0). alchemist
0.12 needs Flutter 3.32; Dart 3.9 first ships in Flutter 3.35, so 3.35 is
the binding floor. Pin the exact build toolchain in .fvmrc (Flutter
3.44.1).

Moving to the Dart 3.9 language level switches `dart format` to the new
"tall" style and enables two new lints. This commit is the resulting
mechanical churn, isolated from any behaviour change:
  - whole-tree `dart format` reformat (tall style)
  - `dart fix` for unnecessary_underscores + use_null_aware_elements

No runtime behaviour change; `make test` green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-11 12:11:53 +02:00
co-authored by Claude Opus 4.8
parent bcea5f15b7
commit 6d0ebab721
444 changed files with 7587 additions and 12849 deletions
+1 -4
View File
@@ -69,10 +69,7 @@ void main() {
test('** crosses directory boundaries', () {
final s = IgnoreSet.parse(const ['docs/**/*.draft.md\n']);
expect(
s.isIgnored('docs/deep/nested/a.draft.md', isDirectory: false),
isTrue,
);
expect(s.isIgnored('docs/deep/nested/a.draft.md', isDirectory: false), isTrue);
expect(s.isIgnored('docs/a.draft.md', isDirectory: false), isTrue);
expect(s.isIgnored('other/a.draft.md', isDirectory: false), isFalse);
});
+3 -12
View File
@@ -104,10 +104,7 @@ void main() {
final link = Link('${root.path}/leak')..createSync(secret.path);
expect(link.existsSync(), isTrue);
expect(
() => resolveUnderRootFollowingSymlinks(root, 'leak'),
throwsA(isA<PathOutsideRoot>()),
);
expect(() => resolveUnderRootFollowingSymlinks(root, 'leak'), throwsA(isA<PathOutsideRoot>()));
});
test('tolerates symlinks in the workspace root path itself', () {
@@ -130,10 +127,7 @@ void main() {
Link('${root.path}/b').createSync(secret.path);
Link('${root.path}/a').createSync('${root.path}/b');
expect(
() => resolveUnderRootFollowingSymlinks(root, 'a'),
throwsA(isA<PathOutsideRoot>()),
);
expect(() => resolveUnderRootFollowingSymlinks(root, 'a'), throwsA(isA<PathOutsideRoot>()));
});
});
@@ -171,10 +165,7 @@ void main() {
addTearDown(() => outside.existsSync() ? outside.deleteSync(recursive: true) : null);
File('${outside.path}/secret.txt').writeAsStringSync('payload');
Link('${extra.path}/leak').createSync('${outside.path}/secret.txt');
expect(
() => resolveUnderRootsFollowingSymlinks(root, [extra], '${extra.absolute.path}/leak'),
throwsA(isA<PathOutsideRoot>()),
);
expect(() => resolveUnderRootsFollowingSymlinks(root, [extra], '${extra.absolute.path}/leak'), throwsA(isA<PathOutsideRoot>()));
});
});
}
+1 -7
View File
@@ -28,13 +28,7 @@ void main() {
test('walks recursively, returns files sorted by path', () async {
final r = await walkFiles(root: root, ignore: IgnoreSet([]));
expect(r.truncated, isFalse);
expect(r.files.map((e) => e.path).toList(), [
'README.md',
'build/output.bin',
'lib/main.dart',
'lib/src/util.dart',
'pubspec.yaml',
]);
expect(r.files.map((e) => e.path).toList(), ['README.md', 'build/output.bin', 'lib/main.dart', 'lib/src/util.dart', 'pubspec.yaml']);
});
test('prunes ignored directories (build/ via builtin ignore)', () async {
+8 -14
View File
@@ -15,12 +15,12 @@ void main() {
test('fromEvent maps every FileSystemEvent.type to a wire kind', () {
final dir = Directory.systemTemp;
FileSystemEvent ev(int type) => switch (type) {
FileSystemEvent.create => FileSystemCreateEvent('${dir.path}/f', false),
FileSystemEvent.delete => FileSystemDeleteEvent('${dir.path}/f', false),
FileSystemEvent.modify => FileSystemModifyEvent('${dir.path}/f', false, false),
FileSystemEvent.move => FileSystemMoveEvent('${dir.path}/f', false, '${dir.path}/g'),
_ => FileSystemModifyEvent('${dir.path}/f', false, false),
};
FileSystemEvent.create => FileSystemCreateEvent('${dir.path}/f', false),
FileSystemEvent.delete => FileSystemDeleteEvent('${dir.path}/f', false),
FileSystemEvent.modify => FileSystemModifyEvent('${dir.path}/f', false, false),
FileSystemEvent.move => FileSystemMoveEvent('${dir.path}/f', false, '${dir.path}/g'),
_ => FileSystemModifyEvent('${dir.path}/f', false, false),
};
expect(FileChangeKind.fromEvent(ev(FileSystemEvent.create)), FileChangeKind.created);
expect(FileChangeKind.fromEvent(ev(FileSystemEvent.delete)), FileChangeKind.deleted);
expect(FileChangeKind.fromEvent(ev(FileSystemEvent.modify)), FileChangeKind.modified);
@@ -65,15 +65,9 @@ void main() {
// amount. firstWhere completes on the first matching event;
// the timeout fails the test with a clear message if inotify
// never delivers (instead of asserting on an empty list).
final saw = watcher.stream.firstWhere(
(c) => c.path == 'new.txt',
orElse: () => throw StateError('stream closed before new.txt arrived'),
);
final saw = watcher.stream.firstWhere((c) => c.path == 'new.txt', orElse: () => throw StateError('stream closed before new.txt arrived'));
await File('${sandbox.path}/new.txt').writeAsString('hi');
final change = await saw.timeout(
ioTimeout,
onTimeout: () => fail('no `new.txt` event within ${ioTimeout.inSeconds}s'),
);
final change = await saw.timeout(ioTimeout, onTimeout: () => fail('no `new.txt` event within ${ioTimeout.inSeconds}s'));
expect(change.path, 'new.txt');
});