Skip to content

Commit b8cb469

Browse files
committed
Use SpanlessEq to test for span equality.
1 parent 1cee809 commit b8cb469

File tree

5 files changed

+248
-184
lines changed

5 files changed

+248
-184
lines changed

clippy_lints/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,7 +1021,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10211021
store.register_late_pass(|| box wildcard_imports::WildcardImports);
10221022
store.register_early_pass(|| box macro_use::MacroUseImports);
10231023
store.register_late_pass(|| box verbose_file_reads::VerboseFileReads);
1024-
store.register_early_pass(|| box utils::internal_lints::CollapsibleCalls);
1024+
store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls);
10251025

10261026
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
10271027
LintId::of(&arithmetic::FLOAT_ARITHMETIC),
@@ -1125,13 +1125,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11251125

11261126
store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![
11271127
LintId::of(&utils::internal_lints::CLIPPY_LINTS_INTERNAL),
1128+
LintId::of(&utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS),
11281129
LintId::of(&utils::internal_lints::COMPILER_LINT_FUNCTIONS),
11291130
LintId::of(&utils::internal_lints::DEFAULT_LINT),
11301131
LintId::of(&utils::internal_lints::LINT_WITHOUT_LINT_PASS),
11311132
LintId::of(&utils::internal_lints::OUTER_EXPN_EXPN_DATA),
11321133
LintId::of(&utils::internal_lints::PRODUCE_ICE),
1133-
LintId::of(&utils::internal_lints::DEFAULT_LINT),
1134-
LintId::of(&utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS),
11351134
]);
11361135

