From f0d7df7cc39e9d4c93cc6a31afdce3a54481f9ad Mon Sep 17 00:00:00 2001 From: Malena Gruevski <45406876+malenaohl@users.noreply.github.com> Date: Sat, 7 Dec 2024 17:34:24 -0500 Subject: [PATCH] Add function_like_proc_macro_missing lint (#1021) Addresses a checkbox in #946 --------- Co-authored-by: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> --- .../function_like_proc_macro_missing.ron | 42 +++++++++++++++++++ src/query.rs | 1 + .../new/Cargo.toml | 10 +++++ .../new/src/lib.rs | 20 +++++++++ .../old/Cargo.toml | 10 +++++ .../old/src/lib.rs | 23 ++++++++++ .../function_like_proc_macro_missing.snap | 14 +++++++ 7 files changed, 120 insertions(+) create mode 100644 src/lints/function_like_proc_macro_missing.ron create mode 100644 test_crates/function_like_proc_macro_missing/new/Cargo.toml create mode 100644 test_crates/function_like_proc_macro_missing/new/src/lib.rs create mode 100644 test_crates/function_like_proc_macro_missing/old/Cargo.toml create mode 100644 test_crates/function_like_proc_macro_missing/old/src/lib.rs create mode 100644 test_outputs/query_execution/function_like_proc_macro_missing.snap diff --git a/src/lints/function_like_proc_macro_missing.ron b/src/lints/function_like_proc_macro_missing.ron new file mode 100644 index 00000000..19bc61b6 --- /dev/null +++ b/src/lints/function_like_proc_macro_missing.ron @@ -0,0 +1,42 @@ +SemverQuery( + id: "function_like_proc_macro_missing", + human_readable_name: "function-like proc macro removed", + description: "A function-like procedural macro that previously existed has been removed.", + required_update: Major, + lint_level: Deny, + reference_link: Some("https://doc.rust-lang.org/reference/procedural-macros.html#function-like-procedural-macros"), + query: r#" + { + CrateDiff { + baseline { + item { + ... on FunctionLikeProcMacro { + macro_name: name @output @tag + visibility_limit @filter(op: "=", value: ["$public"]) + + # Get span info from the baseline for error reporting + span_: span @optional { + filename @output + begin_line @output + } + } + } + } + + current @fold @transform(op: "count") @filter(op: "=", value: ["$zero"]) { + item { + ... on FunctionLikeProcMacro { + name @filter(op: "=", value: ["%macro_name"]) + } + } + } + } + }"#, + arguments: { + "public": "public", + "zero": 0, + }, + error_message: "A function-like procedural macro has been removed. Any code that invokes this macro will fail to compile.", + per_result_error_template: Some("macro {{macro_name}} in file {{span_filename}}:{{span_begin_line}}"), + witness: None, +) diff --git a/src/query.rs b/src/query.rs index 419b22d7..c20f5178 100644 --- a/src/query.rs +++ b/src/query.rs @@ -1079,6 +1079,7 @@ add_lints!( function_changed_abi, function_const_removed, function_export_name_changed, + function_like_proc_macro_missing, function_missing, function_must_use_added, function_now_doc_hidden, diff --git a/test_crates/function_like_proc_macro_missing/new/Cargo.toml b/test_crates/function_like_proc_macro_missing/new/Cargo.toml new file mode 100644 index 00000000..aab18142 --- /dev/null +++ b/test_crates/function_like_proc_macro_missing/new/Cargo.toml @@ -0,0 +1,10 @@ +[package] +publish = false +name = "function_like_proc_macro_missing" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] diff --git a/test_crates/function_like_proc_macro_missing/new/src/lib.rs b/test_crates/function_like_proc_macro_missing/new/src/lib.rs new file mode 100644 index 00000000..bb139345 --- /dev/null +++ b/test_crates/function_like_proc_macro_missing/new/src/lib.rs @@ -0,0 +1,20 @@ +use proc_macro::TokenStream; + +// make_answer is removed + +// Keep this to verify we don't have false positives +#[proc_macro] +pub fn another_macro(_item: TokenStream) -> TokenStream { + "fn other() -> u32 { 0 }".parse().unwrap() +} + +// Keep other macro types to verify we don't detect their changes +#[proc_macro_derive(MyDerive)] +pub fn my_derive(_item: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_attribute] +pub fn my_attribute(_attr: TokenStream, _item: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/test_crates/function_like_proc_macro_missing/old/Cargo.toml b/test_crates/function_like_proc_macro_missing/old/Cargo.toml new file mode 100644 index 00000000..aab18142 --- /dev/null +++ b/test_crates/function_like_proc_macro_missing/old/Cargo.toml @@ -0,0 +1,10 @@ +[package] +publish = false +name = "function_like_proc_macro_missing" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] diff --git a/test_crates/function_like_proc_macro_missing/old/src/lib.rs b/test_crates/function_like_proc_macro_missing/old/src/lib.rs new file mode 100644 index 00000000..943a22ea --- /dev/null +++ b/test_crates/function_like_proc_macro_missing/old/src/lib.rs @@ -0,0 +1,23 @@ +use proc_macro::TokenStream; + +#[proc_macro] +pub fn make_answer(_item: TokenStream) -> TokenStream { + "fn answer() -> u32 { 42 }".parse().unwrap() +} + +// Will keep this one to ensure we don't have false positives +#[proc_macro] +pub fn another_macro(_item: TokenStream) -> TokenStream { + "fn other() -> u32 { 0 }".parse().unwrap() +} + +// Other kinds of proc macros that should not trigger this lint +#[proc_macro_derive(MyDerive)] +pub fn my_derive(_item: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_attribute] +pub fn my_attribute(_attr: TokenStream, _item: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/test_outputs/query_execution/function_like_proc_macro_missing.snap b/test_outputs/query_execution/function_like_proc_macro_missing.snap new file mode 100644 index 00000000..49b3d242 --- /dev/null +++ b/test_outputs/query_execution/function_like_proc_macro_missing.snap @@ -0,0 +1,14 @@ +--- +source: src/query.rs +expression: "&query_execution_results" +snapshot_kind: text +--- +{ + "./test_crates/function_like_proc_macro_missing/": [ + { + "macro_name": String("make_answer"), + "span_begin_line": Uint64(4), + "span_filename": String("src/lib.rs"), + }, + ], +}