Skip to content

Commit

Permalink
add ability to template codegen files
Browse files Browse the repository at this point in the history
  • Loading branch information
kurtbuilds committed Dec 19, 2023
1 parent a79e218 commit c44232d
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 12 deletions.
5 changes: 5 additions & 0 deletions core/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ impl PackageConfig {
name.to_case(Case::ScreamingSnake)
))
}

pub fn get_file_template(&self, path: &str) -> Option<String> {
let path = self.dest.join("template").join(path);
std::fs::read_to_string(path).ok()
}
}

pub struct OutputConfig {
Expand Down
1 change: 1 addition & 0 deletions libninja/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ tracing = "0.1.40"
env_logger = "0.10.0"
pretty_assertions = "1.3.0"
tempfile = "3.6.0"
syn = { version = "2.0" , features = ["extra-traits"]}
51 changes: 39 additions & 12 deletions libninja/src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use indoc::formatdoc;
use openapiv3::OpenAPI;
use proc_macro2::TokenStream;
use quote::quote;
use syn::Item;
use text_io::read;

use codegen::ToRustIdent;
Expand Down Expand Up @@ -103,11 +104,11 @@ pub fn copy_from_target_templates(dest: &Path) -> Result<()> {
for path in ignore::Walk::new(&template_path) {
let path: ignore::DirEntry = path?;
let rel_path = path.path().strip_prefix(&template_path)?;
if rel_path.to_str().unwrap() == "src/lib.rs" {
continue;
}
if path.file_type().expect(&format!("Failed to read file: {}", path.path().display())).is_file() {
let dest = dest.join(rel_path);
if dest.exists() {
continue;
}
fs::create_dir_all(dest.parent().unwrap())?;
//copy the file
std::fs::copy(&path.path(), &dest)?;
Expand Down Expand Up @@ -175,6 +176,36 @@ pub fn generate_rust_library(spec: OpenAPI, opts: OutputConfig) -> Result<()> {
Ok(())
}

fn write_file_with_template(mut file: File<TokenStream>, template: Option<String>, path: &Path) -> Result<()> {
let Some(template) = template else {
return write_rust_file_to_path(path, file);
};
// Write things in this order
// file.doc
// file.imports
// template.imports
// template.defs
// file.defs
// let template = syn::parse_file(&template)?;
let doc = std::mem::take(&mut file.doc)
.to_rust_code();
let imports = std::mem::take(&mut file.imports)
.into_iter()
.filter(|i| !template.contains(&i.path))
.map(|i| i.to_rust_code());
let pre = quote! {
#doc
#(#imports)*
};
let mut code = format_code(pre)?;
code.push('\n');
code += template.trim();
code.push('\n');
let after = file.to_rust_code();
code += &format_code(after)?;
fs::write_file(path, &code)
}

fn write_model_module(spec: &HirSpec, opts: &PackageConfig) -> Result<()> {
let config = &opts.config;
let src_path = opts.dest.join("src");
Expand All @@ -185,7 +216,8 @@ fn write_model_module(spec: &HirSpec, opts: &PackageConfig) -> Result<()> {
for (name, record) in &spec.schemas {
let file = generate_single_model_file(name, record, spec, config);
let name = sanitize_filename(name);
write_rust_file_to_path(&src_path.join("model").join(name).with_extension("rs"), file)?;
let dest = src_path.join("model").join(&name).with_extension("rs");
write_file_with_template(file, opts.get_file_template(&format!("src/model/{}.rs", name)), &dest)?;
}
Ok(())
}
Expand All @@ -198,23 +230,18 @@ fn write_lib_rs(spec: &HirSpec, extras: &Extras, opts: &PackageConfig) -> Result
let impl_Client = client::impl_Client(spec, &opts);

let client_name = struct_Client.name.clone();
let template_path = opts.dest.join("template").join("src").join("lib.rs");
let lib_rs_template = if template_path.exists() {
fs::read_to_string(template_path)?
} else {
let lib_rs_template = opts.get_file_template("src/lib.rs").unwrap_or_else(|| {
let s = get_template_file("rust/src/lib.rs");
formatdoc!(
r#"
//! [`{client}`](struct.{client}.html) is the main entry point for this library.
//!
//! Library created with [`libninja`](https://www.libninja.com).
{s}
"#,
client = client_name.0
)
};
) + s
});
let template_has_from_env = lib_rs_template.contains("from_env");

if template_has_from_env {
struct_Client.class_methods.retain(|m| m.name.0 != "from_env");
}
Expand Down

0 comments on commit c44232d

Please sign in to comment.