Main coves client
1# Flutter Code Quality & Formatting Guide
2
3This guide covers linting, formatting, and automated code quality checks for the Coves mobile app.
4
5---
6
7## Tools Overview
8
9### 1. **flutter analyze** (Static Analysis / Linting)
10Checks code for errors, warnings, and style issues based on `analysis_options.yaml`.
11
12### 2. **dart format** (Code Formatting)
13Auto-formats code to Dart style guide (spacing, indentation, line length).
14
15### 3. **analysis_options.yaml** (Configuration)
16Defines which lint rules are enforced.
17
18---
19
20## Quick Start
21
22### Run All Quality Checks
23```bash
24# Format code
25dart format .
26
27# Analyze code
28flutter analyze
29
30# Run tests
31flutter test
32```
33
34---
35
36## 1. Code Formatting with `dart format`
37
38### Basic Usage
39```bash
40# Check if code needs formatting (exits with 1 if changes needed)
41dart format --output=none --set-exit-if-changed .
42
43# Format all Dart files
44dart format .
45
46# Format specific directory
47dart format lib/
48
49# Format specific file
50dart format lib/services/coves_api_service.dart
51
52# Dry run (show what would change without modifying files)
53dart format --output=show .
54```
55
56### Dart Formatting Rules
57- **80-character line limit** (configurable in analysis_options.yaml)
58- **2-space indentation**
59- **Trailing commas** for better git diffs
60- **Consistent spacing** around operators
61
62### Example: Trailing Commas
63```dart
64// ❌ Without trailing comma (bad for diffs)
65Widget build(BuildContext context) {
66 return Container(
67 child: Text('Hello')
68 );
69}
70
71// ✅ With trailing comma (better for diffs)
72Widget build(BuildContext context) {
73 return Container(
74 child: Text('Hello'), // ← Trailing comma
75 );
76}
77```
78
79---
80
81## 2. Static Analysis with `flutter analyze`
82
83### Basic Usage
84```bash
85# Analyze entire project
86flutter analyze
87
88# Analyze specific directory
89flutter analyze lib/
90
91# Analyze specific file
92flutter analyze lib/services/coves_api_service.dart
93
94# Analyze with verbose output
95flutter analyze --verbose
96```
97
98### Understanding Output
99```
100 error • Business logic in widgets • lib/screens/feed.dart:42 • custom_rule
101warning • Missing documentation • lib/services/api.dart:10 • public_member_api_docs
102 info • Line too long • lib/models/post.dart:55 • lines_longer_than_80_chars
103```
104
105- **error**: Must fix (breaks build in CI)
106- **warning**: Should fix (may break CI depending on config)
107- **info**: Optional suggestions (won't break build)
108
109---
110
111## 3. Upgrading to Stricter Lint Rules
112
113### Option A: Use Recommended Rules (Recommended)
114Replace your current `analysis_options.yaml` with the stricter version:
115
116```bash
117# Backup current config
118cp analysis_options.yaml analysis_options.yaml.bak
119
120# Use recommended config
121cp analysis_options_recommended.yaml analysis_options.yaml
122
123# Test it
124flutter analyze
125```
126
127### Option B: Use Very Good Analysis (Most Strict)
128For maximum code quality, use Very Good Ventures' lint rules:
129
130```yaml
131# pubspec.yaml
132dev_dependencies:
133 very_good_analysis: ^6.0.0
134```
135
136```yaml
137# analysis_options.yaml
138include: package:very_good_analysis/analysis_options.yaml
139```
140
141### Option C: Customize Incrementally
142Start with your current rules and add these high-value rules:
143
144```yaml
145# analysis_options.yaml
146include: package:flutter_lints/flutter.yaml
147
148linter:
149 rules:
150 # High-value additions
151 - prefer_const_constructors
152 - prefer_const_literals_to_create_immutables
153 - prefer_final_locals
154 - avoid_print
155 - require_trailing_commas
156 - prefer_single_quotes
157 - lines_longer_than_80_chars
158 - unawaited_futures
159```
160
161---
162
163## 4. IDE Integration
164
165### VS Code
166Add to `.vscode/settings.json`:
167
168```json
169{
170 "dart.lineLength": 80,
171 "editor.formatOnSave": true,
172 "editor.formatOnType": false,
173 "editor.rulers": [80],
174 "dart.showLintNames": true,
175 "dart.previewFlutterUiGuides": true,
176 "dart.previewFlutterUiGuidesCustomTracking": true,
177 "[dart]": {
178 "editor.formatOnSave": true,
179 "editor.selectionHighlight": false,
180 "editor.suggest.snippetsPreventQuickSuggestions": false,
181 "editor.suggestSelection": "first",
182 "editor.tabCompletion": "onlySnippets",
183 "editor.wordBasedSuggestions": "off"
184 }
185}
186```
187
188### Android Studio / IntelliJ
1891. **Settings → Editor → Code Style → Dart**
190 - Set line length to 80
191 - Enable "Format on save"
1922. **Settings → Editor → Inspections → Dart**
193 - Enable all inspections
194
195---
196
197## 5. Pre-Commit Hooks (Recommended)
198
199Automate quality checks before every commit using `lefthook`.
200
201### Setup
202```bash
203# Install lefthook
204brew install lefthook # macOS
205# or
206curl -1sLf 'https://dl.cloudsmith.io/public/evilmartians/lefthook/setup.deb.sh' | sudo -E bash
207sudo apt install lefthook # Linux
208
209# Initialize
210lefthook install
211```
212
213### Configuration
214Create `lefthook.yml` in project root:
215
216```yaml
217# lefthook.yml
218pre-commit:
219 parallel: true
220 commands:
221 # Format Dart code
222 format:
223 glob: "*.dart"
224 run: dart format {staged_files} && git add {staged_files}
225
226 # Analyze Dart code
227 analyze:
228 glob: "*.dart"
229 run: flutter analyze {staged_files}
230
231 # Run quick tests (optional)
232 # test:
233 # glob: "*.dart"
234 # run: flutter test
235
236pre-push:
237 commands:
238 # Full test suite before push
239 test:
240 run: flutter test
241
242 # Full analyze before push
243 analyze:
244 run: flutter analyze
245```
246
247### Alternative: Simple Git Hook
248Create `.git/hooks/pre-commit`:
249
250```bash
251#!/bin/bash
252
253echo "Running dart format..."
254dart format .
255
256echo "Running flutter analyze..."
257flutter analyze
258
259if [ $? -ne 0 ]; then
260 echo "❌ Analyze failed. Fix issues before committing."
261 exit 1
262fi
263
264echo "✅ Pre-commit checks passed!"
265```
266
267Make it executable:
268```bash
269chmod +x .git/hooks/pre-commit
270```
271
272---
273
274## 6. CI/CD Integration
275
276### GitHub Actions
277Create `.github/workflows/code_quality.yml`:
278
279```yaml
280name: Code Quality
281
282on:
283 pull_request:
284 branches: [main, develop]
285 push:
286 branches: [main, develop]
287
288jobs:
289 analyze:
290 runs-on: ubuntu-latest
291 steps:
292 - uses: actions/checkout@v3
293
294 - uses: subosito/flutter-action@v2
295 with:
296 flutter-version: '3.24.0'
297 channel: 'stable'
298
299 - name: Install dependencies
300 run: flutter pub get
301
302 - name: Verify formatting
303 run: dart format --output=none --set-exit-if-changed .
304
305 - name: Analyze code
306 run: flutter analyze
307
308 - name: Run tests
309 run: flutter test
310```
311
312### GitLab CI
313```yaml
314# .gitlab-ci.yml
315stages:
316 - quality
317 - test
318
319format:
320 stage: quality
321 image: cirrusci/flutter:stable
322 script:
323 - flutter pub get
324 - dart format --output=none --set-exit-if-changed .
325
326analyze:
327 stage: quality
328 image: cirrusci/flutter:stable
329 script:
330 - flutter pub get
331 - flutter analyze
332
333test:
334 stage: test
335 image: cirrusci/flutter:stable
336 script:
337 - flutter pub get
338 - flutter test
339```
340
341---
342
343## 7. Common Issues & Solutions
344
345### Issue: "lines_longer_than_80_chars"
346**Solution:** Break long lines with trailing commas
347```dart
348// Before
349final user = User(name: 'Alice', email: 'alice@example.com', age: 30);
350
351// After
352final user = User(
353 name: 'Alice',
354 email: 'alice@example.com',
355 age: 30,
356);
357```
358
359### Issue: "prefer_const_constructors"
360**Solution:** Add const where possible
361```dart
362// Before
363return Container(child: Text('Hello'));
364
365// After
366return const Container(child: Text('Hello'));
367```
368
369### Issue: "avoid_print"
370**Solution:** Use debugPrint with kDebugMode
371```dart
372// Before
373print('Error: $error');
374
375// After
376if (kDebugMode) {
377 debugPrint('Error: $error');
378}
379```
380
381### Issue: "unawaited_futures"
382**Solution:** Either await or use unawaited()
383```dart
384// Before
385someAsyncFunction(); // Warning
386
387// After - Option 1: Await
388await someAsyncFunction();
389
390// After - Option 2: Explicitly ignore
391import 'package:flutter/foundation.dart';
392unawaited(someAsyncFunction());
393```
394
395---
396
397## 8. Project-Specific Rules
398
399### Current Configuration
400We use `flutter_lints: ^5.0.0` with default rules.
401
402### Recommended Upgrade Path
4031. **Week 1:** Add format-on-save to IDEs
4042. **Week 2:** Add pre-commit formatting hook
4053. **Week 3:** Enable stricter analysis_options.yaml
4064. **Week 4:** Add CI/CD checks
4075. **Week 5:** Fix all existing violations
4086. **Week 6:** Enforce in CI (fail builds on violations)
409
410### Custom Rules for Coves
411Add these to `analysis_options.yaml` for Coves-specific quality:
412
413```yaml
414analyzer:
415 errors:
416 # Treat these as errors (not warnings)
417 missing_required_param: error
418 missing_return: error
419
420 exclude:
421 - '**/*.g.dart'
422 - '**/*.freezed.dart'
423 - 'packages/atproto_oauth_flutter/**'
424
425linter:
426 rules:
427 # Architecture enforcement
428 - avoid_print
429 - prefer_const_constructors
430 - prefer_final_locals
431
432 # Code quality
433 - require_trailing_commas
434 - lines_longer_than_80_chars
435
436 # Safety
437 - unawaited_futures
438 - close_sinks
439 - cancel_subscriptions
440```
441
442---
443
444## 9. Quick Reference
445
446### Daily Workflow
447```bash
448# Before committing
449dart format .
450flutter analyze
451flutter test
452
453# Or use pre-commit hook (automated)
454```
455
456### Before PR
457```bash
458# Full quality check
459dart format --output=none --set-exit-if-changed .
460flutter analyze
461flutter test --coverage
462```
463
464### Fix Formatting Issues
465```bash
466# Auto-fix all formatting
467dart format .
468
469# Fix specific file
470dart format lib/screens/home/feed_screen.dart
471```
472
473### Ignore Specific Warnings
474```dart
475// Ignore for one line
476// ignore: avoid_print
477print('Debug message');
478
479// Ignore for entire file
480// ignore_for_file: avoid_print
481
482// Ignore for block
483// ignore: lines_longer_than_80_chars
484final veryLongVariableName = 'This is a very long string that exceeds 80 characters';
485```
486
487---
488
489## 10. Resources
490
491### Official Documentation
492- [Dart Linter Rules](https://dart.dev/lints)
493- [Flutter Lints Package](https://pub.dev/packages/flutter_lints)
494- [Effective Dart Style Guide](https://dart.dev/guides/language/effective-dart/style)
495
496### Community Resources
497- [Very Good Analysis](https://pub.dev/packages/very_good_analysis)
498- [Lint Package](https://pub.dev/packages/lint)
499- [Flutter Analyze Best Practices](https://docs.flutter.dev/testing/best-practices)
500
501---
502
503## Next Steps
504
5051. ✅ Review `analysis_options_recommended.yaml`
5062. ⬜ Decide on strictness level (current / recommended / very_good)
5073. ⬜ Set up IDE format-on-save
5084. ⬜ Create pre-commit hooks
5095. ⬜ Add CI/CD quality checks
5106. ⬜ Schedule time to fix existing violations
5117. ⬜ Enforce in team workflow