11371136
store.register_group(true, "clippy::all", Some("clippy"), vec![

clippy_lints/src/utils/internal_lints.rs

Lines changed: 127 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
1+
use crate::utils::SpanlessEq;
12
use crate::utils::{
2-
is_expn_of, match_def_path, match_type, method_calls, paths, span_lint, span_lint_and_help, span_lint_and_sugg,
3-
walk_ptrs_ty, snippet as other_snippet, match_path_ast
3+
is_expn_of, match_def_path, match_qpath, match_type, method_calls, paths, snippet as other_snippet, span_lint,
4+
span_lint_and_help, span_lint_and_sugg, walk_ptrs_ty,
45
};
56
use if_chain::if_chain;
67
use rustc::hir::map::Map;
7-
use rustc_ast::ast;
8-
use rustc_ast::ast::{Crate as AstCrate, Expr as AstExpr, ItemKind, LitKind, Name, NodeId};
8+
use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, Name, NodeId};
99
use rustc_ast::visit::FnKind;
10-
use rustc_ast::ptr::P;
1110
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1211
use rustc_errors::Applicability;
1312
use rustc_hir as hir;
1413
use rustc_hir::def::{DefKind, Res};
1514
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
16-
use rustc_hir::{Crate, Expr, ExprKind, HirId, Item, MutTy, Mutability, Path, Ty, TyKind};
15+
use rustc_hir::{Crate, Expr, ExprKind, HirId, Item, MutTy, Mutability, Path, StmtKind, Ty, TyKind};
1716
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
1817
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
1918
use rustc_span::source_map::{Span, Spanned};
2019
use rustc_span::symbol::SymbolStr;
2120

22-
2321
use std::borrow::Cow;
2422

2523
declare_clippy_lint! {
@@ -176,7 +174,7 @@ impl EarlyLintPass for ClippyLintsInternal {
176174
CLIPPY_LINTS_INTERNAL,
177175
item.span,
178176
"this constant should be before the previous constant due to lexical \
179-
ordering",
177+
ordering",
180178
);
181179
}
182180
}
@@ -206,8 +204,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass {
206204
if let ExprKind::AddrOf(_, _, ref inner_exp) = expr.kind;
207205
if let ExprKind::Struct(_, ref fields, _) = inner_exp.kind;
208206
let field = fields.iter()
209-
.find(|f| f.ident.as_str() == "desc")
210-
.expect("lints must have a description field");
207+
.find(|f| f.ident.as_str() == "desc")
208+
.expect("lints must have a description field");
211209
if let ExprKind::Lit(Spanned {
212210
node: LitKind::Str(ref sym, _),
213211
..
@@ -343,7 +341,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions {
343341
if let Some(sugg) = self.map.get(&*fn_name.as_str());
344342
let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
345343
if match_type(cx, ty, &paths::EARLY_CONTEXT)
346-
|| match_type(cx, ty, &paths::LATE_CONTEXT);
344+
|| match_type(cx, ty, &paths::LATE_CONTEXT);
347345
then {
348346
span_lint_and_help(
349347
cx,
@@ -405,175 +403,162 @@ fn is_trigger_fn(fn_kind: FnKind<'_>) -> bool {
405403

406404
declare_lint_pass!(CollapsibleCalls => [COLLAPSIBLE_SPAN_LINT_CALLS]);
407405

408-
impl EarlyLintPass for CollapsibleCalls {
409-
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &AstExpr) {
410-
use ast::{StmtKind, ExprKind};
411-
406+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CollapsibleCalls {
407+
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) {
412408
if_chain! {
413409
if let ExprKind::Call(ref func, ref and_then_args) = expr.kind;
414-
if let ExprKind::Path(None, ref path) = func.kind;
415-
if match_path_ast(path, &["span_lint_and_then"]);
410+
if let ExprKind::Path(ref path) = func.kind;
411+
if match_qpath(path, &["span_lint_and_then"]);
416412
if and_then_args.len() == 5;
417-
if let ExprKind::Closure(_, _, _, _, block, _) = &and_then_args[4].kind;
418-
if let ExprKind::Block(block, _) = &block.kind;
413+
if let ExprKind::Closure(_, _, body_id, _, _) = &and_then_args[4].kind;
414+
if let body = cx.tcx.hir().body(*body_id);
415+
if let ExprKind::Block(block, _) = &body.value.kind;
419416
let stmts = &block.stmts;
420417
if stmts.len() == 1;
421-
if let StmtKind::Expr(only_expr) = &stmts[0].kind;
422-
if let ExprKind::MethodCall(ref ps, ref span_call_args) = &only_expr.kind;
423-
let and_then_args = get_and_then_args(cx, and_then_args);
418+
//
419+
if let StmtKind::Semi(only_expr) = &stmts[0].kind;
420+
if let ExprKind::MethodCall(ref ps, _, ref span_call_args) = &only_expr.kind;
421+
let and_then_snippets = get_and_then_snippets(cx, and_then_args);
422+
let mut sle = SpanlessEq::new(cx).ignore_fn();
424423
then {
425424
match &*ps.ident.as_str() {
426-
"span_suggestion" =>
427-
suggest_span_suggestion(cx, expr, and_then_args, suggestion_args(cx, span_call_args)),
428-
"span_help" =>
429-
suggest_span_help(cx, expr, and_then_args, help_args(cx, span_call_args)),
430-
"span_note" =>
431-
suggest_span_note(cx, expr, and_then_args, note_args(cx, span_call_args)),
425+
"span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => {
426+
suggest_suggestion(cx, expr, and_then_snippets, span_suggestion_snippets(cx, span_call_args));
427+
},
428+
"span_suggestion" => {
429+
dbg!(&span_call_args[0]);
430+
dbg!(&span_call_args[1]);
431+
dbg!(&span_call_args[2]);
432+
}
433+
"span_help" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => {
434+
let help_snippet = snippet(cx, span_call_args[2].span);
435+
suggest_help(cx, expr, and_then_snippets, help_snippet);
436+
},
437+
"span_note" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => {
438+
let note_snippet = snippet(cx, span_call_args[2].span);
439+
suggest_note(cx, expr, and_then_snippets, note_snippet);
440+
},
441+
"help" => {
442+
let help_snippet = snippet(cx, span_call_args[1].span);
443+
suggest_help(cx, expr, and_then_snippets, help_snippet);
444+
}
445+
"note" => {
446+
let note_snippet = snippet(cx, span_call_args[1].span);
447+
suggest_note(cx, expr, and_then_snippets, note_snippet);
448+
}
432449
_ => (),
433450
}
434451
}
435452
}
436453
}
437454
}
438455

439-
struct AndThenArgs<'a> {
456+
struct AndThenSnippets<'a> {
440457
cx: Cow<'a, str>,
441458
lint: Cow<'a, str>,
442459
span: Cow<'a, str>,
443460
msg: Cow<'a, str>,
444461
}
445462

446-
fn get_and_then_args<'a>(cx: &EarlyContext<'_>, and_then_args: &Vec<P<AstExpr>>) -> AndThenArgs<'a>{
447-
let cx_snippet = snippet(cx, and_then_args[0].span);
448-
let lint_snippet= snippet(cx, and_then_args[1].span);
449-
let span_snippet = snippet(cx, and_then_args[2].span);
450-
let msg_snippet= snippet(cx, and_then_args[3].span);
463+
fn get_and_then_snippets<'a, 'hir>(
464+
cx: &LateContext<'_, '_>,
465+
and_then_snippets: &'hir [Expr<'hir>],
466+
) -> AndThenSnippets<'a> {
467+
let cx_snippet = snippet(cx, and_then_snippets[0].span);
468+
let lint_snippet = snippet(cx, and_then_snippets[1].span);
469+
let span_snippet = snippet(cx, and_then_snippets[2].span);
470+
let msg_snippet = snippet(cx, and_then_snippets[3].span);
451471

452-
AndThenArgs {
472+
AndThenSnippets {
453473
cx: cx_snippet,
454474
lint: lint_snippet,
455475
span: span_snippet,
456476
msg: msg_snippet,
457477
}
458478
}
459479

460-
struct SuggestionArgs<'a> {
461-
span: Cow<'a, str>,
480+
struct SpanSuggestionSnippets<'a> {
462481
help: Cow<'a, str>,
463482
sugg: Cow<'a, str>,
464483
applicability: Cow<'a, str>,
465484
}
466485

467-
fn suggestion_args<'a>(cx: &EarlyContext<'_>, span_call_args: &Vec<P<AstExpr>>) -> SuggestionArgs<'a> {
468-
let span_snippet_of_span_call = snippet(cx, span_call_args[0].span);
469-
let help_snippet = snippet(cx, span_call_args[1].span);
470-
let sugg_snippet = snippet(cx, span_call_args[2].span);
471-
let applicability_snippet = snippet(cx, span_call_args[3].span);
486+
fn span_suggestion_snippets<'a, 'hir>(
487+
cx: &LateContext<'_, '_>,
488+
span_call_args: &'hir [Expr<'hir>],
489+
) -> SpanSuggestionSnippets<'a> {
490+
let help_snippet = snippet(cx, span_call_args[2].span);
491+
let sugg_snippet = snippet(cx, span_call_args[3].span);
492+
let applicability_snippet = snippet(cx, span_call_args[4].span);
472493

