From 04654fe9de8cb67e32320d301f3f4dd04498092d Mon Sep 17 00:00:00 2001 From: Wojciech Graj Date: Thu, 21 May 2026 14:16:45 +0200 Subject: [PATCH] Implement quote::ToTokens for FoundCrate This crate's primary use-case is to find the name of a crate so it can be used in generated code. This code will almost always be generated using the `quote` macro, meaning you'll pretty much always need to do the conversion shown in the README: match found_crate { FoundCrate::Itself => quote!( crate::Something ), FoundCrate::Name(name) => { let ident = Ident::new(&name, Span::call_site()); quote!( #ident::Something ) } }; This commit implements quote::ToTokens, so you can use FoundCrate directly in the quote macro. --- .github/workflows/rust.yml | 7 ++++--- Cargo.toml | 5 +++++ src/lib.rs | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 94774d8..5e5e556 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -17,6 +17,7 @@ jobs: - uses: actions/checkout@v2 - uses: dtolnay/rust-toolchain@stable - run: cargo test --all + - run: cargo test --all --all-features msrv: name: "Check MSRV: 1.82.0" runs-on: ubuntu-latest @@ -29,7 +30,7 @@ jobs: toolchain: 1.82.0 # MSRV - uses: Swatinem/rust-cache@v2 - name: Default features - run: cargo test --all + run: cargo test --all --all-features rustfmt: name: rustfmt runs-on: ubuntu-latest @@ -43,7 +44,7 @@ jobs: components: rustfmt - uses: Swatinem/rust-cache@v2 - name: Check formatting - run: cargo fmt --all -- --check + run: cargo fmt --all --all-features -- --check clippy: name: cargo clippy (forbidden methods) runs-on: ubuntu-latest @@ -52,4 +53,4 @@ jobs: - uses: dtolnay/rust-toolchain@stable # We just use clippy to spot forbidden methods. # We disable the default lint set which has much questionable output. - - run: cargo clippy --all -- -A clippy::all -D clippy::disallowed_methods + - run: cargo clippy --all --all-features -- -A clippy::all -D clippy::disallowed_methods diff --git a/Cargo.toml b/Cargo.toml index 4d22f63..62c29fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,11 +15,16 @@ readme = "./README.md" rust-version = "1.82.0" [dependencies] +proc-macro2 = { version = "1.0.0", optional = true } toml_edit = { version = "0.25.0", default-features = false, features = [ "parse", ] } +quote = { version = "1.0.0", optional = true } [dev-dependencies] quote = "1.0.39" syn = "2.0.99" proc-macro2 = "1.0.94" + +[features] +to_tokens = ["dep:proc-macro2", "dep:quote"] diff --git a/src/lib.rs b/src/lib.rs index f1d47e5..fe58a76 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,6 +94,10 @@ use std::{ time::SystemTime, }; +#[cfg(feature = "to_tokens")] +use proc_macro2::{Ident, Span, TokenStream}; +#[cfg(feature = "to_tokens")] +use quote::{quote, ToTokens}; use toml_edit::{DocumentMut, Item, TableLike, TomlError}; /// Error type used by this crate. @@ -152,6 +156,22 @@ pub enum FoundCrate { Name(String), } +#[cfg(feature = "to_tokens")] +impl ToTokens for FoundCrate { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + Self::Itself => { + quote!(crate) + }, + Self::Name(name) => { + let name = Ident::new_raw(name, Span::call_site()); + quote!(::#name) + }, + } + .to_tokens(tokens); + } +} + // In a rustc invocation, there will only ever be one entry in this map, since every crate is // compiled with its own rustc process. However, the same is not (currently) the case for // rust-analyzer. @@ -574,4 +594,19 @@ mod tests { "#, Ok(Some(FoundCrate::Name(name))) if name == "my_crate_cool" } + + #[cfg(feature = "to_tokens")] + #[test] + fn itself_to_tokens() { + assert_eq!(quote!(crate).to_string(), FoundCrate::Itself.into_token_stream().to_string()); + } + + #[cfg(feature = "to_tokens")] + #[test] + fn name_to_tokens() { + assert_eq!( + quote!(::r#my_crate).to_string(), + FoundCrate::Name("my_crate".to_string()).into_token_stream().to_string() + ); + } }