<< All versions
Skill v1.0.0
currentAutomated scan100/100lugassawan/swe-workbench/language-dart
──Details
PublishedSeptember 28, 2026 at 12:41 AM
Content Hashsha256:c0f89e6bc22b65f7...
Git SHA
──Files
Files (1 file, 5.0 KB)
SKILL.md5.0 KBactive
SKILL.md · 93 lines · 5.0 KB
version: "1.0.0" name: language-dart description: Dart idioms — null safety, Futures and Streams, widget composition, and Riverpod app architecture. Auto-load when working with .dart files, pubspec.yaml, or when the user mentions Dart, Flutter, widgets, Riverpod, Streams, or null safety.
Dart
Null safety
- Sound null safety is on by default (Dart ≥2.12) — no unsound nulls sneak through.
- Non-nullable is the default; append
?only when a value can genuinely be absent (String? name). latedefers initialization for values assigned before first read (DI fields,initStatefields) — alatefield read before assignment throws.!(null-assertion) asserts non-null; prefer narrowing (if (x != null)) or?./??over!, since!throws at runtime.??=for lazy default assignment;??for fallback expressions.
dart
String greet(String? name) => 'Hello, ${name ?? 'stranger'}';
Async — Futures and Streams
Future<T>wraps a value that arrives later;async/awaitreads like sync code.- Unhandled Future errors surface as unhandled exceptions — always
try/catcharoundawait, or attach.catchError. Stream<T>models a sequence over time;await forconsumes it,StreamControllerproduces it.Completer<T>bridges callback-based APIs into aFuture.Future.wait([...])for concurrent futures; don'tawaitsequentially in a loop when the work is independent.
dart
Future<User> fetchUser(String id) async {try {final res = await api.get('/users/$id');return User.fromJson(res.data);} on DioException catch (e) {throw UserFetchException(id, e);}}
Widget composition
StatelessWidgetis the default; reach forStatefulWidgetonly when the widget owns mutable state across rebuilds.build()must be pure and fast — no side effects, no I/O; it can run many times per frame.- Compose small widgets instead of deep inheritance — extract a widget class, not a private
_buildX()method, when it needs its ownconstor rebuild boundary. constconstructors on leaf widgets let Flutter skip rebuilding subtrees whose inputs didn't change.- Pass a
Key(ValueKey,ObjectKey) when reordering or diffing a list of like-typed widgets, or state attaches to the wrong element.
State management — Riverpod and Bloc
- Riverpod:
Provider/NotifierProviderdeclares state outside the widget tree;ref.watch(p)subscribes and rebuilds,ref.read(p)reads once (event handlers, notbuild). - Bloc: a
Cubitexposes methods thatemitnew states; aBlocmaps incomingEvents toStates viaon<Event>. Widgets react viaBlocBuilder/BlocListener. - Both push state out of widgets and make it unit-testable without pumping a widget tree — pick per-team convention, don't mix them within the same feature.
dart
final counterProvider = NotifierProvider<Counter, int>(Counter.new);class Counter extends Notifier<int> {@overrideint build() => 0;void increment() => state++;}
Doc comments
- dartdoc —
///doc comment: the first sentence is treated as a standalone summary — keep it one sentence, expand only for a non-obvious contract.
dart
/// Returns the cached price, refreshing it if older than [maxAge].Future<Decimal> priceFor(String symbol, Duration maxAge) async { ... }
Testing
flutter_test:testWidgets('description', (tester) async { ... })drives a widget in an isolated binding.tester.pumpWidget(...)mounts;tester.pump()advances one frame,tester.pumpAndSettle()drains animations/microtasks.find.text(...),find.byType(...),find.byKey(...)locate widgets; assert withexpect(find.text('X'), findsOneWidget).integration_testruns the same API on a real device/emulator for end-to-end flows.- Unit-test
Notifier/Cubit/Bloclogic directly — no widget tree needed.
Tooling
- Format:
dart format . - Lint/analyze:
dart analyze(package) orflutter analyze(app) — configured viaanalysis_options.yaml. - Dependencies: declared in
pubspec.yaml; resolved withdart pub get/flutter pub get. - Test:
flutter test(widget/unit),flutter test integration_test(e2e).
Idioms cheat sheet
finalovervarwhen the reference won't be reassigned;constwhen the value is compile-time constant.- Cascades (
obj..a()..b()) for fluent multi-call setup. - Named constructors (
User.fromJson(...)) beat factory functions with boolean flags. - Extension methods add behavior to existing types without subclassing.
- Records (
(int, String),({int id, String name})) for small ad-hoc multi-value returns, in place of a throwaway class.
Avoid
!as a habitual fix for the analyzer instead of proving non-null.- Business logic inside
build()— extract it into the state-management layer. - Deeply nested
setStatewidgets when aNotifier/Cubitwould isolate the rebuild. - Blocking synchronous work on the UI isolate — use
compute()or a separate isolate for CPU-heavy work.