The CodeCharter DSL is a subset of LINQ. If you know C#, you already know almost everything you need.
File Anatomy
@name "..." # required
@severity warn # required, info | warn | error
@category "..." # optional, freely chosen
@description "..." # optional
@recommendation "..." # optional
# blank line, then the query body
<linq-expression>
Query Forms
Query Syntax
from t in Types
where t.Kind == "Class"
where t.IsAbstract
select t
Method Syntax
Types.Where(t => t.Kind == "Class" && t.IsAbstract)
Both produce the same result. With more than one condition, query syntax is usually more readable.
Top-Level Collections
| Collection | Element |
|---|---|
Types |
TypeModel |
Methods |
MethodModel |
Properties |
PropertyModel |
Fields |
FieldModel |
Events |
EventModel |
Namespaces |
NamespaceModel |
Assemblies |
AssemblyModel |
TypeDependencies |
TypeDependency |
SyntaxIssues |
SyntaxIssue |
TypeModel Properties (Selection)
Name string
FullName string
Namespace string
Kind string ("Class" | "Interface" | "Struct" | "Enum")
IsAbstract bool
IsSealed bool
IsStatic bool
IsPartial bool
AccessModifier string ("Public" | "Internal" | "Private" | "Protected")
LinesOfCode int
NumberOfMethods int
NumberOfFields int
NumberOfDerivedTypes int
WeightedMethodsPerClass int
DepthOfInheritance int
LackOfCohesion double
ResponseForClass int
Abstractness double
Instability double
DistanceFromMainSequence double
MaintainabilityIndex double
CouplingEfferent int
CouplingAfferent int
BaseType TypeModel
Methods collection<MethodModel>
Constructors collection<MethodModel>
Properties collection<PropertyModel>
Fields collection<FieldModel>
NestedTypes collection<TypeModel>
DerivedTypes collection<TypeModel>
UsedTypes collection<TypeModel>
UsedByTypes collection<TypeModel>
ImplementedInterfaces collection<TypeModel>
Attributes collection<AttributeModel>
MethodModel Properties (Selection)
Name string
FullName string
ShortName string
AccessModifier string
IsAsync bool
IsStatic bool
IsOverride bool
IsInterfaceImplementation bool
IsConstructor bool
IsExtensionMethod bool
IsVirtual bool
ReturnType string
ReturnTypeShortName string
Parameters collection<ParameterModel>
LinesOfCode int
CognitiveComplexity int
CyclomaticComplexity int
NestingDepth int
NumberOfLocalVariables int
NumberOfParameters int
DeclaringType TypeModel
CalledMethods collection<MethodModel>
CalledByMethods collection<MethodModel>
Attributes collection<AttributeModel>
Operators
LINQ standard:
== != < <= > >=
&& || !
+ - * /
Strings:
.StartsWith("...")
.EndsWith("...")
.Contains("...")
.Matches("regex") # regex match
Collections:
.Any(x => ...)
.All(x => ...)
.Count
.Count > 5
.Where(x => ...).Count
Special Sub-Models
BaseType.FullName
where t.BaseType.FullName.Contains("ControllerBase")
Parameters[i].TypeShortName
where m.Parameters.Any(p => p.TypeShortName == "CancellationToken")
SyntaxIssue.Kind
Discrete values for pre-analyzed patterns. Known kinds:
"DateTimeDirectUsage"
"EmptyCatch"
"ExplicitTypeInsteadOfVar"
"FireAndForgetAsync"
"GenericExceptionCatch"
"MagicNumber"
"MissingGuardClause"
"MissingInheritDoc"
"MissingParamDoc"
"MissingXmlDoc"
"NewInConstructor"
"NullEqualityCheck"
"StringConcatenation"
"TodoComment"
"UnusedParameter"
"UnusedUsing"
Common Pitfalls
.Countnot.Count(). On collections,Countis a property, not a method.Kind == "Class"is case-sensitive."class"will not match.AccessModifier == "Public"with a capital P. We follow C# conventions.Parameterscontains only formal parameters, not thethisreceiver on instance methods.