From 817749426c03d97e20f35be9d88e5f2648d88dbe Mon Sep 17 00:00:00 2001 From: Malena Gruevski <45406876+malenaohl@users.noreply.github.com> Date: Sat, 7 Dec 2024 22:40:57 -0500 Subject: [PATCH] Add new lint macro_no_longer_exported (#1031) Addresses checkbox in https://github.com/obi1kenobi/cargo-semver-checks/issues/946 --------- Co-authored-by: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> --- src/lints/macro_no_longer_exported.ron | 45 +++++++++++++++++++ src/query.rs | 1 + .../macro_no_longer_exported/new/Cargo.toml | 7 +++ .../macro_no_longer_exported/new/src/lib.rs | 22 +++++++++ .../macro_no_longer_exported/old/Cargo.toml | 7 +++ .../macro_no_longer_exported/old/src/lib.rs | 20 +++++++++ .../macro_no_longer_exported.snap | 28 ++++++++++++ .../query_execution/macro_now_doc_hidden.snap | 7 +++ .../witnesses/macro_no_longer_exported.snap | 20 +++++++++ 9 files changed, 157 insertions(+) create mode 100644 src/lints/macro_no_longer_exported.ron create mode 100644 test_crates/macro_no_longer_exported/new/Cargo.toml create mode 100644 test_crates/macro_no_longer_exported/new/src/lib.rs create mode 100644 test_crates/macro_no_longer_exported/old/Cargo.toml create mode 100644 test_crates/macro_no_longer_exported/old/src/lib.rs create mode 100644 test_outputs/query_execution/macro_no_longer_exported.snap create mode 100644 test_outputs/witnesses/macro_no_longer_exported.snap diff --git a/src/lints/macro_no_longer_exported.ron b/src/lints/macro_no_longer_exported.ron new file mode 100644 index 00000000..3a23b557 --- /dev/null +++ b/src/lints/macro_no_longer_exported.ron @@ -0,0 +1,45 @@ +SemverQuery( + id: "macro_no_longer_exported", + human_readable_name: "macro is no longer exported", + description: "A macro_rules macro that was previously exported is no longer exported.", + required_update: Major, + lint_level: Deny, + reference_link: Some("https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope"), + query: r#" + { + CrateDiff { + baseline { + item { + ... on Macro { + name @output @tag + public_api_eligible @filter(op: "=", value: ["$true"]) + } + } + } + current { + item { + ... on Macro { + name @filter(op: "=", value: ["%name"]) + # Check the macro still exists but is no longer public API + # and isn't doc(hidden) (which would be caught by another lint) + public_api_eligible @filter(op: "!=", value: ["$true"]) + doc_hidden @filter(op: "!=", value: ["$true"]) + + span_: span @optional { + filename @output + begin_line @output + } + } + } + } + } + }"#, + arguments: { + "true": true, + }, + error_message: "A macro that was previously exported with #[macro_export] is no longer exported. This breaks downstream code that used the macro.", + per_result_error_template: Some("macro {{name}} in {{span_filename}}:{{span_begin_line}}"), + witness: Some(( + hint_template: r#"{{name}}!(...);"#, + )), +) diff --git a/src/query.rs b/src/query.rs index 69efa0cf..c865b6b1 100644 --- a/src/query.rs +++ b/src/query.rs @@ -1095,6 +1095,7 @@ add_lints!( inherent_method_must_use_added, inherent_method_now_doc_hidden, inherent_method_unsafe_added, + macro_no_longer_exported, macro_now_doc_hidden, method_parameter_count_changed, module_missing, diff --git a/test_crates/macro_no_longer_exported/new/Cargo.toml b/test_crates/macro_no_longer_exported/new/Cargo.toml new file mode 100644 index 00000000..fbf1dffb --- /dev/null +++ b/test_crates/macro_no_longer_exported/new/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "macro_no_longer_exported" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/macro_no_longer_exported/new/src/lib.rs b/test_crates/macro_no_longer_exported/new/src/lib.rs new file mode 100644 index 00000000..1e27c54f --- /dev/null +++ b/test_crates/macro_no_longer_exported/new/src/lib.rs @@ -0,0 +1,22 @@ +// No longer exported but not hidden - should trigger +macro_rules! example_macro { + () => { + println!("Hello from macro!"); + }; +} + +// No longer exported but is hidden - should NOT trigger (caught by different lint) +#[doc(hidden)] +macro_rules! will_be_hidden { + () => { + println!("Will become hidden"); + }; +} + +// Now exported - should not trigger +#[macro_export] +macro_rules! internal_macro { + () => { + println!("Internal macro"); + }; +} diff --git a/test_crates/macro_no_longer_exported/old/Cargo.toml b/test_crates/macro_no_longer_exported/old/Cargo.toml new file mode 100644 index 00000000..fbf1dffb --- /dev/null +++ b/test_crates/macro_no_longer_exported/old/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "macro_no_longer_exported" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/macro_no_longer_exported/old/src/lib.rs b/test_crates/macro_no_longer_exported/old/src/lib.rs new file mode 100644 index 00000000..37e278ff --- /dev/null +++ b/test_crates/macro_no_longer_exported/old/src/lib.rs @@ -0,0 +1,20 @@ +#[macro_export] +macro_rules! example_macro { + () => { + println!("Hello from macro!"); + }; +} + +#[macro_export] +macro_rules! will_be_hidden { + () => { + println!("Will become hidden"); + }; +} + +// Internal macro - should not trigger when made public +macro_rules! internal_macro { + () => { + println!("Internal macro"); + }; +} diff --git a/test_outputs/query_execution/macro_no_longer_exported.snap b/test_outputs/query_execution/macro_no_longer_exported.snap new file mode 100644 index 00000000..5969578d --- /dev/null +++ b/test_outputs/query_execution/macro_no_longer_exported.snap @@ -0,0 +1,28 @@ +--- +source: src/query.rs +expression: "&query_execution_results" +snapshot_kind: text +--- +{ + "./test_crates/declarative_macro_missing/": [ + { + "name": String("will_no_longer_be_exported"), + "span_begin_line": Uint64(1), + "span_filename": String("src/lib.rs"), + }, + ], + "./test_crates/macro_no_longer_exported/": [ + { + "name": String("example_macro"), + "span_begin_line": Uint64(2), + "span_filename": String("src/lib.rs"), + }, + ], + "./test_crates/macro_now_doc_hidden/": [ + { + "name": String("becomes_non_exported"), + "span_begin_line": Uint64(36), + "span_filename": String("src/lib.rs"), + }, + ], +} diff --git a/test_outputs/query_execution/macro_now_doc_hidden.snap b/test_outputs/query_execution/macro_now_doc_hidden.snap index a84ff171..0cf24726 100644 --- a/test_outputs/query_execution/macro_now_doc_hidden.snap +++ b/test_outputs/query_execution/macro_now_doc_hidden.snap @@ -11,6 +11,13 @@ snapshot_kind: text "span_filename": String("src/lib.rs"), }, ], + "./test_crates/macro_no_longer_exported/": [ + { + "name": String("will_be_hidden"), + "span_begin_line": Uint64(10), + "span_filename": String("src/lib.rs"), + }, + ], "./test_crates/macro_now_doc_hidden/": [ { "name": String("will_be_hidden"), diff --git a/test_outputs/witnesses/macro_no_longer_exported.snap b/test_outputs/witnesses/macro_no_longer_exported.snap new file mode 100644 index 00000000..3665672b --- /dev/null +++ b/test_outputs/witnesses/macro_no_longer_exported.snap @@ -0,0 +1,20 @@ +--- +source: src/query.rs +description: "Lint `macro_no_longer_exported` did not have the expected witness output.\nSee https://github.com/obi1kenobi/cargo-semver-checks/blob/main/CONTRIBUTING.md#testing-witnesses\nfor more information." +expression: "&actual_witnesses" +snapshot_kind: text +--- +[["./test_crates/declarative_macro_missing/"]] +filename = 'src/lib.rs' +begin_line = 1 +hint = 'will_no_longer_be_exported!(...);' + +[["./test_crates/macro_no_longer_exported/"]] +filename = 'src/lib.rs' +begin_line = 2 +hint = 'example_macro!(...);' + +[["./test_crates/macro_now_doc_hidden/"]] +filename = 'src/lib.rs' +begin_line = 36 +hint = 'becomes_non_exported!(...);'