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
+12 -26
View File
@@ -11,9 +11,7 @@ import 'editor_settings.dart';
class Selection {
const Selection({required this.start, required this.end});
const Selection.collapsed(int offset)
: start = offset,
end = offset;
const Selection.collapsed(int offset) : start = offset, end = offset;
final int start;
final int end;
@@ -23,10 +21,7 @@ class Selection {
Map<String, Object?> toJson() => {'start': start, 'end': end};
factory Selection.fromJson(Map<String, Object?> j) => Selection(
start: (j['start'] as num).toInt(),
end: (j['end'] as num).toInt(),
);
factory Selection.fromJson(Map<String, Object?> j) => Selection(start: (j['start'] as num).toInt(), end: (j['end'] as num).toInt());
@override
bool operator ==(Object other) => other is Selection && other.start == start && other.end == end;
@@ -39,14 +34,8 @@ class Selection {
}
class EditorBuffer {
EditorBuffer({
required this.id,
required this.path,
required this.content,
Selection? selection,
this.dirty = false,
this.settings = EditorSettings.empty,
}) : selection = selection ?? const Selection.collapsed(0);
EditorBuffer({required this.id, required this.path, required this.content, Selection? selection, this.dirty = false, this.settings = EditorSettings.empty})
: selection = selection ?? const Selection.collapsed(0);
/// Stable daemon-local id (`b_1`, `b_2`, …).
final String id;
@@ -77,18 +66,15 @@ class EditorBuffer {
EditorSettings settings;
Map<String, Object?> toJson() => {
'id': id,
'path': path,
'length': content.length,
'selection': selection.toJson(),
'dirty': dirty,
'editorSettings': settings.toJson(),
};
'id': id,
'path': path,
'length': content.length,
'selection': selection.toJson(),
'dirty': dirty,
'editorSettings': settings.toJson(),
};
/// Full snapshot including [content] — for `editor.read` / tests /
/// anything that needs the text explicitly.
Map<String, Object?> toFullJson() => {
...toJson(),
'content': content,
};
Map<String, Object?> toFullJson() => {...toJson(), 'content': content};
}
+21 -21
View File
@@ -54,11 +54,11 @@ class EditorSettings {
/// The line terminator [endOfLine] names, or null when unset.
String? get eolString => switch (endOfLine) {
'lf' => '\n',
'crlf' => '\r\n',
'cr' => '\r',
_ => null,
};
'lf' => '\n',
'crlf' => '\r\n',
'cr' => '\r',
_ => null,
};
/// The text one Tab press inserts, or null to keep the editor's default
/// (Flutter's focus traversal) — the editor only takes over Tab when a source
@@ -75,25 +75,25 @@ class EditorSettings {
/// first) lives in the resolver — a higher-precedence source (settings panel,
/// clide settings file) merges over a lower one (.editorconfig).
EditorSettings merge(EditorSettings other) => EditorSettings(
indentStyle: other.indentStyle ?? indentStyle,
indentSize: other.indentSize ?? indentSize,
tabWidth: other.tabWidth ?? tabWidth,
endOfLine: other.endOfLine ?? endOfLine,
maxLineLength: other.maxLineLength ?? maxLineLength,
trimTrailingWhitespace: other.trimTrailingWhitespace ?? trimTrailingWhitespace,
insertFinalNewline: other.insertFinalNewline ?? insertFinalNewline,
);
indentStyle: other.indentStyle ?? indentStyle,
indentSize: other.indentSize ?? indentSize,
tabWidth: other.tabWidth ?? tabWidth,
endOfLine: other.endOfLine ?? endOfLine,
maxLineLength: other.maxLineLength ?? maxLineLength,
trimTrailingWhitespace: other.trimTrailingWhitespace ?? trimTrailingWhitespace,
insertFinalNewline: other.insertFinalNewline ?? insertFinalNewline,
);
/// Only the set keys, for the IPC payload. Empty map when [isEmpty].
Map<String, Object?> toJson() => {
if (indentStyle != null) 'indent_style': indentStyle,
if (indentSize != null) 'indent_size': indentSize,
if (tabWidth != null) 'tab_width': tabWidth,
if (endOfLine != null) 'end_of_line': endOfLine,
if (maxLineLength != null) 'max_line_length': maxLineLength,
if (trimTrailingWhitespace != null) 'trim_trailing_whitespace': trimTrailingWhitespace,
if (insertFinalNewline != null) 'insert_final_newline': insertFinalNewline,
};
if (indentStyle != null) 'indent_style': indentStyle,
if (indentSize != null) 'indent_size': indentSize,
if (tabWidth != null) 'tab_width': tabWidth,
if (endOfLine != null) 'end_of_line': endOfLine,
if (maxLineLength != null) 'max_line_length': maxLineLength,
if (trimTrailingWhitespace != null) 'trim_trailing_whitespace': trimTrailingWhitespace,
if (insertFinalNewline != null) 'insert_final_newline': insertFinalNewline,
};
factory EditorSettings.fromJson(Object? raw) {
if (raw is! Map) return empty;
+4 -4
View File
@@ -113,10 +113,10 @@ int? _posInt(String? v) {
}
bool? _bool(String? v) => switch (v) {
'true' => true,
'false' => false,
_ => null,
};
'true' => true,
'false' => false,
_ => null,
};
// ---------------------------------------------------------------------------
// INI parsing
+12 -57
View File
@@ -15,10 +15,7 @@ import 'buffer.dart';
import 'editor_settings_resolver.dart';
class EditorRegistry {
EditorRegistry({
required this.events,
required this.workspaceRoot,
});
EditorRegistry({required this.events, required this.workspaceRoot});
final DaemonEventSink events;
@@ -53,12 +50,7 @@ class EditorRegistry {
}
final id = 'b_${_nextId++}';
final buf = EditorBuffer(
id: id,
path: path,
content: content,
settings: resolveEditorSettings(workspaceRoot, path),
);
final buf = EditorBuffer(id: id, path: path, content: content, settings: resolveEditorSettings(workspaceRoot, path));
_buffers[id] = buf;
_pathToId[path] = id;
@@ -111,10 +103,7 @@ class EditorRegistry {
void setSelection(String id, Selection sel) {
final buf = _buffers[id];
if (buf == null) return;
final clamped = Selection(
start: sel.start.clamp(0, buf.content.length),
end: sel.end.clamp(0, buf.content.length),
);
final clamped = Selection(start: sel.start.clamp(0, buf.content.length), end: sel.end.clamp(0, buf.content.length));
if (clamped.start == buf.selection.start && clamped.end == buf.selection.end) {
return;
}
@@ -131,23 +120,12 @@ class EditorRegistry {
if (buf == null) return;
buf.content = content;
if (selection != null) {
buf.selection = Selection(
start: selection.start.clamp(0, content.length),
end: selection.end.clamp(0, content.length),
);
buf.selection = Selection(start: selection.start.clamp(0, content.length), end: selection.end.clamp(0, content.length));
} else {
buf.selection = Selection(
start: buf.selection.start.clamp(0, content.length),
end: buf.selection.end.clamp(0, content.length),
);
buf.selection = Selection(start: buf.selection.start.clamp(0, content.length), end: buf.selection.end.clamp(0, content.length));
}
buf.dirty = true;
_emit('editor.edited', {
'id': id,
'kind': 'replace',
'length': content.length,
'selection': buf.selection.toJson(),
});
_emit('editor.edited', {'id': id, 'kind': 'replace', 'length': content.length, 'selection': buf.selection.toJson()});
}
/// Persist [id] to disk. Applies the buffer's on-save settings (EOL,
@@ -167,19 +145,11 @@ class EditorRegistry {
if (changed) {
buf.content = normalized;
buf.selection = Selection(
start: buf.selection.start.clamp(0, normalized.length),
end: buf.selection.end.clamp(0, normalized.length),
);
buf.selection = Selection(start: buf.selection.start.clamp(0, normalized.length), end: buf.selection.end.clamp(0, normalized.length));
// Re-broadcast so the UI reloads the normalized text (the editor.edited
// handler re-reads the buffer); emitted before editor.saved clears dirty.
buf.dirty = false;
_emit('editor.edited', {
'id': id,
'kind': 'replace',
'length': normalized.length,
'selection': buf.selection.toJson(),
});
_emit('editor.edited', {'id': id, 'kind': 'replace', 'length': normalized.length, 'selection': buf.selection.toJson()});
}
buf.dirty = false;
@@ -197,11 +167,7 @@ class EditorRegistry {
final next = resolveEditorSettings(workspaceRoot, buf.path);
if (next.toJson().toString() == buf.settings.toJson().toString()) continue;
buf.settings = next;
_emit('editor.settings-changed', {
'id': buf.id,
'path': buf.path,
'editorSettings': next.toJson(),
});
_emit('editor.settings-changed', {'id': buf.id, 'path': buf.path, 'editorSettings': next.toJson()});
}
}
@@ -235,26 +201,15 @@ class EditorRegistry {
void _emitActive() {
final buf = active;
_emit('editor.active-changed', {
'id': buf?.id,
'path': buf?.path,
});
_emit('editor.active-changed', {'id': buf?.id, 'path': buf?.path});
}
void _emitSelection(EditorBuffer buf) {
_emit('editor.selection-changed', {
'id': buf.id,
'selection': buf.selection.toJson(),
});
_emit('editor.selection-changed', {'id': buf.id, 'selection': buf.selection.toJson()});
}
void _emit(String kind, Map<String, Object?> data) {
events.emit(IpcEvent(
subsystem: 'editor',
kind: kind,
timestamp: DateTime.now().toUtc(),
data: data,
));
events.emit(IpcEvent(subsystem: 'editor', kind: kind, timestamp: DateTime.now().toUtc(), data: data));
}
String _absolutePathOf(String repoRelative) {