Irbisa · Cheatsheet
Lints, Analyzer & Code Review
analysis_options, lint rulesets, dart fix, dart format, custom_lint, annotations, PR review
What is
analysis_options.yaml, and what can you configure in it?include: package:flutter_lints/flutter.yaml analyzer: exclude: - "**/*.g.dart" - "**/*.freezed.dart"…What is the difference between
dart analyze,dart fixanddart format?dart analyze # report only; infos do not faildart analyze --fatal-infos # what CI should runflutter analyze # infos are already fatal here dart fix --dry-run # preview automated fixes, grouped by ruledart fix --apply --code=prefer_const_constructors…With
flutter_lintsenabled, what doesflutter analyzereport for this widget, and how do you fix each issue?class Greeting extends StatelessWidget { Greeting({this.name}); final String? name; @override Widget build(BuildContext context) { print('build $name'); return Column(children: [ Container(height: 16, child: const Text('Hi')), Container(child: Text(name ?? 'guest')), const Icon(Icons.star, color: Color(0xFF00)), ]); }}What is the difference between
lints,flutter_lintsandvery_good_analysis, and how do you choose one?# Flutter app default, generated by flutter createinclude: package:flutter_lints/flutter.yaml # Pure Dart package: include: package:lints/recommended.yaml# Strict third-party: include: package:very_good_analysis/analysis_options.yaml…How do you change a lint's severity, and which rules are worth promoting to
error?include: package:flutter_lints/flutter.yaml analyzer: errors: use_build_context_synchronously: error # crash after an await unawaited_futures: error # error with no catch to reach…Which Flutter lints catch real bugs rather than style, and what does each one prevent?
// Always false, and it compilesfinal ids = <int>[1, 2, 3];const raw = '2';final found = ids.contains(raw); // collection_methods_unrelated_typefinal same = raw == 2; // unrelated_type_equality_checksfinal fixed = ids.contains(int.parse(raw)); // right…Find the bug: on a 404 the profile screen stays on the spinner and the console shows an unhandled error.
enum ApiFailure { notFound, server } Future<User> fetchUser(http.Client client, Uri url) async { final res = await client.get(url); if (res.statusCode == 404) throw ApiFailure.notFound; if (res.statusCode != 200) throw ApiFailure.server; return User.fromJson(jsonDecode(res.body) as Map<String, dynamic>);} Future<void> loadProfile(Uri url) async { try { profile.value = ProfileLoaded(await fetchUser(client, url)); } on Exception catch (e) { profile.value = ProfileError(e); }}What is the difference between
// ignore:,// ignore_for_file:andanalyzer: exclude:, and which do you accept in a PR?// wrong in hand-written code: every lint in this file, including future ones// ignore_for_file: type=lint // right: one rule, one line, and a reason the reviewer can check// ignore: avoid_dynamic_calls -- payload shape is validated in decode()String title(dynamic json) => json['title'] as String;…What do
@override,@immutable,@protected,@visibleForTestingand@mustCallSuperdo, and what actually enforces them?import 'package:flutter/foundation.dart'; // re-exports package:meta annotations @immutableclass Filter { const Filter(this.tags); final List<String> tags; // passes must_be_immutable, yet tags.add() works…Find the bug: DevTools shows one more
ChatViewModelin memory each time the user opens and closes a chat.abstract class ViewModel { final _subs = <StreamSubscription<Object?>>[]; void watch<T>(Stream<T> s, void Function(T) f) => _subs.add(s.listen(f)); Future<void> dispose() => Future.wait([for (final s in _subs) s.cancel()]);} class ChatViewModel extends ViewModel { ChatViewModel(ChatRepository repo) { watch(repo.messages(), messages.add); } final messages = <Message>[]; Timer? _typing; @override Future<void> dispose() async => _typing?.cancel();}How do you rename a public method in a package other apps depend on without breaking their builds?
class UserApi { // The new name holds the only implementation. User parseUser(String body) => User.fromJson(jsonDecode(body) as Map<String, dynamic>); @Deprecated('Use parseUser instead. Will be removed in 3.0.0.') User decodeUser(String body) => parseUser(body); // forwards, never copies…How do you keep formatting consistent across a team, and what changed in
dart formatwith Dart 3.7?# analysis_options.yaml, read by the IDE, the CLI and CI:# formatter:# page_width: 100# trailing_commas: preserve # Dart 3.8+: keep commas as written # CI gate: exit 1 if any file would change…What belongs in a pre-commit hook and what belongs in CI, and why can't the hook be your quality gate?
# lefthook.yml: committed; `lefthook install` wires .git/hooks after a clonepre-commit: commands: format: glob: "*.dart" run: dart format {staged_files}…dart analyzefails in CI on code your IDE shows as clean. It is the same analyzer, so what differs?How do you find unused code, dependencies and assets in a Flutter project, and what can no tool detect?
This
Statepasses the analyzer and its widget test. What would you flag in code review?class _OrderPageState extends State<OrderPage> { final _note = TextEditingController(); Order? _order; @override void initState() { super.initState(); _load(); } Future<void> _load() async { final order = await OrderRepository().fetch(widget.orderId); setState(() => _order = order); } @override Widget build(BuildContext context) => Column(children: [Text(_order?.title ?? 'Loading'), TextField(controller: _note)]);}Half of a PR was written by an AI assistant. What do you check before approving it, beyond what
flutter analyzeand the tests catch?// All three pass `flutter analyze` with flutter_lints; none should be approved. HttpClient trustingClient() => HttpClient() ..badCertificateCallback = (cert, host, port) => true; // accepts any certificate Future<void> onSave(OrderRepository repo, Order order) async {…How do you run code review on a Flutter team: what do you look for beyond the analyzer, and how do you phrase comments?
How do you turn a recurring review comment into a custom lint rule, and how do you make it run in CI?
// Rules package, built on custom_lint_builder.// CI must run it separately: dart run custom_lintPluginBase createPlugin() => _HouseLints(); class _HouseLints extends PluginBase { @override…A reviewer wants CI to fail when a file passes 300 lines or a function's cyclomatic complexity passes 10. Would you agree?
Enabling a strict ruleset in a 200,000-line app reports 4,000 issues. How do you land it without one unreviewable diff?
# 1. The mechanical share, in its own commit, with no manual editsdart fix --dry-rundart fix --apply # or --code=<rule> to keep it reviewablegit commit -am "chore: dart fix --apply (machine-generated)" # 2. Rank what is left; in --format=machine field 3 is the diagnostic code…