473-
SuggestionArgs {
474-
span: span_snippet_of_span_call,
494+
SpanSuggestionSnippets {
475495
help: help_snippet,
476496
sugg: sugg_snippet,
477497
applicability: applicability_snippet,
478498
}
479499
}
480500

481-
fn suggest_span_suggestion(cx: &EarlyContext<'_>, expr: &AstExpr, and_then_args: AndThenArgs<'_>, suggestion_args: SuggestionArgs<'_>) {
482-
if and_then_args.span == suggestion_args.span {
483-
println!("suggestion true");
484-
span_lint_and_sugg (
485-
cx,
486-
COLLAPSIBLE_SPAN_LINT_CALLS,
487-
expr.span,
488-
"this call is collapsible",
489-
"collapse into",
490-
format!(
491-
"span_lint_and_sugg({}, {}, {}, {}, {}, {},{})",
492-
and_then_args.cx,
493-
and_then_args.lint,
494-
and_then_args.span,
495-
and_then_args.msg,
496-
suggestion_args.help,
497-
suggestion_args.sugg,
498-
suggestion_args.applicability
499-
),
500-
Applicability::MachineApplicable
501-
);
502-
}
503-
}
504-
505-
struct HelpArgs<'a> {
506-
span: Cow<'a, str>,
507-
help: Cow<'a, str>,
508-
}
509-
510-
fn help_args<'a>(cx: &EarlyContext<'_>, span_call_args: &Vec<P<AstExpr>>) -> HelpArgs<'a>{
511-
let span_snippet_of_span_call = snippet(cx, span_call_args[0].span);
512-
let help_snippet = snippet(cx, span_call_args[1].span);
513-
514-
HelpArgs {
515-
span: span_snippet_of_span_call,
516-
help: help_snippet,
517-
}
518-
}
519-
520-
fn suggest_span_help(cx: &EarlyContext<'_>, expr: &AstExpr, and_then_args: AndThenArgs<'_>, help_args: HelpArgs<'_>) {
521-
if and_then_args.span == help_args.span {
522-
span_lint_and_sugg(
523-
cx,
524-
COLLAPSIBLE_SPAN_LINT_CALLS,
525-
expr.span,
526-
"this call is collapsible",
527-
"collapse into",
528-
format!(
529-
"span_lint_and_help({}, {}, {}, {},{})",
530-
and_then_args.cx,
531-
and_then_args.lint,
532-
and_then_args.span,
533-
and_then_args.msg,
534-
help_args.help
535-
),
536-
Applicability::MachineApplicable
537-
);
538-
}
539-
}
540-
541-
struct NoteArgs<'a> {
542-
span: Cow<'a, str>,
543-
note: Cow<'a, str>,
544-
}
545-
546-
fn note_args<'a>(cx: &EarlyContext<'_>, span_call_args: &Vec<P<AstExpr>>) -> NoteArgs<'a> {
547-
let span_snippet_of_span_call = snippet(cx, span_call_args[0].span);
548-
let note_snippet = snippet(cx, span_call_args[1].span);
549-
550-
NoteArgs {
551-
span: span_snippet_of_span_call,
552-
note: note_snippet,
553-
}
554-
}
555-
556-
fn suggest_span_note(cx: &EarlyContext<'_>, expr: &AstExpr, and_then_args: AndThenArgs<'_> , note_args: NoteArgs<'_> ) {
557-
if and_then_args.span == note_args.span {
558-
span_lint_and_sugg(
559-
cx,
560-
COLLAPSIBLE_SPAN_LINT_CALLS,
561-
expr.span,
562-
"this call is collspible",
563-
"collapse into",
564-
format!(
565-
"span_lint_and_note({},{}, {}, {}, {})",
566-
and_then_args.cx,
567-
and_then_args.lint,
568-
and_then_args.span,
569-
and_then_args.msg,
570-
note_args.note
571-
),
572-
Applicability::MachineApplicable
573-
);
574-
}
575-
}
576-
577-
fn snippet<'a>(cx: &EarlyContext<'_>, span: Span) -> Cow<'a, str> {
578-
other_snippet(cx, span, "Should not be")
501+
fn suggest_suggestion(
502+
cx: &LateContext<'_, '_>,
503+
expr: &Expr<'_>,
504+
and_then_snippets: AndThenSnippets<'_>,
505+
span_suggestion_snippets: SpanSuggestionSnippets<'_>,
506+
) {
507+
span_lint_and_sugg(
508+
cx,
509+
COLLAPSIBLE_SPAN_LINT_CALLS,
510+
expr.span,
511+
"this call is collapsible",
512+
"collapse into",
513+
format!(
514+
"span_lint_and_sugg({}, {}, {}, {}, {}, {}, {})",
515+
and_then_snippets.cx,
516+
and_then_snippets.lint,
517+
and_then_snippets.span,
518+
and_then_snippets.msg,
519+
span_suggestion_snippets.help,
520+
span_suggestion_snippets.sugg,
521+
span_suggestion_snippets.applicability
522+
),
523+
Applicability::MachineApplicable,
524+
);
525+
}
526+
527+
fn suggest_help(cx: &LateContext<'_, '_>, expr: &Expr<'_>, and_then_snippets: AndThenSnippets<'_>, help: Cow<'_, str>) {
528+
span_lint_and_sugg(
529+
cx,
530+
COLLAPSIBLE_SPAN_LINT_CALLS,
531+
expr.span,
532+
"this call is collapsible",
533+
"collapse into",
534+
format!(
535+
"span_lint_and_help({}, {}, {}, {}, {})",
536+
and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg, help
537+
),
538+
Applicability::MachineApplicable,
539+
);
540+
}
541+
542+
fn suggest_note(cx: &LateContext<'_, '_>, expr: &Expr<'_>, and_then_snippets: AndThenSnippets<'_>, note: Cow<'_, str>) {
543+
span_lint_and_sugg(
544+
cx,
545+
COLLAPSIBLE_SPAN_LINT_CALLS,
546+
expr.span,
547+
"this call is collspible",
548+
"collapse into",
549+
format!(
550+
"span_lint_and_note({}, {}, {}, {}, {}, {})",
551+
and_then_snippets.cx,
552+
and_then_snippets.lint,
553+
and_then_snippets.span,
554+
and_then_snippets.msg,
555+
and_then_snippets.span,
556+
note
557+
),
558+
Applicability::MachineApplicable,
559+
);
560+
}
561+
562+
fn snippet<'a>(cx: &LateContext<'_, '_>, span: Span) -> Cow<'a, str> {
563+
other_snippet(cx, span, "Should not be this snippet")
579564
}

0 commit comments

Comments
 (0)