-
-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking issue: implement the linter #501
Comments
Hey @mtshiba. The child issues seems good for me to tinker around Erg code. I would like to work on this. If you have any pointers to point me in the right direction, that would be great! |
OK, here are the steps for adding rules to the linter.
For example: pub(crate) fn true_comparison(expr: &Expr, input: Input, caused_by: String, loc: Location) -> CompileWarning {
CompileWarning::new(
ErrorCore::new(
vec![
SubMessage::ambiguous_new(loc, vec![], Some(format!("just write: {}", expr.to_string_notype()))),
],
"equality checks against True are redundant".to_string(),
0,
ErrorKind::Warning,
loc,
),
input,
caused_by,
)
} The function can take any arguments, but at least the following arguments are required.
The return type is
For example, let's add a rule to warn about redundant expressions such as impl Linter {
...
fn lint_bool_comparison(&mut self, expr: &Expr) {
match expr {
Expr::BinOp(binop) => {
let lhs = <&Literal>::try_from(binop.lhs.as_ref()).map(|lit| &lit.value);
let rhs = <&Literal>::try_from(binop.rhs.as_ref()).map(|lit| &lit.value);
let lhs_or_rhs = lhs.or(rhs);
let func = match (binop.op.kind, lhs_or_rhs) {
(TokenKind::DblEq, Ok(ValueObj::Bool(true))) => true_comparison,
(TokenKind::DblEq, Ok(ValueObj::Bool(false))) => false_comparison,
(TokenKind::NotEq, Ok(ValueObj::Bool(true))) => false_comparison,
(TokenKind::NotEq, Ok(ValueObj::Bool(false))) => true_comparison,
_ => {
self.lint_bool_comparison(&binop.lhs);
self.lint_bool_comparison(&binop.rhs);
return;
}
};
let expr = if lhs.is_ok_and(|val| val.is_bool()) {
binop.rhs.as_ref()
} else if rhs.is_ok_and(|val| val.is_bool()) {
binop.lhs.as_ref()
} else {
self.lint_bool_comparison(&binop.lhs);
self.lint_bool_comparison(&binop.rhs);
return;
};
let warn = func(expr, self.input(), self.caused_by(), binop.loc());
self.warns.push(warn);
self.lint_bool_comparison(&binop.lhs);
self.lint_bool_comparison(&binop.rhs);
}
_ => self.check_recursively(&Self::lint_bool_comparison, expr),
}
}
...
} I used some conversion functions and helper methods. Please check docs.rs to find out what APIs are available. Or you can implement methods plainly without using helper methods. Creates a warning and adds it to You can apply this rule recursively to the expressions in
pub fn lint(&mut self, src: String) -> Result<CompileWarnings, ErrorArtifact> {
log!(info "Start linting");
let art = self.builder.build(src, "exec")?;
self.warns.extend(art.warns);
for chunk in art.object.module.iter() {
self.lint_too_many_params(chunk);
+ self.lint_bool_comparison(chunk);
}
log!(info "Finished linting");
Ok(self.warns.take())
} That's all! |
TODOs:
The text was updated successfully, but these errors were encountered: