diff --git a/codegen/src/generator.rs b/codegen/src/generator.rs index 0235654..a21bc97 100644 --- a/codegen/src/generator.rs +++ b/codegen/src/generator.rs @@ -8,8 +8,7 @@ use std::collections::{HashMap, HashSet}; use std::str; const DATA_IMPORTS: &str = "use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator, RotoMessage};\nuse core::str;\n#[cfg(feature = \"alloc\")]\nuse bytes::{Bytes, BytesMut, Buf, BufMut};\n"; -const SERVICE_IMPORTS: &str = - "#[cfg(feature = \"alloc\")]\nuse tonic::{Request, Response, Status};\n\ +const SERVICE_IMPORTS: &str = "#[cfg(feature = \"alloc\")]\nuse tonic::{Request, Response, Status};\n\ #[cfg(feature = \"alloc\")]\nuse tokio_stream::Stream;\n\ #[cfg(feature = \"alloc\")]\nuse std::pin::Pin;\n\ #[cfg(feature = \"alloc\")]\nuse std::sync::Arc;\n\ @@ -591,7 +590,7 @@ where let mut output = String::new(); output.push_str("// @generated by protoc-gen-roto — do not edit\n"); - output.push_str("#[allow(unused_imports)]\n\n"); + output.push_str("#[allow(unused_imports)]\n"); output.push_str(imports); for dep_res in file_proto.dependency() { @@ -636,10 +635,12 @@ where } let mut root_mod_content = String::new(); - root_mod_content.push_str("// @generated by protoc-gen-roto — do not edit\n"); - root_mod_content.push_str("#![allow(unused_imports)]\n\n"); let mut sorted_root_mods: Vec<_> = root_mods.into_iter().collect(); sorted_root_mods.sort(); + if sorted_root_mods.is_empty() { + root_mod_content.push_str("// @generated by protoc-gen-roto — do not edit\n"); + root_mod_content.push_str("#![allow(unused_imports)]\n\n"); + } for m in sorted_root_mods { root_mod_content.push_str(&format!("pub mod {};\n", m)); } @@ -647,6 +648,9 @@ where for (mod_path, sub_mods) in mod_files { let mut content = String::new(); + if sub_mods.is_empty() { + continue; + } content.push_str("// @generated by protoc-gen-roto — do not edit\n"); content.push_str("#![allow(unused_imports)]\n\n"); let mut sorted_subs: Vec<_> = sub_mods.into_iter().collect(); @@ -759,7 +763,65 @@ pub fn generate_rust_code( } fn strip_boilerplate(content: &str) -> String { - content.to_string() + let mut stripped = content; + let header = "// @generated by protoc-gen-roto — do not edit\n"; + if stripped.starts_with(header) { + stripped = &stripped[header.len()..]; + + let patterns = [ + "#[allow(unused_imports)]\n", + "#![allow(unused_imports)]\n\n", + "#![allow(unused_imports)]\n", + ]; + + for pattern in patterns { + if stripped.starts_with(pattern) { + stripped = &stripped[pattern.len()..]; + break; + } + } + } + stripped.to_string() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_strip_boilerplate_standard() { + let content = "// @generated by protoc-gen-roto — do not edit\n#[allow(unused_imports)]\nuse std::str;\n"; + let stripped = strip_boilerplate(content); + assert_eq!(stripped, "use std::str;\n"); + } + + #[test] + fn test_strip_boilerplate_crate_level() { + let content = "// @generated by protoc-gen-roto — do not edit\n#![allow(unused_imports)]\n\nuse std::str;\n"; + let stripped = strip_boilerplate(content); + assert_eq!(stripped, "use std::str;\n"); + } + + #[test] + fn test_strip_boilerplate_crate_level_single_newline() { + let content = "// @generated by protoc-gen-roto — do not edit\n#![allow(unused_imports)]\nuse std::str;\n"; + let stripped = strip_boilerplate(content); + assert_eq!(stripped, "use std::str;\n"); + } + + #[test] + fn test_strip_boilerplate_no_boilerplate() { + let content = "use std::str;\n"; + let stripped = strip_boilerplate(content); + assert_eq!(stripped, "use std::str;\n"); + } + + #[test] + fn test_strip_boilerplate_only_header() { + let content = "// @generated by protoc-gen-roto — do not edit\n"; + let stripped = strip_boilerplate(content); + assert_eq!(stripped, ""); + } } fn write_service(svc_proto: &ServiceDescriptorProto, package: &str, output: &mut String) { diff --git a/roto-tonic/src/generated/interop.rs b/roto-tonic/src/generated/interop.rs index 4429bfb..a70a155 100644 --- a/roto-tonic/src/generated/interop.rs +++ b/roto-tonic/src/generated/interop.rs @@ -1,6 +1,5 @@ // @generated by protoc-gen-roto — do not edit #[allow(unused_imports)] - use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator, RotoMessage}; use core::str; #[cfg(feature = "alloc")] @@ -407,9 +406,6 @@ impl roto_runtime::RotoMessage for OwnedStreamingResponse { } -// @generated by protoc-gen-roto — do not edit -#[allow(unused_imports)] - #[cfg(feature = "alloc")] use tonic::{Request, Response, Status};