1 use clippy_utils::diagnostics::span_lint_and_note;
2 use clippy_utils::is_lint_allowed;
3 use clippy_utils::macros::root_macro_call_first_node;
4 use rustc_ast::LitKind;
6 use rustc_hir::ExprKind;
7 use rustc_lint::{LateContext, LateLintPass};
8 use rustc_session::{declare_tool_lint, impl_lint_pass};
11 declare_clippy_lint! {
13 /// Checks for the inclusion of large files via `include_bytes!()`
14 /// and `include_str!()`
16 /// ### Why is this bad?
17 /// Including large files can increase the size of the binary
21 /// let included_str = include_str!("very_large_file.txt");
22 /// let included_bytes = include_bytes!("very_large_file.txt");
25 /// Instead, you can load the file at runtime:
29 /// let string = fs::read_to_string("very_large_file.txt")?;
30 /// let bytes = fs::read("very_large_file.txt")?;
32 #[clippy::version = "1.62.0"]
33 pub LARGE_INCLUDE_FILE,
35 "including a large file"
38 pub struct LargeIncludeFile {
42 impl LargeIncludeFile {
44 pub fn new(max_file_size: u64) -> Self {
45 Self { max_file_size }
49 impl_lint_pass!(LargeIncludeFile => [LARGE_INCLUDE_FILE]);
51 impl LateLintPass<'_> for LargeIncludeFile {
52 fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
54 if let Some(macro_call) = root_macro_call_first_node(cx, expr);
55 if !is_lint_allowed(cx, LARGE_INCLUDE_FILE, expr.hir_id);
56 if cx.tcx.is_diagnostic_item(sym::include_bytes_macro, macro_call.def_id)
57 || cx.tcx.is_diagnostic_item(sym::include_str_macro, macro_call.def_id);
58 if let ExprKind::Lit(lit) = &expr.kind;
60 let len = match &lit.node {
62 LitKind::ByteStr(bstr) => bstr.len(),
64 LitKind::Str(sym, _) => sym.as_str().len(),
68 if len as u64 <= self.max_file_size {
76 "attempted to include a large file",
79 "the configuration allows a maximum size of {} bytes",