pub trait CstRule:
Rule
+ Serialize
+ Deserialize {
// Provided methods
fn check_node(&self, node: &SyntaxNode, ctx: &mut RuleCtx) -> Option<()> { ... }
fn check_token(&self, token: &SyntaxToken, ctx: &mut RuleCtx) -> Option<()> { ... }
fn check_root(&self, root: &SyntaxNode, ctx: &mut RuleCtx) -> Option<()> { ... }
}
Expand description
The main type of rule run by the runner. The rule takes individual
nodes inside of a Concrete Syntax Tree and checks them.
It may also take individual syntax tokens.
Rule must be all be Send
+ Sync
, because rules are run in parallel.
§Rule Level Configuration
Rules do not know about the lint level they were configured for, the runner runs the rules, then maps any error/warning diagnostics to their appropriate severity. This saves on boilerplate code for getting the appropriate diagnostic builder type and config.
§Guidelines
This is a list of guidelines and tips you should generally follow when implementing a rule:
- Do not use text based equality, it is inaccurate, instead use
lexical_eq
. - Avoid using
text_range
on nodes, it is inaccurate because it may include whitespace, instead usetrimmed_range
. - Avoid using
text
on nodes for the same reason as the previous, usetrimmed_text
. - If you can offer better diagnostics and more context around a rule error, always do it! It is a central goal of the project to offer very helpful diagnostics.
- Do not be afraid to clone syntax nodes, ast nodes, and syntax tokens. They are all backed by an
Rc
around Node data. therefore they can be cheaply cloned (but if you can, have your functions take a reference since Rc cloning is not zero cost). - Do not try to rely on the result of other rules, it is impossible because rules are run at the same time.
- Do not rely on file data of different files. There is a separate rule type for this.
- Do not unwrap pieces of an AST node (sometimes it is ok because they are guaranteed to be there), since that will cause panics with error recovery.
- Do not use node or string coloring outside of diagnostic notes, it messes with termcolor and ends up looking horrible.
Provided Methods§
Sourcefn check_node(&self, node: &SyntaxNode, ctx: &mut RuleCtx) -> Option<()>
fn check_node(&self, node: &SyntaxNode, ctx: &mut RuleCtx) -> Option<()>
Check an individual node in the syntax tree.
You can use the match_ast
macro to make matching a node to an ast node easier.
The reason this uses nodes and not a visitor is because nodes are more flexible,
converting them to an AST node has zero cost and you can easily traverse surrounding nodes.
Defaults to doing nothing.
The return type is Option<()>
to allow usage of ?
on the properties of AST nodes which are all optional.
Sourcefn check_token(&self, token: &SyntaxToken, ctx: &mut RuleCtx) -> Option<()>
fn check_token(&self, token: &SyntaxToken, ctx: &mut RuleCtx) -> Option<()>
Check an individual token in the syntax tree. Defaults to doing nothing.
Sourcefn check_root(&self, root: &SyntaxNode, ctx: &mut RuleCtx) -> Option<()>
fn check_root(&self, root: &SyntaxNode, ctx: &mut RuleCtx) -> Option<()>
Check the root of the tree one time.
This method is guaranteed to only be called once.
The root’s kind will be either SCRIPT
or MODULE
.
Defaults to doing nothing.