Skip to content

Commit

Permalink
Fix printing of the preamble in generated Rust code.
Browse files Browse the repository at this point in the history
In the generated Rust bindings, Generate the preamble comments in a
separate string, because `prettyplease` does not preserve comments.

Also, add several more options to the preamble printing code.

Fixes #1086.
  • Loading branch information
sunfishcode committed Nov 15, 2024
1 parent af2d6e8 commit cf7d8aa
Showing 1 changed file with 64 additions and 12 deletions.
76 changes: 64 additions & 12 deletions crates/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct InterfaceName {
#[derive(Default)]
struct RustWasm {
types: Types,
src_preamble: Source,
src: Source,
opts: Opts,
import_modules: Vec<(String, Vec<String>)>,
Expand Down Expand Up @@ -837,44 +838,90 @@ macro_rules! __export_{world_name}_impl {{

impl WorldGenerator for RustWasm {
fn preprocess(&mut self, resolve: &Resolve, world: WorldId) {
wit_bindgen_core::generated_preamble(&mut self.src, env!("CARGO_PKG_VERSION"));
wit_bindgen_core::generated_preamble(&mut self.src_preamble, env!("CARGO_PKG_VERSION"));

// Render some generator options to assist with debugging and/or to help
// recreate it if the original generation command is lost.
uwriteln!(self.src, "// Options used:");
uwriteln!(self.src_preamble, "// Options used:");
if self.opts.std_feature {
uwriteln!(self.src, "// * std_feature");
uwriteln!(self.src_preamble, "// * std_feature");
}
if self.opts.raw_strings {
uwriteln!(self.src, "// * raw_strings");
uwriteln!(self.src_preamble, "// * raw_strings");
}
if !self.opts.skip.is_empty() {
uwriteln!(self.src, "// * skip: {:?}", self.opts.skip);
uwriteln!(self.src_preamble, "// * skip: {:?}", self.opts.skip);
}
if self.opts.stubs {
uwriteln!(self.src_preamble, "// * stubs");
}
if let Some(export_prefix) = &self.opts.export_prefix {
uwriteln!(
self.src_preamble,
"// * export_prefix: {:?}",
export_prefix
);
}
if let Some(runtime_path) = &self.opts.runtime_path {
uwriteln!(self.src_preamble, "// * runtime_path: {:?}", runtime_path);
}
if let Some(bitflags_path) = &self.opts.bitflags_path {
uwriteln!(
self.src_preamble,
"// * bitflags_path: {:?}",
bitflags_path
);
}
if !matches!(self.opts.ownership, Ownership::Owning) {
uwriteln!(self.src, "// * ownership: {:?}", self.opts.ownership);
uwriteln!(
self.src_preamble,
"// * ownership: {:?}",
self.opts.ownership
);
}
if !self.opts.additional_derive_attributes.is_empty() {
uwriteln!(
self.src,
self.src_preamble,
"// * additional derives {:?}",
self.opts.additional_derive_attributes
);
}
for (k, v) in self.opts.with.iter() {
uwriteln!(self.src, "// * with {k:?} = {v}");
uwriteln!(self.src_preamble, "// * with {k:?} = {v}");
}
if let Some(type_section_suffix) = &self.opts.type_section_suffix {
uwriteln!(
self.src_preamble,
"// * type_section_suffix: {:?}",
type_section_suffix
);
}
if let Some(default) = &self.opts.default_bindings_module {
uwriteln!(self.src, "// * default-bindings-module: {default:?}");
uwriteln!(
self.src_preamble,
"// * default-bindings-module: {default:?}"
);
}
if self.opts.disable_run_ctors_once_workaround {
uwriteln!(self.src, "// * disable-run-ctors-once-workaround");
uwriteln!(
self.src_preamble,
"// * disable-run-ctors-once-workaround"
);
}
if let Some(s) = &self.opts.export_macro_name {
uwriteln!(self.src, "// * export-macro-name: {s}");
uwriteln!(self.src_preamble, "// * export-macro-name: {s}");
}
if self.opts.pub_export_macro {
uwriteln!(self.src, "// * pub-export-macro");
uwriteln!(self.src_preamble, "// * pub-export-macro");
}
if self.opts.generate_unused_types {
uwriteln!(self.src_preamble, "// * generate_unused_types");
}
if self.opts.disable_custom_section_link_helpers {
uwriteln!(
self.src_preamble,
"// * disable_custom_section_link_helpers"
);
}
self.types.analyze(resolve);
self.world = Some(world);
Expand Down Expand Up @@ -1101,6 +1148,11 @@ impl WorldGenerator for RustWasm {
*src.as_mut_string() = prettyplease::unparse(&syntax_tree);
}

// Prepend the preamble. We do this after formatting because
// `syn::parse_file` + `prettyplease::unparse` does not preserve comments.
let src_preamble = mem::take(&mut self.src_preamble);
*src.as_mut_string() = format!("{}{}", src_preamble.as_str(), src.as_str());

let module_name = name.to_snake_case();
files.push(&format!("{module_name}.rs"), src.as_bytes());

Expand Down

0 comments on commit cf7d8aa

Please sign in to comment.