Skip to content

Commit 01ab9fe

Browse files
committed
Auto merge of #4185 - mikerite:outer_expn_info, r=Manishearth
Add OUTER_EXPN_INFO lint changelog: none
2 parents 71be6f6 + b726b41 commit 01ab9fe

File tree

5 files changed

+99
-1
lines changed

5 files changed

+99
-1
lines changed

clippy_lints/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
429429
reg.register_early_lint_pass(box utils::internal_lints::ClippyLintsInternal);
430430
reg.register_late_lint_pass(box utils::internal_lints::CompilerLintFunctions::new());
431431
reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default());
432+
reg.register_late_lint_pass(box utils::internal_lints::OuterExpnInfoPass);
432433
reg.register_late_lint_pass(box utils::inspector::DeepCodeInspector);
433434
reg.register_late_lint_pass(box utils::author::Author);
434435
reg.register_late_lint_pass(box types::Types);
@@ -659,6 +660,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
659660
utils::internal_lints::CLIPPY_LINTS_INTERNAL,
660661
utils::internal_lints::COMPILER_LINT_FUNCTIONS,
661662
utils::internal_lints::LINT_WITHOUT_LINT_PASS,
663+
utils::internal_lints::OUTER_EXPN_INFO,
662664
]);
663665

664666
reg.register_lint_group("clippy::all", Some("clippy"), vec![

clippy_lints/src/utils/internal_lints.rs

+58-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use crate::utils::{match_def_path, match_type, paths, span_help_and_lint, span_lint, walk_ptrs_ty};
1+
use crate::utils::{
2+
match_def_path, match_type, method_calls, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty,
3+
};
24
use if_chain::if_chain;
35
use rustc::hir;
46
use rustc::hir::def::{DefKind, Res};
@@ -7,6 +9,7 @@ use rustc::hir::*;
79
use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass};
810
use rustc::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
911
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
12+
use rustc_errors::Applicability;
1013
use syntax::ast::{Crate as AstCrate, ItemKind, Name};
1114
use syntax::source_map::Span;
1215
use syntax_pos::symbol::LocalInternedString;
@@ -72,6 +75,29 @@ declare_clippy_lint! {
7275
"usage of the lint functions of the compiler instead of the utils::* variant"
7376
}
7477

78+
declare_clippy_lint! {
79+
/// **What it does:** Checks for calls to `cx.outer().expn_info()` and suggests to use
80+
/// the `cx.outer_expn_info()`
81+
///
82+
/// **Why is this bad?** `cx.outer_expn_info()` is faster and more concise.
83+
///
84+
/// **Known problems:** None.
85+
///
86+
/// **Example:**
87+
/// Bad:
88+
/// ```rust
89+
/// expr.span.ctxt().outer().expn_info()
90+
/// ```
91+
///
92+
/// Good:
93+
/// ```rust
94+
/// expr.span.ctxt().outer_expn_info()
95+
/// ```
96+
pub OUTER_EXPN_INFO,
97+
internal,
98+
"using `cx.outer().expn_info()` instead of `cx.outer_expn_info()`"
99+
}
100+
75101
declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);
76102

77103
impl EarlyLintPass for ClippyLintsInternal {
@@ -251,3 +277,34 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions {
251277
}
252278
}
253279
}
280+
281+
pub struct OuterExpnInfoPass;
282+
283+
impl_lint_pass!(OuterExpnInfoPass => [OUTER_EXPN_INFO]);
284+
285+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnInfoPass {
286+
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
287+
let (method_names, arg_lists) = method_calls(expr, 2);
288+
let method_names: Vec<LocalInternedString> = method_names.iter().map(|s| s.as_str()).collect();
289+
let method_names: Vec<&str> = method_names.iter().map(std::convert::AsRef::as_ref).collect();
290+
if_chain! {
291+
if let ["expn_info", "outer"] = method_names.as_slice();
292+
let args = arg_lists[1];
293+
if args.len() == 1;
294+
let self_arg = &args[0];
295+
let self_ty = walk_ptrs_ty(cx.tables.expr_ty(self_arg));
296+
if match_type(cx, self_ty, &paths::SYNTAX_CONTEXT);
297+
then {
298+
span_lint_and_sugg(
299+
cx,
300+
OUTER_EXPN_INFO,
301+
expr.span.trim_start(self_arg.span).unwrap_or(expr.span),
302+
"usage of `outer().expn_info()`",
303+
"try",
304+
".outer_expn_info()".to_string(),
305+
Applicability::MachineApplicable,
306+
);
307+
}
308+
}
309+
}
310+
}

clippy_lints/src/utils/paths.rs

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"];
101101
pub const STD_MEM_TRANSMUTE: [&str; 3] = ["std", "mem", "transmute"];
102102
pub const STD_PTR_NULL: [&str; 3] = ["std", "ptr", "null"];
103103
pub const STRING: [&str; 3] = ["alloc", "string", "String"];
104+
pub const SYNTAX_CONTEXT: [&str; 3] = ["syntax_pos", "hygiene", "SyntaxContext"];
104105
pub const TO_OWNED: [&str; 3] = ["alloc", "borrow", "ToOwned"];
105106
pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"];
106107
pub const TO_STRING: [&str; 3] = ["alloc", "string", "ToString"];

tests/ui/outer_expn_info.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![deny(clippy::internal)]
2+
#![feature(rustc_private)]
3+
4+
#[macro_use]
5+
extern crate rustc;
6+
use rustc::hir::Expr;
7+
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
8+
9+
declare_lint! {
10+
pub TEST_LINT,
11+
Warn,
12+
""
13+
}
14+
15+
declare_lint_pass!(Pass => [TEST_LINT]);
16+
17+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
18+
fn check_expr(&mut self, _cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
19+
let _ = expr.span.ctxt().outer().expn_info();
20+
}
21+
}
22+
23+
fn main() {}

tests/ui/outer_expn_info.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: usage of `outer().expn_info()`
2+
--> $DIR/outer_expn_info.rs:19:33
3+
|
4+
LL | let _ = expr.span.ctxt().outer().expn_info();
5+
| ^^^^^^^^^^^^^^^^^^^^ help: try: `.outer_expn_info()`
6+
|
7+
note: lint level defined here
8+
--> $DIR/outer_expn_info.rs:1:9
9+
|
10+
LL | #![deny(clippy::internal)]
11+
| ^^^^^^^^^^^^^^^^
12+
= note: #[deny(clippy::outer_expn_info)] implied by #[deny(clippy::internal)]
13+
14+
error: aborting due to previous error
15+

0 commit comments

Comments
 (0)