Skip to content

Syntax Overview

The DSL as a compact reference.

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

  • .Count not .Count(). On collections, Count is a property, not a method.
  • Kind == "Class" is case-sensitive. "class" will not match.
  • AccessModifier == "Public" with a capital P. We follow C# conventions.
  • Parameters contains only formal parameters, not the this receiver on instance methods.