diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0e496569..861eacb8 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -14,20 +14,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Install nightly rustfmt - uses: dtolnay/rust-toolchain@nightly + - name: Install stable + uses: dtolnay/rust-toolchain@stable with: - components: rustfmt - - name: Report cargo version - run: cargo --version - - name: Report rustfmt version - run: cargo fmt -- --version - - name: Report nightly cargo version - run: cargo +nightly --version - - name: Report nightly rustfmt version - run: cargo +nightly fmt -- --version - - name: Check style + components: rustfmt, clippy + - name: Check formatting run: cargo fmt -- --check + - name: Clippy + run: cargo clippy --all-features --all-targets build-and-test: runs-on: ${{ matrix.os }} diff --git a/example-build/src/main.rs b/example-build/src/main.rs index c0fa53a8..547be05a 100644 --- a/example-build/src/main.rs +++ b/example-build/src/main.rs @@ -5,11 +5,12 @@ include!(concat!(env!("OUT_DIR"), "/codegen.rs")); fn main() { let client = Client::new("https://foo/bar"); - let _ = client.enrol( + // Explicitly drop the future to avoid clippy's let_underscore_future lint. + std::mem::drop(client.enrol( "auth-token", &types::EnrolBody { host: "".to_string(), key: "".to_string(), }, - ); + )); } diff --git a/example-wasm/src/main.rs b/example-wasm/src/main.rs index c0fa53a8..547be05a 100644 --- a/example-wasm/src/main.rs +++ b/example-wasm/src/main.rs @@ -5,11 +5,12 @@ include!(concat!(env!("OUT_DIR"), "/codegen.rs")); fn main() { let client = Client::new("https://foo/bar"); - let _ = client.enrol( + // Explicitly drop the future to avoid clippy's let_underscore_future lint. + std::mem::drop(client.enrol( "auth-token", &types::EnrolBody { host: "".to_string(), key: "".to_string(), }, - ); + )); } diff --git a/progenitor-client/src/progenitor_client.rs b/progenitor-client/src/progenitor_client.rs index 6f8dcca0..9f256a3f 100644 --- a/progenitor-client/src/progenitor_client.rs +++ b/progenitor-client/src/progenitor_client.rs @@ -528,6 +528,8 @@ pub fn encode_path(pc: &str) -> String { #[doc(hidden)] pub trait RequestBuilderExt { + // The error type is large but it's used in generated output. + #[expect(clippy::result_large_err)] fn form_urlencoded(self, body: &T) -> Result>; } diff --git a/progenitor-impl/src/cli.rs b/progenitor-impl/src/cli.rs index e1bdf30c..026edc28 100644 --- a/progenitor-impl/src/cli.rs +++ b/progenitor-impl/src/cli.rs @@ -389,8 +389,8 @@ impl Generator { continue; } - let first_page_required = first_page_required_set - .map_or(false, |required| required.contains(¶m.api_name)); + let first_page_required = + first_page_required_set.is_some_and(|required| required.contains(¶m.api_name)); let volitionality = if innately_required || first_page_required { Volitionality::Required diff --git a/progenitor-impl/src/lib.rs b/progenitor-impl/src/lib.rs index 68454ece..cfbe9177 100644 --- a/progenitor-impl/src/lib.rs +++ b/progenitor-impl/src/lib.rs @@ -85,35 +85,25 @@ struct CrateSpec { } /// Style of generated client. -#[derive(Clone, Deserialize, PartialEq, Eq)] +#[derive(Clone, Deserialize, PartialEq, Eq, Default)] pub enum InterfaceStyle { /// Use positional style. + #[default] Positional, /// Use builder style. Builder, } -impl Default for InterfaceStyle { - fn default() -> Self { - Self::Positional - } -} - /// Style for using the OpenAPI tags when generating names in the client. -#[derive(Clone, Deserialize)] +#[derive(Clone, Deserialize, Default)] pub enum TagStyle { /// Merge tags to create names in the generated client. + #[default] Merged, /// Use each tag name to create separate names in the generated client. Separate, } -impl Default for TagStyle { - fn default() -> Self { - Self::Merged - } -} - impl GenerationSettings { /// Create new generator settings with default values. pub fn new() -> Self { diff --git a/progenitor-impl/src/method.rs b/progenitor-impl/src/method.rs index 8bf1d0fe..f5aae477 100644 --- a/progenitor-impl/src/method.rs +++ b/progenitor-impl/src/method.rs @@ -1663,7 +1663,7 @@ impl Generator { let send_doc = format!( "Sends a `{}` request to `{}`", method.method.as_str().to_ascii_uppercase(), - method.path.to_string(), + method.path, ); let send_impl = quote! { #[doc = #send_doc] @@ -1724,7 +1724,7 @@ impl Generator { let stream_doc = format!( "Streams `{}` requests to `{}`", method.method.as_str().to_ascii_uppercase(), - method.path.to_string(), + method.path, ); quote! { @@ -2174,7 +2174,7 @@ fn make_doc_comment(method: &OperationMethod) -> String { buf.push_str(&format!( "Sends a `{}` request to `{}`\n\n", method.method.as_str().to_ascii_uppercase(), - method.path.to_string(), + method.path, )); if method @@ -2213,7 +2213,7 @@ fn make_stream_doc_comment(method: &OperationMethod) -> String { buf.push_str(&format!( "Sends repeated `{}` requests to `{}` until there are no more results.\n\n", method.method.as_str().to_ascii_uppercase(), - method.path.to_string(), + method.path, )); if method diff --git a/progenitor-impl/src/template.rs b/progenitor-impl/src/template.rs index 47f3cc85..1670d121 100644 --- a/progenitor-impl/src/template.rs +++ b/progenitor-impl/src/template.rs @@ -35,7 +35,7 @@ impl PathTemplate { "{}", rename .get(&n) - .expect(&format!("missing path name mapping {}", n)), + .unwrap_or_else(|| panic!("missing path name mapping {}", n)), ); Some(quote! { encode_path(&#param.to_string()) @@ -158,15 +158,15 @@ pub fn parse(t: &str) -> Result { Ok(PathTemplate { components }) } -impl ToString for PathTemplate { - fn to_string(&self) -> std::string::String { - self.components - .iter() - .map(|component| match component { - Component::Constant(s) => s.clone(), - Component::Parameter(s) => format!("{{{}}}", s), - }) - .fold(String::new(), |a, b| a + &b) +impl std::fmt::Display for PathTemplate { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for component in &self.components { + match component { + Component::Constant(s) => s.fmt(f)?, + Component::Parameter(s) => write!(f, "{{{}}}", s)?, + } + } + Ok(()) } } @@ -178,7 +178,7 @@ mod tests { #[test] fn basic() { - let trials = vec![ + let trials = [ ( "/info", "/info", @@ -271,7 +271,7 @@ mod tests { #[test] fn names() { - let trials = vec![ + let trials = [ ("/info", vec![]), ("/measure/{number}", vec!["number".to_string()]), ( diff --git a/progenitor-impl/src/util.rs b/progenitor-impl/src/util.rs index 170d00ac..5e5301c3 100644 --- a/progenitor-impl/src/util.rs +++ b/progenitor-impl/src/util.rs @@ -126,6 +126,6 @@ pub(crate) fn unique_ident_from( return ident; } - name.insert_str(0, "_"); + name.insert(0, '_'); } } diff --git a/progenitor-impl/tests/test_output.rs b/progenitor-impl/tests/test_output.rs index 010315d9..8cf5f317 100644 --- a/progenitor-impl/tests/test_output.rs +++ b/progenitor-impl/tests/test_output.rs @@ -27,7 +27,7 @@ where } fn generate_formatted(generator: &mut Generator, spec: &OpenAPI) -> String { - let content = generator.generate_tokens(&spec).unwrap(); + let content = generator.generate_tokens(spec).unwrap(); reformat_code(content) } @@ -165,7 +165,7 @@ fn test_cli_gen() { #[test] fn test_nexus_with_different_timeout() { - const OPENAPI_FILE: &'static str = "nexus.json"; + const OPENAPI_FILE: &str = "nexus.json"; let mut in_path = PathBuf::from("../sample_openapi"); in_path.push(OPENAPI_FILE); diff --git a/progenitor/tests/build_buildomat.rs b/progenitor/tests/build_buildomat.rs index aea37474..8d2aec33 100644 --- a/progenitor/tests/build_buildomat.rs +++ b/progenitor/tests/build_buildomat.rs @@ -4,7 +4,7 @@ mod positional { progenitor::generate_api!("../sample_openapi/buildomat.json"); fn _ignore() { - let _ = Client::new("").worker_task_upload_chunk("task", vec![0]); + std::mem::drop(Client::new("").worker_task_upload_chunk("task", vec![0])); } } @@ -16,11 +16,13 @@ mod builder_untagged { ); fn _ignore() { - let _ = Client::new("") - .worker_task_upload_chunk() - .task("task") - .body(vec![0]) - .send(); + std::mem::drop( + Client::new("") + .worker_task_upload_chunk() + .task("task") + .body(vec![0]) + .send(), + ); } } @@ -32,10 +34,12 @@ mod builder_tagged { ); fn _ignore() { - let _ = Client::new("") - .worker_task_upload_chunk() - .task("task") - .body(vec![0]) - .send(); + std::mem::drop( + Client::new("") + .worker_task_upload_chunk() + .task("task") + .body(vec![0]) + .send(), + ); } } diff --git a/progenitor/tests/build_keeper.rs b/progenitor/tests/build_keeper.rs index 8ed63341..d10d7b1a 100644 --- a/progenitor/tests/build_keeper.rs +++ b/progenitor/tests/build_keeper.rs @@ -4,13 +4,13 @@ mod positional { progenitor::generate_api!("../sample_openapi/keeper.json"); fn _ignore() { - let _ = Client::new("").enrol( + std::mem::drop(Client::new("").enrol( "auth token", &types::EnrolBody { host: "".to_string(), key: "".to_string(), }, - ); + )); } } @@ -22,14 +22,16 @@ mod builder_untagged { ); fn _ignore() { - let _ = Client::new("") - .enrol() - .authorization("") - .body(types::EnrolBody { - host: "".to_string(), - key: "".to_string(), - }) - .send(); + std::mem::drop( + Client::new("") + .enrol() + .authorization("") + .body(types::EnrolBody { + host: "".to_string(), + key: "".to_string(), + }) + .send(), + ); } } @@ -41,13 +43,15 @@ mod builder_tagged { ); fn _ignore() { - let _ = Client::new("") - .enrol() - .authorization("") - .body(types::EnrolBody { - host: "".to_string(), - key: "".to_string(), - }) - .send(); + std::mem::drop( + Client::new("") + .enrol() + .authorization("") + .body(types::EnrolBody { + host: "".to_string(), + key: "".to_string(), + }) + .send(), + ); } } diff --git a/progenitor/tests/build_nexus.rs b/progenitor/tests/build_nexus.rs index d90634ff..231fe641 100644 --- a/progenitor/tests/build_nexus.rs +++ b/progenitor/tests/build_nexus.rs @@ -10,14 +10,14 @@ mod positional { use nexus_client::{types, Client}; fn _ignore() { - let _ = async { + std::mem::drop(async { let client = Client::new(""); let org = types::Name::try_from("org").unwrap(); let project = types::Name::try_from("project").unwrap(); let instance = types::Name::try_from("instance").unwrap(); let stream = client.instance_disk_list_stream(&org, &project, &instance, None, None); - let _ = stream.collect::>(); - }; + std::mem::drop(stream.collect::>()); + }); } } @@ -68,7 +68,7 @@ mod builder_untagged { .project_name("project") .instance_name("instance") .stream(); - let _ = stream.collect::>(); + std::mem::drop(stream.collect::>()); } } @@ -95,7 +95,7 @@ mod builder_tagged { .project_name("project") .instance_name("instance") .stream(); - let _ = stream.collect::>(); + std::mem::drop(stream.collect::>()); let _ = client .instance_create() diff --git a/progenitor/tests/build_propolis.rs b/progenitor/tests/build_propolis.rs index 360e39b2..1f170589 100644 --- a/progenitor/tests/build_propolis.rs +++ b/progenitor/tests/build_propolis.rs @@ -12,12 +12,12 @@ mod propolis_client { use propolis_client::Client; pub fn _ignore() { - let _ = async { + std::mem::drop(async { let _upgraded: reqwest::Upgraded = Client::new("") .instance_serial() .send() .await .unwrap() .into_inner(); - }; + }); } diff --git a/progenitor/tests/load_yaml.rs b/progenitor/tests/load_yaml.rs index 558dbd66..02fcac1f 100644 --- a/progenitor/tests/load_yaml.rs +++ b/progenitor/tests/load_yaml.rs @@ -2,6 +2,6 @@ mod load_yaml { progenitor::generate_api!("../sample_openapi/param-overrides.yaml"); fn _ignore() { - let _ = Client::new("").key_get(None, None); + std::mem::drop(Client::new("").key_get(None, None)); } }