The Calidus Model
Abstract
In which the author outlines the basics of Calidus, the most important concepts and classes and how to use them.
Concrete
Calidus is not a terribly complex application. There are no zillion classes to get to know, there are no hard words or hidden meanings and most things do exactly what they sound like. In order to take full advantage of Calidus and develop custom parts such as rules it is important to know some of the inner workings of Calidus. This part is intended for advanced users and is a must-read for developers.
Characters
Technically, the smallest part of Calidus is the character, provided by the builtin character class. The concept of a character is not explicitly present in Calidus because no rule validation is performed on characters, but since they are the base element on which a token is built they deserve an honorable mention.
Tokens
A token is the smallest usefull part of the Calidus model. A token can be described as a collection containing at least one character, grouped together in the builtin String class. A token is either:
- A single-character token, such as a SpaceToken or a TabToken
- A single string token, such as an IdentifierToken or a NameSpaceToken
- A multiple string token, such as a LineCommentToken
Calidus uses Coco/R to parse source code into tokens. This means that the list of tokens recognized by Calidus is almost exactly the same as the list of tokens recognized by Coco/R. There are some exceptions to this rule: whitespace is not normally part of the Coco/R parser’s returned token types and is therefore provided by an additional parser.
Tokens that cannot be parsed as a more specific token are GenericTokens.
Statements
A statement is a collection containing at least one token. What exactly constitutes a statement is somewhat determined by the C# language: in most cases the end of a statement is a semicolon. For if, for, while constructs and the likes the end of a statement is the closing round bracket ‘)’, and for attributes the end of a statement is the closing square bracket ‘]’.
The statement parser groups tokens together by splitting them at certain well-defined places, the most common example of this is when a semicolon was encountered. There are other ways to group statements, which include using brackets, newlines and other special token types.
Parsing token groups to see if they match a statement definition is a complex operation, and the definition of what constitutes a statement can differ greatly. One thing that creates a lot of complexity is the amount of whitespace separating tokens, which may or may not be relevant depending on the context. To make token parsing easy Calidus provides a fluent interface that allows a declarative statement definition.
Statements that cannot be parsed as a more specific statement are GenericStatements.
Lines
Lines are probably the easiest elements in the Calidus model. A line is just a line: it is a collection of tokens that reside on the same line. Lines are the only elements that can have rules associated with them but do not have any native support for pluggable definitions and extensions: what constitutes a line can never change and is fixed by Calidus.
Blocks
Blocks are logical groupings of at least one statement. Blocks have very wide definitions: a series of using statements in a file are grouped into a block because they are related, but so are all elements in the source file since they compose the FileBlock. The entire contents of a class constitutes a ClassBlock, and blocks are also the place where an if, while, for, do while, foreach… statement is present along with the code that is run as part of it.
Rules
Calidus is a source style validation tool, and the constraints placed on the source are coded into rules. Rules can be put on top of the following Calidus elements:
- Statements, based off of StatementRuleBase
- Lines, based off of LineRuleBase
- Blocks, based off of BlockRuleBase
Tokens do not have rules associated with them as a token itself cannot be invalid. For example, a line comment is parsed into a LineCommentToken, but validating this token must be done through the statement that contains this token which is the LineCommentStatement.
Calidus rules are automatically configured by the class reponsible for creating them, allowing a user to use a pre-built rule but apply some customization to it. A good example of this principle is the MemberNameMatchesPatternRule, where a class member’s name is validated against a regex pattern. The pattern itself has a default setting, which can be adjusted to meet the developers needs. This is unlike Microsoft’s StyleCop tool, which has several rules used to validate member names, each of which must be enabled or disabled and might not even meet the requirements when a naming pattern is used that is not built into the application. Rule configuration can be done through the main Calidus GUI.