|
1 | 1 | use crate::utils::SpanlessEq;
|
2 | 2 | use crate::utils::{
|
3 |
| - is_expn_of, match_def_path, match_qpath, match_type, method_calls, paths, run_lints, snippet, span_lint, |
4 |
| - span_lint_and_help, span_lint_and_sugg, walk_ptrs_ty, |
| 3 | + is_expn_of, match_def_path, match_qpath, match_type, method_calls, paths, snippet, span_lint, span_lint_and_help, |
| 4 | + span_lint_and_sugg, walk_ptrs_ty, last_path_segment, match_function_call |
5 | 5 | };
|
6 | 6 | use if_chain::if_chain;
|
7 | 7 | use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, NodeId};
|
@@ -656,3 +656,76 @@ fn suggest_note(
|
656 | 656 | Applicability::MachineApplicable,
|
657 | 657 | );
|
658 | 658 | }
|
| 659 | + |
| 660 | +declare_clippy_lint! { |
| 661 | + /// **What it does:** Collects data about all our lints into a JSON file |
| 662 | + /// |
| 663 | + /// |
| 664 | + /// |
| 665 | + /// **Why is this bad?** TODO |
| 666 | + /// |
| 667 | + /// **Known problems:** None. |
| 668 | + /// |
| 669 | + /// **Example:** TODO |
| 670 | + pub LINT_COLLECTOR, |
| 671 | + // Don't want to run this as part of the dogfood tests, so separate lint group |
| 672 | + internal_collector, |
| 673 | + "not a lint. collects all lints into a JSON file" |
| 674 | +} |
| 675 | + |
| 676 | +declare_lint_pass!(ClippyLintCollector => [LINT_COLLECTOR]); |
| 677 | + |
| 678 | +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ClippyLintCollector { |
| 679 | + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { |
| 680 | + if_chain! { |
| 681 | + if let Some(args) = match_function_call(cx, expr, &["clippy_lints", "utils", "diagnostics", "span_lint_and_sugg"]); |
| 682 | + let (lint_name, applicability) = lint_of_diagnostic_emission(cx, args); |
| 683 | + |
| 684 | + then { |
| 685 | + // dbg!(&lint_name); |
| 686 | + // dbg!(&applicability); |
| 687 | + |
| 688 | + span_lint(cx, LINT_COLLECTOR, expr.span, &format!("here: span_lint_and_sugg")); |
| 689 | + } |
| 690 | + } |
| 691 | + } |
| 692 | +} |
| 693 | + |
| 694 | +/// Iterate over the arguments of e.g. `span_lint_and_sugg` and find the lint |
| 695 | +fn lint_of_diagnostic_emission<'a, 'tcx>( |
| 696 | + cx: &LateContext<'a, 'tcx>, |
| 697 | + args: &[hir::Expr<'_>], |
| 698 | +) -> (Option<Symbol>, Option<Symbol>) { |
| 699 | + let mut lint_name: Option<Symbol> = None; |
| 700 | + let mut applicability: Option<Symbol> = None; |
| 701 | + for arg in args { |
| 702 | + let arg_ty = walk_ptrs_ty(cx.tables.expr_ty(&arg)); |
| 703 | + |
| 704 | + if match_type(cx, arg_ty, &paths::LINT) { |
| 705 | + // If we found the lint arg, extract the lint name |
| 706 | + if let ExprKind::Path(ref lint_path) = arg.kind { |
| 707 | + lint_name = Some(last_path_segment(lint_path).ident.name) |
| 708 | + } |
| 709 | + } |
| 710 | + if match_type(cx, arg_ty, &paths::APPLICABILITY) { |
| 711 | + if let ExprKind::Path(ref path) = arg.kind { |
| 712 | + // TODO: handle variables of Applicability |
| 713 | + dbg!(&arg.kind); |
| 714 | + dbg!(&arg_ty); |
| 715 | + // dbg!(&path); |
| 716 | + applicability = Some(last_path_segment(path).ident.name) |
| 717 | + } |
| 718 | + } |
| 719 | + } |
| 720 | + (lint_name, applicability) |
| 721 | +} |
| 722 | +// todo: re-use `declared_lints` somehow |
| 723 | +// - check for Applicability::MachineApplicable |
| 724 | +// - start with span_lint_and_sugg |
| 725 | + |
| 726 | +// first todo: |
| 727 | +// find span_lint_and_sugg calls with Applicability::MachineApplicable |
| 728 | +// and print the name of the lint |
| 729 | + |
| 730 | +// todo: `args[1]` is brittle. might be better to check each arg: |
| 731 | +// let lint_ty = cx.tables.expr_ty(&args[i]); |
0 commit comments