From 535a710323ea3a46b9c127cd7b3f2d772f9b6838 Mon Sep 17 00:00:00 2001 From: Kurt Wolf Date: Sun, 24 Mar 2024 11:01:04 -0400 Subject: [PATCH] fix tests; --- libninja/src/rust/client.rs | 160 ++++++++++++++++----------------- libninja/src/rust/request.rs | 101 +++++---------------- macro/src/function.rs | 74 ++++++++------- macro/src/lib.rs | 19 ++-- macro/tests/function.rs | 169 ++++++++++++++++++----------------- macro/tests/rfunction.rs | 23 ++--- mir/src/enum.rs | 3 +- mir/src/lib.rs | 13 +-- 8 files changed, 259 insertions(+), 303 deletions(-) diff --git a/libninja/src/rust/client.rs b/libninja/src/rust/client.rs index 15be9f1..5eddcab 100644 --- a/libninja/src/rust/client.rs +++ b/libninja/src/rust/client.rs @@ -1,17 +1,18 @@ use convert_case::{Case, Casing}; -use openapiv3::OpenAPI; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; -use hir::{AuthLocation, AuthStrategy, Location, Parameter, ServerStrategy, HirSpec, Language, Operation, qualified_env_var}; -use mir::{Function, Ident, DocFormat, Doc, FnArg2}; -use mir::{Class, Field, Visibility}; +use hir::{ + AuthLocation, AuthStrategy, HirSpec, Language, Operation, qualified_env_var + , ServerStrategy, +}; use ln_core::PackageConfig; -use mir_rust::{ToRustIdent, ToRustCode}; +use mir::{Class, Field, Visibility}; +use mir::{FnArg2, Function, Ident}; +use mir_rust::{ToRustCode, ToRustIdent}; use crate::rust::codegen::ToRustType; - pub fn server_url(spec: &HirSpec, opt: &PackageConfig) -> TokenStream { match spec.server_strategy() { ServerStrategy::Single(url) => quote!(#url), @@ -48,7 +49,7 @@ fn build_Client_from_env(spec: &HirSpec, opt: &PackageConfig) -> Function Function Function Function Class { let auth_struct_name = opt.authenticator_name().to_rust_struct(); - let mut instance_fields = vec![ - Field { - name: Ident::new("client"), - ty: quote!(Cow<'static, httpclient::Client>), - ..Field::default() - } - ]; + let mut instance_fields = vec![Field { + name: Ident::new("client"), + ty: quote!(Cow<'static, httpclient::Client>), + ..Field::default() + }]; if spec.has_security() { instance_fields.push(Field { name: Ident::new("authentication"), @@ -121,15 +123,13 @@ pub fn struct_Client(spec: &HirSpec, opt: &PackageConfig) -> Class }); } - let mut class_methods = vec![ - build_Client_from_env(spec, opt) - ]; + let mut class_methods = vec![build_Client_from_env(spec, opt)]; if spec.has_security() { class_methods.push(build_Client_with_auth(spec, opt)); } else { class_methods.push(Function { name: Ident::new("new"), - public: true, + vis: Visibility::Public, ret: quote!(Self), body: quote! { Self { @@ -144,7 +144,7 @@ pub fn struct_Client(spec: &HirSpec, opt: &PackageConfig) -> Class name: opt.client_name().to_rust_struct(), instance_fields, class_methods, - public: true, + vis: Visibility::Public, ..Class::default() } } @@ -218,11 +218,7 @@ pub fn impl_ServiceClient_paths(spec: &HirSpec) -> Vec { result } -pub fn authenticate_variant( - req: &AuthStrategy, - opt: &PackageConfig, -) -> TokenStream { - +pub fn authenticate_variant(req: &AuthStrategy, opt: &PackageConfig) -> TokenStream { let auth_struct = opt.authenticator_name().to_rust_struct(); match req { @@ -281,7 +277,8 @@ pub fn authenticate_variant( } pub fn build_Client_authenticate(spec: &HirSpec, opt: &PackageConfig) -> TokenStream { - let authenticate_variant = spec.security + let authenticate_variant = spec + .security .iter() .map(|req| authenticate_variant(req, opt)) .collect::>(); @@ -301,9 +298,9 @@ pub fn impl_Client(spec: &HirSpec, opt: &PackageConfig) -> TokenStream { let path_fns = impl_ServiceClient_paths(spec); let security = spec.has_security(); - let authenticate = security.then(|| { - build_Client_authenticate(spec, opt) - }).unwrap_or_default(); + let authenticate = security + .then(|| build_Client_authenticate(spec, opt)) + .unwrap_or_default(); quote! { impl #client_struct_name { @@ -316,26 +313,24 @@ pub fn impl_Client(spec: &HirSpec, opt: &PackageConfig) -> TokenStream { pub fn struct_Authentication(mir_spec: &HirSpec, opt: &PackageConfig) -> TokenStream { let auth_struct_name = opt.authenticator_name().to_rust_struct(); - let variants = mir_spec.security.iter().map(|strategy| { - match strategy { - AuthStrategy::Token(strategy) => { - let variant_name = strategy.name.to_rust_struct(); - let args = strategy.fields.iter().map(|f| f.name.to_rust_ident()); - quote! { - #variant_name { - #(#args: String),* - } + let variants = mir_spec.security.iter().map(|strategy| match strategy { + AuthStrategy::Token(strategy) => { + let variant_name = strategy.name.to_rust_struct(); + let args = strategy.fields.iter().map(|f| f.name.to_rust_ident()); + quote! { + #variant_name { + #(#args: String),* } } - AuthStrategy::OAuth2(_) => { - quote! { - OAuth2 { middleware: Arc } - } + } + AuthStrategy::OAuth2(_) => { + quote! { + OAuth2 { middleware: Arc } } - AuthStrategy::NoAuth => { - quote! { - NoAuth - } + } + AuthStrategy::NoAuth => { + quote! { + NoAuth } } }); @@ -352,25 +347,28 @@ fn build_Authentication_from_env(spec: &HirSpec, service_name: &str) -> TokenStr }; match strat { AuthStrategy::Token(strat) => { - let fields = strat.fields + let fields = strat + .fields .iter() .map(|f| { let basic = matches!(f.location, AuthLocation::Basic); - let field = - syn::Ident::new(&f.name.to_case(Case::Snake), proc_macro2::Span::call_site()); + let field = syn::Ident::new( + &f.name.to_case(Case::Snake), + proc_macro2::Span::call_site(), + ); let env_var = qualified_env_var(service_name, &f.name); let expect = format!("Environment variable {} is not set.", env_var); if basic { quote! { - #field: { - let value = std::env::var(#env_var).expect(#expect); - STANDARD_NO_PAD.encode(value) - } + #field: { + let value = std::env::var(#env_var).expect(#expect); + STANDARD_NO_PAD.encode(value) } + } } else { quote! { - #field: std::env::var(#env_var).expect(#expect) - } + #field: std::env::var(#env_var).expect(#expect) + } } }) .collect::>(); @@ -379,19 +377,19 @@ fn build_Authentication_from_env(spec: &HirSpec, service_name: &str) -> TokenStr proc_macro2::Span::call_site(), ); quote! { - pub fn from_env() -> Self { - Self::#variant_name { - #(#fields),* - } + pub fn from_env() -> Self { + Self::#variant_name { + #(#fields),* } } + } } AuthStrategy::NoAuth => { quote! { - pub fn from_env() -> Self { - Self::NoAuth - } + pub fn from_env() -> Self { + Self::NoAuth } + } } AuthStrategy::OAuth2(_) => { let access = qualified_env_var(service_name, "access_token"); @@ -413,15 +411,17 @@ fn build_Authentication_from_env(spec: &HirSpec, service_name: &str) -> TokenStr pub fn impl_Authentication(spec: &HirSpec, opt: &PackageConfig) -> TokenStream { let auth_struct_name = opt.authenticator_name().to_rust_struct(); let from_env = build_Authentication_from_env(spec, &opt.service_name); - let oauth2 = spec.oauth2_auth().map(|oauth| { - quote! { - pub fn oauth2(access: String, refresh: String) -> Self { - let mw = shared_oauth2_flow().bearer_middleware(access, refresh); - Self::OAuth2 { middleware: Arc::new(mw) } + let oauth2 = spec + .oauth2_auth() + .map(|oauth| { + quote! { + pub fn oauth2(access: String, refresh: String) -> Self { + let mw = shared_oauth2_flow().bearer_middleware(access, refresh); + Self::OAuth2 { middleware: Arc::new(mw) } + } } - } - - }).unwrap_or_default(); + }) + .unwrap_or_default(); quote! { impl #auth_struct_name { diff --git a/libninja/src/rust/request.rs b/libninja/src/rust/request.rs index b7c2d9e..da43555 100644 --- a/libninja/src/rust/request.rs +++ b/libninja/src/rust/request.rs @@ -19,8 +19,14 @@ use crate::rust::codegen::ToRustType; use super::lower_hir::derives_to_tokens; pub fn assign_inputs_to_request(inputs: &[Parameter]) -> TokenStream { - let params_except_path: Vec<&Parameter> = inputs.iter().filter(|&input| input.location != Location::Path).collect(); - if params_except_path.iter().all(|&input| input.location == Location::Query) { + let params_except_path: Vec<&Parameter> = inputs + .iter() + .filter(|&input| input.location != Location::Path) + .collect(); + if params_except_path + .iter() + .all(|&input| input.location == Location::Query) + { return quote! { r = r.set_query(self.params); }; @@ -100,9 +106,7 @@ pub fn build_url(operation: &Operation) -> TokenStream { } } else { static FIX_PLACEHOLDERS: OnceLock = OnceLock::new(); - let fix = FIX_PLACEHOLDERS.get_or_init(|| - regex::Regex::new("\\{([_\\w]+)\\}").unwrap() - ); + let fix = FIX_PLACEHOLDERS.get_or_init(|| regex::Regex::new("\\{([_\\w]+)\\}").unwrap()); let inputs = inputs.into_iter().map(|input| { let name = input.name.to_rust_ident(); quote! { #name = self.params.#name } @@ -118,55 +122,7 @@ pub fn build_url(operation: &Operation) -> TokenStream { } } -// pub fn authorize_request(spec: &HirSpec) -> TokenStream { -// if spec_defines_auth(spec) { -// quote! { -// r = self.http_client.authenticate(r); -// } -// } else { -// quote! {} -// } -// } - -// pub fn build_send_function(operation: &Operation, spec: &HirSpec) -> Function { -// let assign_inputs = assign_inputs_to_request(&operation.parameters); -// let auth = authorize_request(spec); -// let response = operation.ret.to_rust_type(); -// let method = syn::Ident::new(&operation.method, proc_macro2::Span::call_site()); -// let url = build_url(operation); -// -// let ret = if matches!(operation.ret , Ty::Unit) { -// quote!(Ok(())) -// } else { -// quote!(res -// .json() -// .await -// .map_err(|e| anyhow::anyhow!("{:?}", e)) -// ) -// }; -// Function { -// name: "send".into(), -// ret: quote! { -// ::httpclient::InMemoryResult<#response> -// }, -// body: quote! { -// let mut r = self.http_client.client.#method(#url); -// #assign_inputs -// #auth -// let res = r -// .await?; -// res.json().map_err(Into::into) -// }, -// async_: true, -// public: true, -// ..Function::default() -// } -// } - -pub fn build_struct_fields( - inputs: &[Parameter], - use_references: bool, -) -> Vec> { +pub fn build_struct_fields(inputs: &[Parameter], use_references: bool) -> Vec> { inputs .iter() .map(|input| { @@ -189,9 +145,7 @@ pub fn build_struct_fields( } /// Build the various "builder" methods for optional parameters for a request struct -pub fn build_request_struct_builder_methods( - operation: &Operation, -) -> Vec> { +pub fn build_request_struct_builder_methods(operation: &Operation) -> Vec> { operation.parameters.iter().filter(|a| a.optional).map(|a| { let name = a.name.to_rust_ident(); let mut arg_type = a.ty.to_reference_type(TokenStream::new()); @@ -228,7 +182,7 @@ pub fn build_request_struct_builder_methods( ], ret: quote! {Self}, body, - public: true, + vis: Visibility::Public, ..Function::default() } }).collect() @@ -240,33 +194,27 @@ pub fn build_request_struct( opt: &PackageConfig, ) -> Vec> { let mut instance_fields = build_struct_fields(&operation.parameters, false); - // instance_fields.insert( - // 0, - // Field { - // name: "http_client".to_string(), - // ty: { - // let c = opt.client_name().to_rust_struct(); - // quote! { &'a #c } - // }, - // visibility: Visibility::Crate, - // ..Field::default() - // }, - // ); 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(" ", ""); + let client = opt + .client_name() + .to_rust_struct() + .to_string() + .replace(" ", ""); let derives = derives_to_tokens(&opt.derives); - let doc = Some(Doc(format!(r#"You should use this struct via [`{client}::{fn_name}`]. + let doc = Some(Doc(format!( + r#"You should use this struct via [`{client}::{fn_name}`]. + +On request success, this will return a [`{response}`]."#, + ))); -On request success, this will return a [`{response}`]."#, ))); - let mut result = vec![Class { name: operation.request_struct_name().to_rust_struct(), doc, instance_fields, lifetimes: vec![], - public: true, + vis: Visibility::Public, decorators: vec![quote! {#[derive(Debug, Clone, Serialize, Deserialize #derives)]}], ..Class::default() }]; @@ -292,12 +240,11 @@ On request success, this will return a [`{response}`]."#, ))); .collect::>(); build_struct_fields(&required, true) }, - public: true, + vis: Visibility::Public, lifetimes, ..Class::default() }); } - result } diff --git a/macro/src/function.rs b/macro/src/function.rs index a4d8373..4d00f7e 100644 --- a/macro/src/function.rs +++ b/macro/src/function.rs @@ -1,19 +1,23 @@ use proc_macro::{Delimiter, Ident, TokenStream, TokenTree}; -use proc_macro2::{Ident as Ident2, TokenStream as TokenStream2}; use std::iter::Peekable; -use crate::body::{pull_interpolation}; + +use proc_macro2::{Ident as Ident2, TokenStream as TokenStream2}; use quote::quote; +use mir::Visibility; + +use crate::body::pull_interpolation; + pub struct Tags { pub asyn: bool, - pub public: bool, + pub vis: Visibility, pub fn_name: TokenStream2, } /// Capture $(async)? $(pub)? fn_name -pub fn parse_intro(toks: &mut impl Iterator) -> Tags { +pub fn parse_intro(toks: &mut impl Iterator) -> Tags { let mut asyn = false; - let mut public = false; + let mut vis = Visibility::Private; let mut captured = vec![]; let fn_name = loop { let next = toks @@ -24,7 +28,7 @@ pub fn parse_intro(toks: &mut impl Iterator) -> Tags { asyn = true; } TokenTree::Ident(ident) if ident.to_string() == "pub" => { - public = true; + vis = Visibility::Public; } TokenTree::Ident(ident) => { break ident.to_string(); @@ -45,13 +49,9 @@ pub fn parse_intro(toks: &mut impl Iterator) -> Tags { .into_iter() .map(|name| Ident2::new(&name, proc_macro2::Span::call_site())); - quote!( ::mir::Ident(format!("{}", #( #captured ),*)) ) + quote!(::mir::Ident(format!("{}", #( #captured ),*))) }; - Tags { - asyn, - public, - fn_name, - } + Tags { asyn, vis, fn_name } } pub struct Arg { @@ -77,13 +77,11 @@ pub fn parse_args(arg_toks: TokenStream) -> Vec { } let arg_type = match arg_toks.next() { - // Matches a ident arg_type, e.g. + // Matches the ident arg_type, e.g. // str // Dict[str, str] // requests.PreparedRequest - Some(TokenTree::Ident(ident)) => { - parse_type(ident, &mut arg_toks) - } + Some(TokenTree::Ident(ident)) => parse_type(ident, &mut arg_toks), // Matches a arg_type binding, e.g. // let arg_type = "int"; // function!(add(a: #arg_type, b: #arg_type) {}) @@ -139,12 +137,14 @@ pub fn parse_args(arg_toks: TokenStream) -> Vec { args } - /// Matches a ident arg_type, e.g. /// str /// Dict[str, str] /// requests.PreparedRequest -pub fn parse_type(ident: Ident, toks: &mut Peekable>) -> TokenStream2 { +pub fn parse_type( + ident: Ident, + toks: &mut Peekable>, +) -> TokenStream2 { let mut ident = ident.to_string(); // Matches path-ed types, e.g. requests.PreparedRequest while matches!(toks.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == '.') { @@ -156,7 +156,8 @@ pub fn parse_type(ident: Ident, toks: &mut Peekable>) -> TokenStream2 { +pub fn parse_return(toks: &mut Peekable>) -> TokenStream2 { loop { match toks.peek() { Some(TokenTree::Punct(punct)) if punct.as_char() == '-' => { toks.next(); match toks.next() { - Some(TokenTree::Punct(punct)) if punct.as_char() == '>' => { - match toks.next() { - Some(TokenTree::Ident(ident)) => { - break parse_type(ident, toks); - } - Some(TokenTree::Punct(punct)) if punct.as_char() == '#' => { - let mut captured = vec![]; - let placeholder = pull_interpolation(toks, &mut captured, false); - - let captured = captured - .into_iter() - .map(|name| Ident2::new(&name, proc_macro2::Span::call_site())); - break quote!(format!(#placeholder, #( #captured ),*)); - } - next => panic!("Expected the return type. Got: {:?}", next), + Some(TokenTree::Punct(punct)) if punct.as_char() == '>' => match toks.next() { + Some(TokenTree::Ident(ident)) => { + break parse_type(ident, toks); } - } + Some(TokenTree::Punct(punct)) if punct.as_char() == '#' => { + let mut captured = vec![]; + let placeholder = pull_interpolation(toks, &mut captured, false); + + let captured = captured + .into_iter() + .map(|name| Ident2::new(&name, proc_macro2::Span::call_site())); + break quote!(format!(#placeholder, #( #captured ),*)); + } + next => panic!("Expected the return type. Got: {:?}", next), + }, next => panic!("Expected ->. Got: {:?}", next), } } @@ -197,6 +196,3 @@ pub fn parse_return(toks: &mut Peekable>) -> Token } } } - - - diff --git a/macro/src/lib.rs b/macro/src/lib.rs index a181f3d..30d482f 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -3,13 +3,20 @@ mod function; mod body; use proc_macro::{Delimiter, TokenStream, TokenTree}; - use proc_macro2::{TokenStream as TokenStream2}; use quote::quote; use body::body_callable; use function::{Arg, Tags}; +use mir::Visibility; use crate::function::{parse_intro, parse_args, parse_return} ; +fn vis_to_token(vis: Visibility) -> TokenStream2 { + match vis { + Visibility::Public => quote!(::mir::Visibility::Public), + Visibility::Private => quote!(::mir::Visibility::Private), + Visibility::Crate => quote!(::mir::Visibility::Crate), + } +} /// Define a function where the body is a string. The fn interface definition is reminiscent of Python, /// but because it creates a mir::Function, it will compile down into whatever language we target. @@ -19,7 +26,7 @@ use crate::function::{parse_intro, parse_args, parse_return} ; pub fn function(item: TokenStream) -> TokenStream { let mut toks = item.into_iter().peekable(); - let Tags { asyn, public, fn_name } = parse_intro(&mut toks); + let Tags { asyn, vis, fn_name } = parse_intro(&mut toks); // 2. Argument groups let arg_toks = match toks.next() { Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Parenthesis => group, @@ -46,11 +53,12 @@ pub fn function(item: TokenStream) -> TokenStream { other => panic!("Expected a function body. Got: {:?}", other), }; + let vis = vis_to_token(vis); quote! { ::mir::Function { name: #fn_name, async_: #asyn, - public: #public, + vis: #vis, args: vec![#(#args),*], ret: #ret, body: #body, @@ -65,7 +73,7 @@ pub fn function(item: TokenStream) -> TokenStream { pub fn rfunction(item: TokenStream) -> TokenStream { let mut toks = item.into_iter().peekable(); - let Tags { asyn, public, fn_name } = function::parse_intro(&mut toks); + let Tags { asyn, vis, fn_name } = parse_intro(&mut toks); // 2. Argument groups let arg_toks = match toks.next() { Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Parenthesis => group, @@ -95,11 +103,12 @@ pub fn rfunction(item: TokenStream) -> TokenStream { other => panic!("Expected function body. Got: {:?}", other), }; + let vis = vis_to_token(vis); quote! { ::mir::Function { name: #fn_name, async_: #asyn, - public: #public, + vis: #vis, args: vec![#(#args),*], ret: #ret, body: #body, diff --git a/macro/tests/function.rs b/macro/tests/function.rs index be72dc6..446196e 100644 --- a/macro/tests/function.rs +++ b/macro/tests/function.rs @@ -1,99 +1,100 @@ -use ln_macro::function; -use mir::Function; use pretty_assertions::assert_eq; +use ln_macro::function; +use mir::{Function, Visibility}; + #[test] fn test_function() { let s: Function = function!(async main() {}); assert_eq!(s.name.0, "main"); assert_eq!(s.async_, true); - assert_eq!(s.public, false); + assert_eq!(s.vis, Visibility::Public); } -// #[test] -// fn test_function_args() { -// let s: Function = function!(print_repeated(s: str, n: int) {}); -// assert_eq!(s.name.0, "print_repeated"); -// assert_eq!(s.async_, false); -// assert_eq!(s.public, false); -// assert_eq!(s.args.len(), 2); -// assert_eq!(s.args[0].name().unwrap(), "s"); -// assert_eq!(s.args[0].ty().unwrap(), "str"); -// assert_eq!(s.args[1].name().unwrap(), "n"); -// assert_eq!(s.args[1].ty().unwrap(), "int"); -// assert_eq!(s.ret, "".to_string()); -// } +#[test] +fn test_function_args() { + let s: Function = function!(print_repeated(s: str, n: int) {}); + assert_eq!(s.name.0, "print_repeated"); + assert_eq!(s.async_, false); + assert_eq!(s.vis, Visibility::Private); + assert_eq!(s.args.len(), 2); + assert_eq!(s.args[0].name().unwrap(), "s"); + assert_eq!(s.args[0].ty().unwrap(), "str"); + assert_eq!(s.args[1].name().unwrap(), "n"); + assert_eq!(s.args[1].ty().unwrap(), "int"); + assert_eq!(s.ret, "".to_string()); +} -// #[test] -// fn test_function_return() { -// let s: Function = function!(add(a: int, b: int) -> int {}); -// assert_eq!(s.name.0, "add"); -// assert_eq!(s.async_, false); -// assert_eq!(s.public, false); -// assert_eq!(s.args.len(), 2); -// assert_eq!(s.ret, "int".to_string()); -// } +#[test] +fn test_function_return() { + let s: Function = function!(add(a: int, b: int) -> int {}); + assert_eq!(s.name.0, "add"); + assert_eq!(s.async_, false); + assert_eq!(s.vis, Visibility::Private); + assert_eq!(s.args.len(), 2); + assert_eq!(s.ret, "int".to_string()); +} -// #[test] -// fn test_interpolation_in_arg_position() { -// let z = "int"; -// let s: Function = function!(add(a: int, b: #z) -> int {}); -// assert_eq!(s.name.0, "add"); -// assert_eq!(s.async_, false); -// assert_eq!(s.public, false); -// assert_eq!(s.args.len(), 2); -// assert_eq!(s.args[1].ty().unwrap(), "int"); -// assert_eq!(s.ret, "int".to_string()); -// } +#[test] +fn test_interpolation_in_arg_position() { + let z = "int"; + let s: Function = function!(add(a: int, b: #z) -> int {}); + assert_eq!(s.name.0, "add"); + assert_eq!(s.async_, false); + assert_eq!(s.vis, Visibility::Private); + assert_eq!(s.args.len(), 2); + assert_eq!(s.args[1].ty().unwrap(), "int"); + assert_eq!(s.ret, "int".to_string()); +} -// #[test] -// fn test_interpolation_in_ret_position() { -// let z = "int"; -// let s: Function = function!(add(a: int, b: int) -> #z {}); -// assert_eq!(s.ret, "int"); -// } +#[test] +fn test_interpolation_in_ret_position() { + let z = "int"; + let s: Function = function!(add(a: int, b: int) -> #z {}); + assert_eq!(s.ret, "int"); +} -// #[test] -// fn test_interpolation_in_name_position() { -// let z = "main"; -// let s: Function = function!(#z(a: int, b: int) {}); -// assert_eq!(s.name.0, z); -// } +#[test] +fn test_interpolation_in_name_position() { + let z = "main"; + let s: Function = function!(#z(a: int, b: int) {}); + assert_eq!(s.name.0, z); +} -// #[test] -// fn test_function_stringified_body() { -// let s: Function = function!(debug_add(a: int, b: int) -> int { -// print(a); -// print(b); -// a + b; -// }); -// assert_eq!(s.name.0, "debug_add"); -// assert_eq!( -// s.body, -// "\ -// print(a) -// print(b) -// a + b\ -// " -// .to_string() -// ); -// } +#[test] +fn test_function_stringified_body() { + let s: Function = function!(debug_add(a: int, b: int) -> int { + print(a); + print(b); + a + b; + }); + assert_eq!(s.name.0, "debug_add"); + assert_eq!( + s.body, + "\ +print(a) +print(b) +a + b\ +" + .to_string() + ); +} -// #[test] -// fn test_use_body_variable() { -// let s: Function = function!(debug_add(a: int, b: int) -> int { -// print(a); -// print(b); -// a + b; -// }); -// assert_eq!(s.name.0, "debug_add"); -// assert_eq!( -// s.body, -// "\ -// print(a) -// print(b) -// a + b\ -// " -// .to_string() -// ); -// } +#[test] +fn test_use_body_variable() { + let s: Function = function!(debug_add(a: int, b: int) -> int { + print(a); + print(b); + a + b; + }); + assert_eq!(s.name.0, "debug_add"); + assert_eq!( + s.body, + "\ +print(a) +print(b) +a + b\ +" + .to_string() + ); +} diff --git a/macro/tests/rfunction.rs b/macro/tests/rfunction.rs index c83f243..43b2e84 100644 --- a/macro/tests/rfunction.rs +++ b/macro/tests/rfunction.rs @@ -1,17 +1,20 @@ -use ln_macro::rfunction; +use proc_macro2::TokenStream; use quote::quote; +use ln_macro::rfunction; +use mir::Function; + #[test] fn test_quote_body() { - // let s: Function = rfunction!(add(a: i32, b: i32) -> i32 { - // println!("Hello, World!") - // }); - // assert_eq!(s.name.0, "add"); - // assert_eq!(s.body.to_string(), "println ! (\"Hello, World!\")"); - // assert_eq!(s.ret.to_string(), "i32"); - // assert_eq!(s.args.len(), 2); - // assert_eq!(s.args[0].ty().unwrap().to_string(), "i32"); - // assert_eq!(s.args[1].ty().unwrap().to_string(), "i32"); + let s: Function = rfunction!(add(a: i32, b: i32) -> i32 { + println!("Hello, World!") + }); + assert_eq!(s.name.0, "add"); + assert_eq!(s.body.to_string(), "println ! (\"Hello, World!\")"); + assert_eq!(s.ret.to_string(), "i32"); + assert_eq!(s.args.len(), 2); + assert_eq!(s.args[0].ty().unwrap().to_string(), "i32"); + assert_eq!(s.args[1].ty().unwrap().to_string(), "i32"); } #[test] diff --git a/mir/src/enum.rs b/mir/src/enum.rs index 6bcf59f..54545f0 100644 --- a/mir/src/enum.rs +++ b/mir/src/enum.rs @@ -1,4 +1,3 @@ -use std::marker::PhantomData; use crate::{Doc, Function, Ident, Visibility}; #[derive(Debug, Default)] @@ -16,4 +15,4 @@ pub struct Enum { pub struct Variant { pub name: Ident, pub doc: Option, -} \ No newline at end of file +} diff --git a/mir/src/lib.rs b/mir/src/lib.rs index f1847fa..af6097e 100644 --- a/mir/src/lib.rs +++ b/mir/src/lib.rs @@ -10,16 +10,16 @@ pub use r#enum::*; pub use ty::*; pub use visibility::*; +mod class; mod doc; +mod r#enum; +mod file; mod function; +mod ident; +mod import; mod r#macro; mod ty; -mod class; -mod import; mod visibility; -mod ident; -mod r#enum; -mod file; pub struct Interface { pub name: String, @@ -38,8 +38,10 @@ pub struct NewType { pub struct Literal(pub T); +#[allow(unused)] pub struct Grave(String); +#[allow(unused)] pub struct FString(String); pub fn literal(s: impl Into) -> Literal { @@ -68,4 +70,3 @@ impl std::fmt::Display for ParamKey { } } } -