Rules
loam.dev bietet sechs Analyse-Fähigkeiten, alle hinter einem stabilen
Rule-Interface. Eine neue Rule hinzuzufügen ändert die
Pipeline nicht — nur die Rule-Liste. Eine Rule ist heute live,
fünf sind geplant und erscheinen als Post-MVP-Iterationen.
Der Status ist immer ehrlich angegeben.
Live
Ungenutzte öffentliche Exports
Findet öffentliche API-Member — Klassen, Methoden, Getter/Setter, Felder, Enums, Typedefs — ohne Referenz im gesamten Projekt. Die Analyse läuft auf dem aufgelösten Element-Model, nicht per Regex. Code-Generator-Eingaben (Drift, freezed, Riverpod, json_serializable) werden automatisch ausgeschlossen, ohne jede Konfiguration.
// öffentlich, aber nirgendwo verwendet
class OldHelper {
static String format(String s) => s.trim();
}
// ebenfalls unreferenziert — wird gemeldet
enum LegacyStatus { active, archived } // entweder entfernen, privat machen oder
// mit Begründung unterdrücken:
// loam-ignore: unused-public-exports – re-exported via barrel
// genutzt und behalten:
class ActiveHelper {
static String format(String s) => s.trim();
} Mehr in die Tiefe
Der
Developer Guide
(englisch) enthält die vollständige CLI-Referenz, Konfigurationsoptionen
(Rule-Toggles, Pfad-Suppression, Inline-// loam-ignore:-Direktiven)
und die vollständige Baseline-Onboarding-Sequenz — einschließlich der
Integration von loam gate in GitHub Actions.
Die automatische Unterdrückung für Code-Generator-Eingaben ist im Guide
unter „Automatic codegen-input suppression" beschrieben — die drei
Erkennungssignale (Base-Type-Registry, Annotation-Registry, struktureller
Fallback) funktionieren ohne loam.yaml-Konfiguration.
Geplant
Diese fünf Rules stehen auf der Post-MVP-Roadmap. Jede ist ein
eigenständiges Plugin hinter demselben Rule-Interface —
die Pipeline ändert sich beim Erscheinen nicht.
Zirkuläre Dependencies
Erkennt Import-Zyklen zwischen Dart-Bibliotheken. Zyklen machen die Kompilierungsreihenfolge mehrdeutig, verhindern Tree-Shaking und sind ein häufiges Zeichen unklarer Schichtverantwortlichkeiten.
// lib/a.dart
import 'b.dart';
// lib/b.dart
import 'a.dart'; // ← Zyklus: a → b → a // Gemeinsame Typen in eine dritte Bibliothek auslagern:
// lib/shared.dart (importiert weder a noch b)
// lib/a.dart importiert shared.dart
// lib/b.dart importiert shared.dart Code-Duplikate
Findet strukturell ähnliche Code-Blöcke per AST-normalisiertem Token-Hashing. Markiert Hilfsfunktionen, die kopiert statt extrahiert wurden — ein klassischer KI-Agent-Nebeneffekt.
// feature_a/utils.dart
String formatDate(DateTime d) =>
'${d.day}.${d.month}.${d.year}';
// feature_b/helpers.dart ← Beinahe-Duplikat
String renderDate(DateTime d) =>
'${d.day}.${d.month}.${d.year}'; // lib/shared/date_format.dart
String formatDate(DateTime d) =>
'${d.day}.${d.month}.${d.year}';
// beide Features importieren den gemeinsamen Helper Komplexitäts-Hotspots
Misst zyklomatische und kognitive Komplexität je Funktion/Methode und aggregiert sie zu einem Projekt-Health-Score. Markiert Funktionen, die zu komplex zum Review oder Testen sind.
// kognitive Komplexität ≫ Schwellwert
Future<void> syncData(List<Item> items) async {
for (final item in items) {
if (item.isValid) {
if (item.needsSync) {
try {
if (await remote.has(item.id)) {
await remote.update(item);
} else { await remote.create(item); }
} catch (e) { /* geschluckt */ }
}
}
}
} // aufgeteilt in fokussierte, testbare Helpers
Future<void> syncData(List<Item> items) async {
final candidates = items.where(_needsSync);
await Future.wait(candidates.map(_syncOne));
}
Future<void> _syncOne(Item item) async { … } Architektur-Grenzen
Erkennt das Layer-Layout automatisch (core/, features/, services/, …) und meldet Imports, die verbotene Grenzen überschreiten. Zero-Config: das abgeleitete Regelset wird transparent herausgeschrieben und kann eingefroren oder verfeinert werden.
// features/profile/profile_page.dart
// ↓ Features-Schicht greift in Services-Interna
import '../../services/db/internal_schema.dart'; // services exponiert stattdessen ein öffentliches API:
// services/user_repository.dart (öffentliches Interface)
// features/profile/profile_page.dart
import '../../services/user_repository.dart'; Anti-AI-Slop
Erkennt KI-typische Qualitätsmängel: leere catch-Blöcke, narrative Füll-Kommentare, grundlose // ignore:-Direktiven, tote Guard-Clauses und halluzinierte Abstraktionen. Deterministische AST-Muster laufen zuerst; ein optionaler LLM-Layer erkennt Slop auf Intentionsebene — über einen Verdict-Cache deterministisch und kostenarm.
// leerer catch — klassischer Slop
try {
await fetchData();
} catch (e) {} // ← schluckt alle Fehler
// narrativer Füll-Kommentar
/// Diese Methode verarbeitet die Daten, indem sie
/// über alle Elemente iteriert und die Transformation
/// anwendet.
List<String> process(List<String> items) =>
items.map((i) => i.toUpperCase()).toList(); // mit Kontext behandeln oder weiterwerfen
try {
await fetchData();
} catch (e, st) {
log.error('fetchData failed', e, st);
rethrow;
}
// Doku-Kommentar mit Mehrwert, nicht Rauschen
/// Gibt [items] in Großbuchstaben zurück.
List<String> process(List<String> items) =>
items.map((i) => i.toUpperCase()).toList(); Mehr in die Tiefe
Der
Developer Guide
(englisch) enthält die vollständige CLI-Referenz, Output-Formate,
Konfiguration und ausgearbeitete Beispiele — einschließlich der
Integration von loam gate in GitHub Actions.