Skip to content

Commit 444d2c1

Browse files
committed
wip
1 parent fa0f6a8 commit 444d2c1

File tree

4 files changed

+84
-2
lines changed

4 files changed

+84
-2
lines changed

clippy_lints/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ macro_rules! declare_clippy_lint {
165165
$(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
166166
}
167167
};
168+
{ $(#[$attr:meta])* pub $name:tt, internal_collector, $description:tt } => {
169+
declare_tool_lint! {
170+
$(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
171+
}
172+
};
168173
}
169174

170175
mod consts;
@@ -855,6 +860,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
855860
&utils::internal_lints::LINT_WITHOUT_LINT_PASS,
856861
&utils::internal_lints::OUTER_EXPN_EXPN_DATA,
857862
&utils::internal_lints::PRODUCE_ICE,
863+
&utils::internal_lints::LINT_COLLECTOR,
858864
&vec::USELESS_VEC,
859865
&vec_resize_to_zero::VEC_RESIZE_TO_ZERO,
860866
&verbose_file_reads::VERBOSE_FILE_READS,
@@ -878,6 +884,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
878884
store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
879885
store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default());
880886
store.register_late_pass(|| box utils::internal_lints::OuterExpnDataPass);
887+
store.register_late_pass(|| box utils::internal_lints::ClippyLintCollector);
881888
store.register_late_pass(|| box utils::inspector::DeepCodeInspector);
882889
store.register_late_pass(|| box utils::author::Author);
883890
let vec_box_size_threshold = conf.vec_box_size_threshold;

clippy_lints/src/utils/internal_lints.rs

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::utils::SpanlessEq;
22
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
55
};
66
use if_chain::if_chain;
77
use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, NodeId};
@@ -656,3 +656,76 @@ fn suggest_note(
656656
Applicability::MachineApplicable,
657657
);
658658
}
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]);

clippy_lints/src/utils/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ pub fn path_to_res(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<def::Res>
285285
}
286286
}
287287

288+
/// A wrapper around `TypeckTables.qpath_res` that returns `Res::Err` instead of panicking
288289
pub fn qpath_res(cx: &LateContext<'_, '_>, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
289290
match qpath {
290291
hir::QPath::Resolved(_, path) => path.res,

clippy_lints/src/utils/paths.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ pub const ITERATOR: [&str; 5] = ["core", "iter", "traits", "iterator", "Iterator
5757
pub const LATE_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "LateContext"];
5858
pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"];
5959
pub const LINT: [&str; 3] = ["rustc_session", "lint", "Lint"];
60+
pub const APPLICABILITY: [&str; 2] = ["rustc_errors", "Applicability"];
6061
pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"];
6162
pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"];
6263
pub const MEM_MAYBEUNINIT: [&str; 4] = ["core", "mem", "maybe_uninit", "MaybeUninit"];

0 commit comments

Comments
 (0)