mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-03 23:53:29 +08:00
4.4 KiB
4.4 KiB
paths
| paths | |||
|---|---|---|---|
|
Dart/Flutter Coding Style
This file extends common/coding-style.md with Dart and Flutter-specific content.
Formatting
- dart format for all
.dartfiles — enforced in CI (dart format --set-exit-if-changed .) - Line length: 80 characters (dart format default)
- Trailing commas on multi-line argument/parameter lists to improve diffs and formatting
Immutability
- Prefer
finalfor local variables andconstfor compile-time constants - Use
constconstructors wherever all fields arefinal - Return unmodifiable collections from public APIs (
List.unmodifiable,Map.unmodifiable) - Use
copyWith()for state mutations in immutable state classes
// BAD
var count = 0;
List<String> items = ['a', 'b'];
// GOOD
final count = 0;
const items = ['a', 'b'];
Naming
Follow Dart conventions:
camelCasefor variables, parameters, and named constructorsPascalCasefor classes, enums, typedefs, and extensionssnake_casefor file names and library namesSCREAMING_SNAKE_CASEfor constants declared withconstat top level- Prefix private members with
_ - Extension names describe the type they extend:
StringExtensions, notMyHelpers
Null Safety
- Avoid
!(bang operator) — prefer?.,??,if (x != null), or Dart 3 pattern matching; reserve!only where a null value is a programming error and crashing is the right behaviour - Avoid
lateunless initialization is guaranteed before first use (prefer nullable or constructor init) - Use
requiredfor constructor parameters that must always be provided
// BAD — crashes at runtime if user is null
final name = user!.name;
// GOOD — null-aware operators
final name = user?.name ?? 'Unknown';
// GOOD — Dart 3 pattern matching (exhaustive, compiler-checked)
final name = switch (user) {
User(:final name) => name,
null => 'Unknown',
};
// GOOD — early-return null guard
String getUserName(User? user) {
if (user == null) return 'Unknown';
return user.name; // promoted to non-null after the guard
}
Sealed Types and Pattern Matching (Dart 3+)
Use sealed classes to model closed state hierarchies:
sealed class AsyncState<T> {
const AsyncState();
}
final class Loading<T> extends AsyncState<T> {
const Loading();
}
final class Success<T> extends AsyncState<T> {
const Success(this.data);
final T data;
}
final class Failure<T> extends AsyncState<T> {
const Failure(this.error);
final Object error;
}
Always use exhaustive switch with sealed types — no default/wildcard:
// BAD
if (state is Loading) { ... }
// GOOD
return switch (state) {
Loading() => const CircularProgressIndicator(),
Success(:final data) => DataWidget(data),
Failure(:final error) => ErrorWidget(error.toString()),
};
Error Handling
- Specify exception types in
onclauses — never use barecatch (e) - Never catch
Errorsubtypes — they indicate programming bugs - Use
Result-style types or sealed classes for recoverable errors - Avoid using exceptions for control flow
// BAD
try {
await fetchUser();
} catch (e) {
log(e.toString());
}
// GOOD
try {
await fetchUser();
} on NetworkException catch (e) {
log('Network error: ${e.message}');
} on NotFoundException {
handleNotFound();
}
Async / Futures
- Always
awaitFutures or explicitly callunawaited()to signal intentional fire-and-forget - Never mark a function
asyncif it neverawaits anything - Use
Future.wait/Future.anyfor concurrent operations - Check
context.mountedbefore usingBuildContextafter anyawait(Flutter 3.7+)
// BAD — ignoring Future
fetchData(); // fire-and-forget without marking intent
// GOOD
unawaited(fetchData()); // explicit fire-and-forget
await fetchData(); // or properly awaited
Imports
- Use
package:imports throughout — never relative imports (../) for cross-feature or cross-layer code - Order:
dart:→ externalpackage:→ internalpackage:(same package) - No unused imports —
dart analyzeenforces this withunused_import
Code Generation
- Generated files (
.g.dart,.freezed.dart,.gr.dart) must be committed or gitignored consistently — pick one strategy per project - Never manually edit generated files
- Keep generator annotations (
@JsonSerializable,@freezed,@riverpod, etc.) on the canonical source file only