2015-08-11 13:53:50 -05:00
|
|
|
use syntax::ast::*;
|
2015-08-16 01:54:43 -05:00
|
|
|
use rustc::lint::*;
|
2015-08-11 13:53:50 -05:00
|
|
|
use rustc::middle::ty;
|
|
|
|
|
2015-08-21 12:00:33 -05:00
|
|
|
use utils::{span_lint, match_type, walk_ptrs_ty};
|
2015-08-21 11:48:36 -05:00
|
|
|
use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH};
|
2015-08-11 13:53:50 -05:00
|
|
|
|
|
|
|
#[derive(Copy,Clone)]
|
|
|
|
pub struct MethodsPass;
|
|
|
|
|
2015-08-14 00:17:10 -05:00
|
|
|
declare_lint!(pub OPTION_UNWRAP_USED, Allow,
|
2015-08-13 03:32:35 -05:00
|
|
|
"using `Option.unwrap()`, which should at least get a better message using `expect()`");
|
2015-08-11 13:53:50 -05:00
|
|
|
declare_lint!(pub RESULT_UNWRAP_USED, Allow,
|
2015-08-13 03:32:35 -05:00
|
|
|
"using `Result.unwrap()`, which might be better handled");
|
2015-08-12 06:58:55 -05:00
|
|
|
declare_lint!(pub STR_TO_STRING, Warn,
|
2015-08-13 03:32:35 -05:00
|
|
|
"using `to_string()` on a str, which should be `to_owned()`");
|
2015-08-12 10:02:49 -05:00
|
|
|
declare_lint!(pub STRING_TO_STRING, Warn,
|
2015-08-13 03:32:35 -05:00
|
|
|
"calling `String.to_string()` which is a no-op");
|
2015-08-11 13:53:50 -05:00
|
|
|
|
|
|
|
impl LintPass for MethodsPass {
|
|
|
|
fn get_lints(&self) -> LintArray {
|
2015-08-12 10:02:49 -05:00
|
|
|
lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING)
|
2015-08-11 13:53:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
|
|
|
|
if let ExprMethodCall(ref ident, _, ref args) = expr.node {
|
2015-08-25 07:41:35 -05:00
|
|
|
let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(&args[0]));
|
2015-08-11 13:53:50 -05:00
|
|
|
if ident.node.name == "unwrap" {
|
2015-08-21 12:00:33 -05:00
|
|
|
if match_type(cx, obj_ty, &OPTION_PATH) {
|
|
|
|
span_lint(cx, OPTION_UNWRAP_USED, expr.span,
|
|
|
|
"used unwrap() on an Option value. If you don't want \
|
|
|
|
to handle the None case gracefully, consider using \
|
|
|
|
expect() to provide a better panic message");
|
|
|
|
} else if match_type(cx, obj_ty, &RESULT_PATH) {
|
|
|
|
span_lint(cx, RESULT_UNWRAP_USED, expr.span,
|
|
|
|
"used unwrap() on a Result value. Graceful handling \
|
|
|
|
of Err values is preferred");
|
2015-08-11 13:53:50 -05:00
|
|
|
}
|
|
|
|
}
|
2015-08-12 06:58:55 -05:00
|
|
|
else if ident.node.name == "to_string" {
|
2015-08-21 12:00:33 -05:00
|
|
|
if obj_ty.sty == ty::TyStr {
|
2015-08-12 06:58:55 -05:00
|
|
|
span_lint(cx, STR_TO_STRING, expr.span, "`str.to_owned()` is faster");
|
2015-08-21 12:00:33 -05:00
|
|
|
} else if match_type(cx, obj_ty, &STRING_PATH) {
|
2015-08-25 05:45:52 -05:00
|
|
|
span_lint(cx, STRING_TO_STRING, expr.span, "`String.to_string()` is a no-op; use \
|
|
|
|
`clone()` to make a copy");
|
2015-08-12 10:02:49 -05:00
|
|
|
}
|
2015-08-12 06:58:55 -05:00
|
|
|
}
|
2015-08-11 13:53:50 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|