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
@@ -19,13 +19,9 @@ import '../../helpers/kernel_fixture.dart';
IpcResponse _ok(Map<String, Object?> data) => IpcResponse.ok(id: '', data: data);
IpcResponse _err(String msg) => IpcResponse.err(
id: '',
error: IpcError(
code: IpcExitCode.toolError,
kind: IpcErrorKind.toolError,
message: msg,
),
);
id: '',
error: IpcError(code: IpcExitCode.toolError, kind: IpcErrorKind.toolError, message: msg),
);
Map<String, Object?> _fileEntry({
required String name,
@@ -34,15 +30,7 @@ Map<String, Object?> _fileEntry({
bool isSymlink = false,
int? sizeBytes,
int? modifiedMs,
}) =>
{
'name': name,
'path': path,
'isDirectory': isDirectory,
'isSymlink': isSymlink,
'sizeBytes': sizeBytes,
'modifiedMs': modifiedMs,
};
}) => {'name': name, 'path': path, 'isDirectory': isDirectory, 'isSymlink': isSymlink, 'sizeBytes': sizeBytes, 'modifiedMs': modifiedMs};
// ---------------------------------------------------------------------------
// Tests
@@ -75,9 +63,7 @@ void main() {
f.ipc.stub(
'files.ls',
(_) async => _ok({
'entries': [
_fileEntry(name: 'main.dart', path: 'lib/main.dart'),
],
'entries': [_fileEntry(name: 'main.dart', path: 'lib/main.dart')],
}),
);
@@ -148,17 +134,12 @@ void main() {
final path = args['path'] as String? ?? '';
if (path == '') {
return _ok({
'entries': [
_fileEntry(name: 'lib', path: 'lib', isDirectory: true),
_fileEntry(name: 'main.dart', path: 'main.dart'),
],
'entries': [_fileEntry(name: 'lib', path: 'lib', isDirectory: true), _fileEntry(name: 'main.dart', path: 'main.dart')],
});
}
if (path == 'lib') {
return _ok({
'entries': [
_fileEntry(name: 'app.dart', path: 'lib/app.dart'),
],
'entries': [_fileEntry(name: 'app.dart', path: 'lib/app.dart')],
});
}
return _ok({'entries': <Object?>[]});
@@ -243,17 +224,12 @@ void main() {
final path = args['path'] as String? ?? '';
if (path == '') {
return _ok({
'entries': [
_fileEntry(name: 'lib', path: 'lib', isDirectory: true),
_fileEntry(name: 'README.md', path: 'README.md'),
],
'entries': [_fileEntry(name: 'lib', path: 'lib', isDirectory: true), _fileEntry(name: 'README.md', path: 'README.md')],
});
}
if (path == 'lib') {
return _ok({
'entries': [
_fileEntry(name: 'main.dart', path: 'lib/main.dart'),
],
'entries': [_fileEntry(name: 'main.dart', path: 'lib/main.dart')],
});
}
return _ok({'entries': <Object?>[]});
@@ -309,12 +285,7 @@ void main() {
final countAfterLoad = lsCallCount;
// Emit files.changed for a file at root level — parent is ''.
f.services.events.emit(DaemonEvent(
subsystem: 'files',
kind: 'files.changed',
data: {'path': 'README.md'},
ts: DateTime.now().toUtc(),
));
f.services.events.emit(DaemonEvent(subsystem: 'files', kind: 'files.changed', data: {'path': 'README.md'}, ts: DateTime.now().toUtc()));
// Give the async refresh a tick.
await Future<void>.delayed(Duration.zero);
@@ -333,12 +304,7 @@ void main() {
final countAfterLoad = lsCallCount;
// 'lib' is not in _entries yet, so its parent 'lib/src' won't be there.
f.services.events.emit(DaemonEvent(
subsystem: 'files',
kind: 'files.changed',
data: {'path': 'lib/src/foo.dart'},
ts: DateTime.now().toUtc(),
));
f.services.events.emit(DaemonEvent(subsystem: 'files', kind: 'files.changed', data: {'path': 'lib/src/foo.dart'}, ts: DateTime.now().toUtc()));
await Future<void>.delayed(Duration.zero);
expect(lsCallCount, countAfterLoad);
@@ -355,12 +321,7 @@ void main() {
await c.load();
final countAfterLoad = lsCallCount;
f.services.events.emit(DaemonEvent(
subsystem: 'editor',
kind: 'files.changed',
data: {'path': 'README.md'},
ts: DateTime.now().toUtc(),
));
f.services.events.emit(DaemonEvent(subsystem: 'editor', kind: 'files.changed', data: {'path': 'README.md'}, ts: DateTime.now().toUtc()));
await Future<void>.delayed(Duration.zero);
expect(lsCallCount, countAfterLoad);
@@ -377,12 +338,7 @@ void main() {
await c.load();
final countAfterLoad = lsCallCount;
f.services.events.emit(DaemonEvent(
subsystem: 'files',
kind: 'files.opened',
data: {'path': 'README.md'},
ts: DateTime.now().toUtc(),
));
f.services.events.emit(DaemonEvent(subsystem: 'files', kind: 'files.opened', data: {'path': 'README.md'}, ts: DateTime.now().toUtc()));
await Future<void>.delayed(Duration.zero);
expect(lsCallCount, countAfterLoad);
@@ -395,12 +351,7 @@ void main() {
await c.load();
final countAfterLoad = 1;
f.services.events.emit(DaemonEvent(
subsystem: 'files',
kind: 'files.changed',
data: {'path': 'pubspec.yaml'},
ts: DateTime.now().toUtc(),
));
f.services.events.emit(DaemonEvent(subsystem: 'files', kind: 'files.changed', data: {'path': 'pubspec.yaml'}, ts: DateTime.now().toUtc()));
await Future<void>.delayed(Duration.zero);
// Root '' is in _entries, so reload fires.
@@ -412,12 +363,7 @@ void main() {
final c = makeCtrl();
await c.load();
f.services.events.emit(DaemonEvent(
subsystem: 'files',
kind: 'files.changed',
data: {'path': null},
ts: DateTime.now().toUtc(),
));
f.services.events.emit(DaemonEvent(subsystem: 'files', kind: 'files.changed', data: {'path': null}, ts: DateTime.now().toUtc()));
await Future<void>.delayed(Duration.zero);
// No crash — just checking the null-path guard.
});
@@ -448,12 +394,7 @@ void main() {
// Dispose and then emit an event — must not crash.
c.dispose();
ctrl = null; // prevent tearDown from double-disposing
f.services.events.emit(DaemonEvent(
subsystem: 'files',
kind: 'files.changed',
data: {'path': 'README.md'},
ts: DateTime.now().toUtc(),
));
f.services.events.emit(DaemonEvent(subsystem: 'files', kind: 'files.changed', data: {'path': 'README.md'}, ts: DateTime.now().toUtc()));
await Future<void>.delayed(Duration.zero);
// Test passes if no exception.
});