Skip to content

Commit

Permalink
simplify class interface
Browse files Browse the repository at this point in the history
  • Loading branch information
kurtbuilds committed Feb 15, 2024
1 parent aeb7152 commit 195713f
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 125 deletions.
8 changes: 7 additions & 1 deletion core/src/extractor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ pub fn extract_spec(spec: &OpenAPI) -> Result<HirSpec> {
}

pub fn is_optional(name: &str, param: &Schema, parent: &Schema) -> bool {
param.nullable || !parent.required().iter().any(|s| s == name)
if param.nullable {
return true;
}
let Some(req) = parent.get_required() else {
return false;
};
!req.iter().any(|s| s == name)
}

pub fn extract_request_schema<'a>(
Expand Down
7 changes: 2 additions & 5 deletions libninja/src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ use mir::{DateSerialization, IntegerSerialization};
use mir::Ident;
use mir_rust::{sanitize_filename, ToRustCode};
use mir_rust::ToRustIdent;
use mir_rust::codegen_function;

use crate::{add_operation_models, extract_spec, OutputConfig, PackageConfig};
use crate::rust::client::{build_Client_authenticate, server_url};
Expand Down Expand Up @@ -397,10 +396,8 @@ fn write_request_module(spec: &HirSpec, opts: &PackageConfig) -> Result<()> {
let mut import = Import::new(&fname, struct_names);
import.vis = Visibility::Public;
imports.push(import);
let builder_methods = build_request_struct_builder_methods(&operation);
let builder_methods = builder_methods
.into_iter()
.map(|s| codegen_function(s, quote! { mut self , }));
let builder_methods = build_request_struct_builder_methods(&operation)
.into_iter().map(|s| s.to_rust_code());

let assign_inputs = assign_inputs_to_request(&operation.parameters);

Expand Down
3 changes: 1 addition & 2 deletions libninja/src/rust/lower_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ impl FieldExt for HirField {
});
}
}
dbg!(self.optional);
if self.optional {
decorators.push(quote! {
#[serde(default, skip_serializing_if = "Option::is_none")]
Expand Down Expand Up @@ -262,7 +261,7 @@ pub fn create_sumtype_struct(schema: &Struct, config: &ConfigFlags, spec: &HirSp
#dummy
#[derive(Debug, Clone, Serialize, Deserialize #default)]
pub struct #name {
#(#fields)*
#(#fields,)*
}
impl std::fmt::Display for #name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
Expand Down
10 changes: 2 additions & 8 deletions libninja/src/rust/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,12 @@ pub fn build_request_struct_builder_methods(
doc: Some(Doc(format!("Set the value of the {} field.", name.0))),
name,
args: vec![
FnArg2::SelfArg { mutable: true, reference: false },
FnArg2::Basic {
name: a.name.to_rust_ident(),
ty: arg_type,
default: None,
}
},
],
ret: quote! {Self},
body,
Expand Down Expand Up @@ -250,9 +251,6 @@ pub fn build_request_struct(
// },
// );

// let mut instance_methods = vec![build_send_function(operation, spec)];
// let mut_self_instance_methods = build_request_struct_builder_methods(operation);

let fn_name = operation.name.to_rust_ident().0;
let response = operation.ret.to_rust_type().to_string().replace(" ", "");
let client = opt.client_name().to_rust_struct().to_string().replace(" ", "");
Expand All @@ -263,10 +261,6 @@ On request success, this will return a [`{response}`]."#, )));
name: operation.request_struct_name().to_rust_struct(),
doc,
instance_fields,
instance_methods: Vec::new(),
mut_self_instance_methods: Vec::new(),
// We need this lifetime because we hold a ref to the client.
// lifetimes: vec!["'a".to_string()],
lifetimes: vec![],
public: true,
decorators: vec![quote! {#[derive(Debug, Clone, Serialize, Deserialize)]}],
Expand Down
9 changes: 5 additions & 4 deletions libninja/tests/basic/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use std::fs::File;
use std::path::PathBuf;
use std::str::FromStr;

use anyhow::Result;
use openapiv3::OpenAPI;
use pretty_assertions::assert_eq;

use hir::{HirSpec, Language};
use libninja::{generate_library, rust};
use ln_core::{OutputConfig, PackageConfig};
use ln_core::extractor::{extract_api_operations, extract_inputs, extract_spec};
use ln_core::{PackageConfig, OutputConfig};
use openapiv3::OpenAPI;
use pretty_assertions::assert_eq;
use std::path::PathBuf;

const BASIC: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/spec/basic.yaml");
const RECURLY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/spec/recurly.yaml");
Expand Down
6 changes: 0 additions & 6 deletions mir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,11 @@ pub struct Class<T> {
pub code: Option<String>,
pub instance_fields: Vec<Field<T>>,
pub static_fields: Vec<Field<T>>,
pub instance_methods: Vec<Function<T>>,
pub constructors: Vec<Function<T>>,
pub class_methods: Vec<Function<T>>,
pub static_methods: Vec<Function<T>>,
pub public: bool,

pub mut_self_instance_methods: Vec<Function<T>>,
pub lifetimes: Vec<String>,
pub decorators: Vec<T>,
pub superclasses: Vec<T>,
Expand Down Expand Up @@ -158,12 +156,10 @@ impl<T> Default for Class<T> {
doc: None,
instance_fields: vec![],
static_fields: vec![],
instance_methods: vec![],
constructors: vec![],
class_methods: vec![],
static_methods: vec![],
public: false,
mut_self_instance_methods: vec![],
lifetimes: vec![],
decorators: vec![],
superclasses: vec![],
Expand All @@ -178,12 +174,10 @@ impl Debug for Class<String> {
doc: {doc:?}, \
instance_fields: todo!, \
static_fields: todo!, \
instance_methods: todo!, \
constructors: todo!, \
class_methods: todo!, \
static_methods: todo!, \
public: {public}, \
mut_self_instance_methods: todo!, \
lifetimes: todo!, \
superclasses: todo! }}",
name = self.name,
Expand Down
62 changes: 28 additions & 34 deletions mir_rust/src/class.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
use mir::{Class, Function};
use proc_macro2::{TokenStream, Span};
use proc_macro2::{Span, TokenStream};
use quote::quote;
use crate::{ToRustCode, ToRustIdent};

use mir::{Class, Field};

use crate::{FluentBool, ToRustCode, ToRustIdent};

impl ToRustCode for Class<TokenStream> {
fn to_rust_code(self) -> TokenStream {
let vis = self.public.then(|| quote!(pub)).unwrap_or_default();
let fields = self.instance_fields.iter().map(|f| {
let name = &f.name.to_rust_ident();
let ty = &f.ty;
let public = f.vis.to_rust_code();
quote! { #public #name: #ty }
});
let instance_methods = self.instance_methods.into_iter().map(|m|
codegen_function(m, quote! { self , })
);
let mut_self_instance_methods = self.mut_self_instance_methods.into_iter().map(|m| {
codegen_function(m, quote! { mut self , })
});
let class_methods = self.class_methods.into_iter().map(|m| {
codegen_function(m, TokenStream::new())
});
let vis = self.public.to_value(|| quote!(pub));
let fields = self.instance_fields.into_iter().map(|f| f.to_rust_code());
let class_methods = self.class_methods.into_iter().map(|m| m.to_rust_code());

let doc = self.doc.to_rust_code();
let lifetimes = if self.lifetimes.is_empty() {
Expand All @@ -42,26 +31,31 @@ impl ToRustCode for Class<TokenStream> {
#vis struct #name #lifetimes {
#(#fields,)*
}
impl #lifetimes #name #lifetimes{
#(#instance_methods)*
#(#mut_self_instance_methods)*
impl #lifetimes #name #lifetimes {
#(#class_methods)*
}
}
}
}

pub fn codegen_function(func: Function<TokenStream>, self_arg: TokenStream) -> TokenStream {
let name = func.name;
let args = func.args.into_iter().map(|a| a.to_rust_code());
let ret = func.ret;
let async_ = func.async_.then(|| quote!(async)).unwrap_or_default();
let vis = func.public.then(|| quote!(pub)).unwrap_or_default();
let body = &func.body;
quote! {
#vis #async_ fn #name(#self_arg #(#args),*) -> #ret {
#body
impl ToRustCode for Field<TokenStream> {
fn to_rust_code(self) -> TokenStream {
let name = self.name.to_rust_ident();
let ty = if self.optional {
let ty = self.ty;
quote! { Option<#ty> }
} else {
self.ty
};
let vis = self.vis.to_rust_code();
let doc = self.doc.to_rust_code();
let decorators = self.decorators;
quote! {
#doc
#(
#decorators
)*
#vis #name: #ty
}
}
}

}
56 changes: 56 additions & 0 deletions mir_rust/src/function.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use proc_macro2::TokenStream;
use quote::quote;
use mir::{FnArg2, Function};
use crate::{FluentBool, ToRustCode};

impl ToRustCode for Function<TokenStream> {
fn to_rust_code(self) -> TokenStream {
let Function {
name,
args,
body,
doc,
async_,
annotations,
ret,
public,
..
} = self;
let annotations = annotations
.into_iter()
.map(|a| syn::parse_str::<syn::Expr>(&a).unwrap());
let doc = doc.to_rust_code();

let vis = public.to_value(|| quote!(pub));
let async_ = async_.to_value(|| quote!(async));
let args = args.into_iter().map(|a| a.to_rust_code());
let ret = (!ret.is_empty()).to_value(|| quote!( -> #ret));
quote! {
#(#[ #annotations ])*
#doc
#vis #async_ fn #name(#(#args),*) #ret {
#body
}
}
}
}

impl ToRustCode for FnArg2<TokenStream> {
fn to_rust_code(self) -> TokenStream {
match self {
FnArg2::Basic { name, ty, default } => {
if default.is_some() {
panic!("No default args in Rust")
}
quote!(#name: #ty)
}
FnArg2::Unpack { .. } => panic!("unpack args not yet supported in Rust"),
FnArg2::SelfArg { reference, mutable } => {
let mutability = mutable.then(|| quote!(mut)).unwrap_or_default();
let reference = reference.then(|| quote!(&)).unwrap_or_default();
quote!(#reference #mutability self)
}
FnArg2::Variadic { .. } | FnArg2::Kwargs { .. } => panic!("No variadic or kwargs args in Rust"),
}
}
}
Loading

0 comments on commit 195713f

Please sign in to comment.