Hello-World-DSL
Die einfachste sinnvolle CodeGuard-Regel hat sechs Zeilen. Hier ist sie:
@name "Class must not be named Manager"
@severity warn
@category "Naming"
@description "Classes called *Manager are vague, name them after what they actually do"
@recommendation "Pick a verb-based name: OrderProcessor, EmailDispatcher, PriceCalculator"
from t in Types
where t.Kind == "Class"
where t.Name.EndsWith("Manager")
select t
Speichere das als .codeguard/rules/no-manager-suffix.cgr und führe
in deinem Repo aus:
codeguard analyze .
Wenn ihr eine Klasse mit Manager-Suffix habt, taucht sie als Finding auf.
Was passiert hier
Sechs Zeilen Metadaten und vier Zeilen Query. Lass uns das durchgehen.
Metadaten
Jede Regel braucht mindestens @name und @severity. Die anderen sind
optional aber empfohlen, sie tauchen im Editor-Hover, im CI-Log und
in den Output-Formaten wieder auf.
@name "Class must not be named Manager"
@severity warn
@category "Naming"
@description "..."
@recommendation "..."
| Direktive | Pflicht | Beschreibung |
|---|---|---|
@name |
ja | Menschenlesbarer Titel |
@severity |
ja | info, warn oder error |
@category |
nein | Frei wählbar, gruppiert verwandte Regeln |
@description |
nein | Was die Regel prüft |
@recommendation |
nein | Wie man es fixt |
Query
Der Body ist eine LINQ-Query gegen das Code-Modell:
from t in Types # alle Typen
where t.Kind == "Class" # nur Klassen
where t.Name.EndsWith("Manager") # mit Manager-Suffix
select t # gibt alle Treffer als Findings zurück
select t ist der Pflicht-Abschluss. Was du selectest wird zum Finding -
der t ist ein TypeModel, also wird das Finding auf die Datei und
Zeile zeigen wo t deklariert ist.
Variante: Suffix dynamisch verbieten
@name "No vague class suffixes"
@severity warn
from t in Types
where t.Kind == "Class"
where new[] { "Manager", "Helper", "Util", "Utility" }
.Any(suffix => t.Name.EndsWith(suffix))
select t
LINQ-Expressions sind möglich. Du kannst inline-Arrays bauen, sortieren, filtern.
Variante: Mit Sub-Query
Eine Regel die nur Klassen findet die zu groß sind UND zu viele Felder haben:
@name "Large class with many fields, split candidate"
@severity warn
@category "Design"
from t in Types
where t.Kind == "Class"
where t.LinesOfCode > 400
where t.Fields.Count > 15
select t
Variante: Methoden statt Typen
@name "Public async method without CancellationToken"
@severity warn
@category "Async"
from m in Methods
where m.IsAsync
where m.AccessModifier == "Public"
where !m.IsOverride
where !m.Parameters.Any(p => p.TypeShortName == "CancellationToken")
select m
Dasselbe Schema, nur mit Methods statt Types als Startpunkt.
Wo geht's weiter
- Datei-Struktur, wie das
.codeguard-Verzeichnis aufgebaut ist - Syntax-Übersicht, alle verfügbaren Properties und Operatoren
- Best Practices, was gute von schlechten Regeln unterscheidet