generate kcl examples in docs from macro (#1710)
* rearrange Signed-off-by: Jess Frazelle <github@jessfraz.com> * examples Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * recast Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * add more tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixups Signed-off-by: Jess Frazelle <github@jessfraz.com> * add more samples Signed-off-by: Jess Frazelle <github@jessfraz.com> * more docs Signed-off-by: Jess Frazelle <github@jessfraz.com> * more Signed-off-by: Jess Frazelle <github@jessfraz.com> * more samples Signed-off-by: Jess Frazelle <github@jessfraz.com> * more Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixups Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixups Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * make serial Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix hang Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix import Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * atan Signed-off-by: Jess Frazelle <github@jessfraz.com> * atan Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * make all tests pass Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix docs Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * must have code balock Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * new docs Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix docs Signed-off-by: Jess Frazelle <github@jessfraz.com> * new docs Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "derive-docs"
|
||||
description = "A tool for generating documentation from Rust derive macros"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
@ -12,6 +12,7 @@ rust-version = "1.73"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
Inflector = "0.11.4"
|
||||
convert_case = "0.6.0"
|
||||
once_cell = "1.19.0"
|
||||
proc-macro2 = "1"
|
||||
|
@ -2,7 +2,12 @@
|
||||
// automated enforcement.
|
||||
#![allow(clippy::style)]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod unbox;
|
||||
|
||||
use convert_case::Casing;
|
||||
use inflector::Inflector;
|
||||
use once_cell::sync::Lazy;
|
||||
use quote::{format_ident, quote, quote_spanned, ToTokens};
|
||||
use regex::Regex;
|
||||
@ -12,6 +17,7 @@ use syn::{
|
||||
parse::{Parse, ParseStream},
|
||||
Attribute, Signature, Visibility,
|
||||
};
|
||||
use unbox::unbox;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct StdlibMetadata {
|
||||
@ -101,6 +107,21 @@ fn do_stdlib_inner(
|
||||
}
|
||||
|
||||
let name = metadata.name;
|
||||
|
||||
// Fail if the name is not camel case.
|
||||
let whitelist = [
|
||||
"patternLinear3d",
|
||||
"patternLinear2d",
|
||||
"patternCircular3d",
|
||||
"patternCircular2d",
|
||||
];
|
||||
if !name.is_camel_case() && !whitelist.contains(&name.as_str()) {
|
||||
errors.push(Error::new_spanned(
|
||||
&ast.sig.ident,
|
||||
format!("stdlib function names must be in camel case: `{}`", name),
|
||||
));
|
||||
}
|
||||
|
||||
let name_ident = format_ident!("{}", name.to_case(convert_case::Case::UpperCamel));
|
||||
let name_str = name.to_string();
|
||||
|
||||
@ -110,16 +131,16 @@ fn do_stdlib_inner(
|
||||
let boxed_fn_name_ident = format_ident!("boxed_{}", fn_name_str);
|
||||
let _visibility = &ast.vis;
|
||||
|
||||
let (summary_text, description_text) = extract_doc_from_attrs(&ast.attrs);
|
||||
let doc_info = extract_doc_from_attrs(&ast.attrs);
|
||||
let comment_text = {
|
||||
let mut buf = String::new();
|
||||
buf.push_str("Std lib function: ");
|
||||
buf.push_str(&name_str);
|
||||
if let Some(s) = &summary_text {
|
||||
if let Some(s) = &doc_info.summary {
|
||||
buf.push_str("\n");
|
||||
buf.push_str(&s);
|
||||
}
|
||||
if let Some(s) = &description_text {
|
||||
if let Some(s) = &doc_info.description {
|
||||
buf.push_str("\n");
|
||||
buf.push_str(&s);
|
||||
}
|
||||
@ -129,17 +150,60 @@ fn do_stdlib_inner(
|
||||
#[doc = #comment_text]
|
||||
};
|
||||
|
||||
let summary = if let Some(summary) = summary_text {
|
||||
let summary = if let Some(summary) = doc_info.summary {
|
||||
quote! { #summary }
|
||||
} else {
|
||||
quote! { "" }
|
||||
};
|
||||
let description = if let Some(description) = description_text {
|
||||
let description = if let Some(description) = doc_info.description {
|
||||
quote! { #description }
|
||||
} else {
|
||||
quote! { "" }
|
||||
};
|
||||
|
||||
let cb = doc_info.code_blocks.clone();
|
||||
let code_blocks = if !cb.is_empty() {
|
||||
quote! {
|
||||
let code_blocks = vec![#(#cb),*];
|
||||
code_blocks.iter().map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
}).collect::<Vec<String>>()
|
||||
}
|
||||
} else {
|
||||
errors.push(Error::new_spanned(
|
||||
&ast.sig,
|
||||
"stdlib functions must have at least one code block",
|
||||
));
|
||||
|
||||
quote! { vec![] }
|
||||
};
|
||||
|
||||
// Make sure the function name is in all the code blocks.
|
||||
for code_block in doc_info.code_blocks.iter() {
|
||||
if !code_block.contains(&name) {
|
||||
errors.push(Error::new_spanned(
|
||||
&ast.sig,
|
||||
format!(
|
||||
"stdlib functions must have the function name `{}` in the code block",
|
||||
name
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let test_code_blocks = doc_info
|
||||
.code_blocks
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, code_block)| generate_code_block_test(&fn_name_str, code_block, index))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let tags = metadata
|
||||
.tags
|
||||
.iter()
|
||||
@ -242,7 +306,7 @@ fn do_stdlib_inner(
|
||||
let mut args = args.iter();
|
||||
let ok = args.next().unwrap();
|
||||
if let syn::GenericArgument::Type(ty) = ok {
|
||||
let ty = unbox(unbox_vec(ty.clone()));
|
||||
let ty = unbox(ty.clone());
|
||||
quote! { #ty }
|
||||
} else {
|
||||
quote! { () }
|
||||
@ -254,7 +318,7 @@ fn do_stdlib_inner(
|
||||
quote! { () }
|
||||
}
|
||||
} else {
|
||||
let ty = unbox(unbox_vec(*ty.clone()));
|
||||
let ty = unbox(*ty.clone());
|
||||
quote! { #ty }
|
||||
}
|
||||
} else {
|
||||
@ -295,9 +359,16 @@ fn do_stdlib_inner(
|
||||
pub(crate) const #name_ident: #name_ident = #name_ident {};
|
||||
};
|
||||
|
||||
let test_mod_name = format_ident!("test_examples_{}", fn_name_str);
|
||||
|
||||
// The final TokenStream returned will have a few components that reference
|
||||
// `#name_ident`, the name of the function to which this macro was applied...
|
||||
let stream = quote! {
|
||||
#[cfg(test)]
|
||||
mod #test_mod_name {
|
||||
#(#test_code_blocks)*
|
||||
}
|
||||
|
||||
// ... a struct type called `#name_ident` that has no members
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#description_doc_comment
|
||||
@ -359,6 +430,10 @@ fn do_stdlib_inner(
|
||||
#deprecated
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
#code_blocks
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
#boxed_fn_name_ident
|
||||
}
|
||||
@ -394,10 +469,18 @@ fn get_crate(var: Option<String>) -> proc_macro2::TokenStream {
|
||||
quote!(crate::docs)
|
||||
}
|
||||
|
||||
fn extract_doc_from_attrs(attrs: &[syn::Attribute]) -> (Option<String>, Option<String>) {
|
||||
let doc = syn::Ident::new("doc", proc_macro2::Span::call_site());
|
||||
#[derive(Debug)]
|
||||
struct DocInfo {
|
||||
pub summary: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub code_blocks: Vec<String>,
|
||||
}
|
||||
|
||||
let mut lines = attrs.iter().flat_map(|attr| {
|
||||
fn extract_doc_from_attrs(attrs: &[syn::Attribute]) -> DocInfo {
|
||||
let doc = syn::Ident::new("doc", proc_macro2::Span::call_site());
|
||||
let mut code_blocks: Vec<String> = Vec::new();
|
||||
|
||||
let raw_lines = attrs.iter().flat_map(|attr| {
|
||||
if let syn::Meta::NameValue(nv) = &attr.meta {
|
||||
if nv.path.is_ident(&doc) {
|
||||
if let syn::Expr::Lit(syn::ExprLit {
|
||||
@ -411,6 +494,53 @@ fn extract_doc_from_attrs(attrs: &[syn::Attribute]) -> (Option<String>, Option<S
|
||||
Vec::new()
|
||||
});
|
||||
|
||||
// Parse any code blocks from the doc string.
|
||||
let mut code_block: Option<String> = None;
|
||||
let mut parsed_lines = Vec::new();
|
||||
for line in raw_lines {
|
||||
if line.starts_with("```") {
|
||||
if let Some(ref inner_code_block) = code_block {
|
||||
code_blocks.push(inner_code_block.trim().to_string());
|
||||
code_block = None;
|
||||
} else {
|
||||
code_block = Some(String::new());
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if let Some(ref mut code_block) = code_block {
|
||||
code_block.push_str(&line);
|
||||
code_block.push('\n');
|
||||
} else {
|
||||
parsed_lines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse code blocks that start with a tab or a space.
|
||||
let mut lines = Vec::new();
|
||||
for line in parsed_lines {
|
||||
if line.starts_with(" ") || line.starts_with('\t') {
|
||||
if let Some(ref mut code_block) = code_block {
|
||||
code_block.push_str(&line.trim_start_matches(" ").trim_start_matches('\t'));
|
||||
code_block.push('\n');
|
||||
} else {
|
||||
code_block = Some(format!("{}\n", line));
|
||||
}
|
||||
} else {
|
||||
if let Some(ref inner_code_block) = code_block {
|
||||
code_blocks.push(inner_code_block.trim().to_string());
|
||||
code_block = None;
|
||||
}
|
||||
lines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
let mut lines = lines.into_iter();
|
||||
|
||||
if let Some(code_block) = code_block {
|
||||
code_blocks.push(code_block.trim().to_string());
|
||||
}
|
||||
|
||||
// Skip initial blank lines; they make for excessively terse summaries.
|
||||
let summary = loop {
|
||||
match lines.next() {
|
||||
@ -426,7 +556,7 @@ fn extract_doc_from_attrs(attrs: &[syn::Attribute]) -> (Option<String>, Option<S
|
||||
}
|
||||
};
|
||||
|
||||
match (summary, first) {
|
||||
let (summary, description) = match (summary, first) {
|
||||
(None, _) => (None, None),
|
||||
(summary, None) => (summary, None),
|
||||
(Some(summary), Some(first)) => (
|
||||
@ -449,6 +579,12 @@ fn extract_doc_from_attrs(attrs: &[syn::Attribute]) -> (Option<String>, Option<S
|
||||
.to_string(),
|
||||
),
|
||||
),
|
||||
};
|
||||
|
||||
DocInfo {
|
||||
summary,
|
||||
description,
|
||||
code_blocks,
|
||||
}
|
||||
}
|
||||
|
||||
@ -458,16 +594,34 @@ fn normalize_comment_string(s: String) -> Vec<String> {
|
||||
.map(|(idx, s)| {
|
||||
// Rust-style comments are intrinsically single-line. We don't want
|
||||
// to trim away formatting such as an initial '*'.
|
||||
// We also don't want to trim away a tab character, which is
|
||||
// used to denote a code block. Code blocks can also be denoted
|
||||
// by four spaces, but we don't want to trim those away either.
|
||||
// We only want to trim a single space character from the start of
|
||||
// a line, and only if it's the first character.
|
||||
let new = s
|
||||
.chars()
|
||||
.enumerate()
|
||||
.flat_map(|(idx, c)| {
|
||||
if idx == 0 {
|
||||
if c == ' ' {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(c)
|
||||
})
|
||||
.collect::<String>()
|
||||
.trim_end()
|
||||
.to_string();
|
||||
let s = new.as_str();
|
||||
|
||||
if idx == 0 {
|
||||
s.trim_start().trim_end()
|
||||
s
|
||||
} else {
|
||||
let trimmed = s.trim_start().trim_end();
|
||||
trimmed
|
||||
.strip_prefix("* ")
|
||||
.unwrap_or_else(|| trimmed.strip_prefix('*').unwrap_or(trimmed))
|
||||
s.strip_prefix("* ").unwrap_or_else(|| s.strip_prefix('*').unwrap_or(s))
|
||||
}
|
||||
.to_string()
|
||||
})
|
||||
.map(ToString::to_string)
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -575,319 +729,59 @@ fn parse_array_type(type_name: &str) -> Option<(&str, usize)> {
|
||||
Some((inner_type.as_str(), length))
|
||||
}
|
||||
|
||||
// Unbox a syn::Type that is boxed to the inner object.
|
||||
fn unbox(t: syn::Type) -> syn::Type {
|
||||
match t {
|
||||
syn::Type::Path(syn::TypePath { ref path, .. }) => {
|
||||
let path = &path.segments;
|
||||
if path.len() == 1 {
|
||||
let seg = &path[0];
|
||||
if seg.ident == "Box" {
|
||||
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { args, .. }) =
|
||||
&seg.arguments
|
||||
{
|
||||
if args.len() == 1 {
|
||||
let mut args = args.iter();
|
||||
let ok = args.next().unwrap();
|
||||
if let syn::GenericArgument::Type(ty) = ok {
|
||||
return ty.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// For each kcl code block, we want to generate a test that checks that the
|
||||
// code block is valid kcl code and compiles and executes.
|
||||
fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> proc_macro2::TokenStream {
|
||||
let test_name = format_ident!("serial_test_example_{}{}", fn_name, index);
|
||||
|
||||
// TODO: We ignore import for now, because the files don't exist and we just want
|
||||
// to show easy imports.
|
||||
let ignored = if fn_name == "import" {
|
||||
quote! { #[ignore] }
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
|
||||
quote! {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
#ignored
|
||||
async fn #test_name() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
// For file conversions we need this to be long.
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
// For file conversions we need this to be long.
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
|
||||
// Create the client.
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await.unwrap();
|
||||
|
||||
let tokens = crate::token::lexer(#code_block);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(crate::engine::conn::EngineConnection::new(ws).await.unwrap())),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx).await.unwrap();
|
||||
}
|
||||
_ => {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
t
|
||||
}
|
||||
|
||||
// For a Vec<Box<T>> return Vec<T>.
|
||||
// For a Vec<T> return Vec<T>.
|
||||
// For a Box<T> return T.
|
||||
fn unbox_vec(t: syn::Type) -> syn::Type {
|
||||
match t {
|
||||
syn::Type::Path(syn::TypePath { ref path, .. }) => {
|
||||
let path = &path.segments;
|
||||
if path.len() == 1 {
|
||||
let seg = &path[0];
|
||||
if seg.ident == "Vec" {
|
||||
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { args, .. }) =
|
||||
&seg.arguments
|
||||
{
|
||||
if args.len() == 1 {
|
||||
let mut args = args.iter();
|
||||
let ok = args.next().unwrap();
|
||||
if let syn::GenericArgument::Type(ty) = ok {
|
||||
let unboxed = unbox(ty.clone());
|
||||
// Wrap it back in a vec.
|
||||
let wrapped = syn::Type::Path(syn::TypePath {
|
||||
qself: None,
|
||||
path: syn::Path {
|
||||
leading_colon: None,
|
||||
segments: {
|
||||
let mut segments = syn::punctuated::Punctuated::new();
|
||||
segments.push_value(syn::PathSegment {
|
||||
ident: syn::Ident::new("Vec", proc_macro2::Span::call_site()),
|
||||
arguments: syn::PathArguments::AngleBracketed(
|
||||
syn::AngleBracketedGenericArguments {
|
||||
colon2_token: None,
|
||||
lt_token: syn::token::Lt::default(),
|
||||
args: {
|
||||
let mut args = syn::punctuated::Punctuated::new();
|
||||
args.push_value(syn::GenericArgument::Type(unboxed));
|
||||
args
|
||||
},
|
||||
gt_token: syn::token::Gt::default(),
|
||||
},
|
||||
),
|
||||
});
|
||||
segments
|
||||
},
|
||||
},
|
||||
});
|
||||
return wrapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
t
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use quote::quote;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_get_inner_array_type() {
|
||||
for (expected, input) in [
|
||||
(Some(("f64", 2)), "[f64;2]"),
|
||||
(Some(("String", 2)), "[String; 2]"),
|
||||
(Some(("Option<String>", 12)), "[Option<String>;12]"),
|
||||
(Some(("Option<String>", 12)), "[Option<String>; 12]"),
|
||||
] {
|
||||
let actual = parse_array_type(input);
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_line_to() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "lineTo",
|
||||
},
|
||||
quote! {
|
||||
fn inner_line_to(
|
||||
data: LineToData,
|
||||
sketch_group: SketchGroup,
|
||||
args: &Args,
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/lineTo.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_min() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "min",
|
||||
},
|
||||
quote! {
|
||||
fn inner_min(
|
||||
/// The args to do shit to.
|
||||
args: Vec<f64>
|
||||
) -> f64 {
|
||||
let mut min = std::f64::MAX;
|
||||
for arg in args.iter() {
|
||||
if *arg < min {
|
||||
min = *arg;
|
||||
}
|
||||
}
|
||||
|
||||
min
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/min.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_show() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
_args: Vec<f64>
|
||||
) {
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/show.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_box() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
args: Box<f64>
|
||||
) -> Box<f64> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/box.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_option() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
args: Option<f64>
|
||||
) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/option.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_array() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
args: [f64; 2]
|
||||
) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/array.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_option_input_format() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/option_input_format.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_return_vec_sketch_group() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<SketchGroup>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/return_vec_sketch_group.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_return_vec_box_sketch_group() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/return_vec_box_sketch_group.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
461
src/wasm-lib/derive-docs/src/tests.rs
Normal file
461
src/wasm-lib/derive-docs/src/tests.rs
Normal file
@ -0,0 +1,461 @@
|
||||
use quote::quote;
|
||||
|
||||
use crate::{do_stdlib, parse_array_type};
|
||||
|
||||
#[test]
|
||||
fn test_get_inner_array_type() {
|
||||
for (expected, input) in [
|
||||
(Some(("f64", 2)), "[f64;2]"),
|
||||
(Some(("String", 2)), "[String; 2]"),
|
||||
(Some(("Option<String>", 12)), "[Option<String>;12]"),
|
||||
(Some(("Option<String>", 12)), "[Option<String>; 12]"),
|
||||
] {
|
||||
let actual = parse_array_type(input);
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_line_to() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "lineTo",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// lineTo
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// lineTo
|
||||
/// ```
|
||||
fn inner_line_to(
|
||||
data: LineToData,
|
||||
sketch_group: SketchGroup,
|
||||
args: &Args,
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/lineTo.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_min() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "min",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// min
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// min
|
||||
/// ```
|
||||
fn inner_min(
|
||||
/// The args to do shit to.
|
||||
args: Vec<f64>
|
||||
) -> f64 {
|
||||
let mut min = std::f64::MAX;
|
||||
for arg in args.iter() {
|
||||
if *arg < min {
|
||||
min = *arg;
|
||||
}
|
||||
}
|
||||
|
||||
min
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/min.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_show() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// show
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
_args: Vec<f64>
|
||||
) {
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/show.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_box() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// show
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
args: Box<f64>
|
||||
) -> Box<f64> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/box.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_option() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// show
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
args: Option<f64>
|
||||
) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/option.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_array() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// show
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// show
|
||||
/// ```
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
args: [f64; 2]
|
||||
) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/array.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_option_input_format() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// import
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/option_input_format.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_return_vec_sketch_group() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// import
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<SketchGroup>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/return_vec_sketch_group.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_return_vec_box_sketch_group() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// import
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/return_vec_box_sketch_group.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_doc_comment_with_code() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "myFunc",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// myFunc
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// myFunc
|
||||
/// ```
|
||||
fn inner_my_func(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/doc_comment_with_code.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_doc_comment_with_code_on_ignored_function() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// import
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// import
|
||||
/// ```
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/doc_comment_with_code_on_ignored_function.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_fail_non_camel_case() {
|
||||
let (_, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import_thing",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// ```
|
||||
fn inner_import_thing(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(!errors.is_empty());
|
||||
assert_eq!(
|
||||
errors[1].to_string(),
|
||||
"stdlib function names must be in camel case: `import_thing`"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_fail_no_code_block() {
|
||||
let (_, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(!errors.is_empty());
|
||||
assert_eq!(
|
||||
errors[1].to_string(),
|
||||
"stdlib functions must have at least one code block"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_fail_name_not_in_code_block() {
|
||||
let (_, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// ```
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(!errors.is_empty());
|
||||
assert_eq!(
|
||||
errors[1].to_string(),
|
||||
"stdlib functions must have the function name `import` in the code block"
|
||||
);
|
||||
}
|
91
src/wasm-lib/derive-docs/src/unbox.rs
Normal file
91
src/wasm-lib/derive-docs/src/unbox.rs
Normal file
@ -0,0 +1,91 @@
|
||||
// Unbox a Vec<Box<T>> to Vec<T>.
|
||||
// Unbox a Box<T> to T.
|
||||
pub(crate) fn unbox(t: syn::Type) -> syn::Type {
|
||||
unbox_inner(unbox_vec(t))
|
||||
}
|
||||
|
||||
// Unbox a syn::Type that is boxed to the inner object.
|
||||
fn unbox_inner(t: syn::Type) -> syn::Type {
|
||||
match t {
|
||||
syn::Type::Path(syn::TypePath { ref path, .. }) => {
|
||||
let path = &path.segments;
|
||||
if path.len() == 1 {
|
||||
let seg = &path[0];
|
||||
if seg.ident == "Box" {
|
||||
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { args, .. }) =
|
||||
&seg.arguments
|
||||
{
|
||||
if args.len() == 1 {
|
||||
let mut args = args.iter();
|
||||
let ok = args.next().unwrap();
|
||||
if let syn::GenericArgument::Type(ty) = ok {
|
||||
return ty.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
t
|
||||
}
|
||||
|
||||
// For a Vec<Box<T>> return Vec<T>.
|
||||
// For a Vec<T> return Vec<T>.
|
||||
fn unbox_vec(t: syn::Type) -> syn::Type {
|
||||
match t {
|
||||
syn::Type::Path(syn::TypePath { ref path, .. }) => {
|
||||
let path = &path.segments;
|
||||
if path.len() == 1 {
|
||||
let seg = &path[0];
|
||||
if seg.ident == "Vec" {
|
||||
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { args, .. }) =
|
||||
&seg.arguments
|
||||
{
|
||||
if args.len() == 1 {
|
||||
let mut args = args.iter();
|
||||
let ok = args.next().unwrap();
|
||||
if let syn::GenericArgument::Type(ty) = ok {
|
||||
let unboxed = unbox(ty.clone());
|
||||
// Wrap it back in a vec.
|
||||
let wrapped = syn::Type::Path(syn::TypePath {
|
||||
qself: None,
|
||||
path: syn::Path {
|
||||
leading_colon: None,
|
||||
segments: {
|
||||
let mut segments = syn::punctuated::Punctuated::new();
|
||||
segments.push_value(syn::PathSegment {
|
||||
ident: syn::Ident::new("Vec", proc_macro2::Span::call_site()),
|
||||
arguments: syn::PathArguments::AngleBracketed(
|
||||
syn::AngleBracketedGenericArguments {
|
||||
colon2_token: None,
|
||||
lt_token: syn::token::Lt::default(),
|
||||
args: {
|
||||
let mut args = syn::punctuated::Punctuated::new();
|
||||
args.push_value(syn::GenericArgument::Type(unboxed));
|
||||
args
|
||||
},
|
||||
gt_token: syn::token::Gt::default(),
|
||||
},
|
||||
),
|
||||
});
|
||||
segments
|
||||
},
|
||||
},
|
||||
});
|
||||
return wrapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
t
|
||||
}
|
@ -1,11 +1,94 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_show {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_show0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nshow");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_show1() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Show {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Show: Show = Show {};
|
||||
fn boxed_show(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +108,11 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +151,24 @@ impl crate::docs::StdLibFn for Show {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec![
|
||||
"This is another code block.\nyes sirrr.\nshow",
|
||||
"This is code.\nIt does other shit.\nshow",
|
||||
];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_show
|
||||
}
|
||||
@ -77,6 +178,18 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" show"]
|
||||
#[doc = r""]
|
||||
#[doc = r" ```"]
|
||||
#[doc = r" This is another code block."]
|
||||
#[doc = r" yes sirrr."]
|
||||
#[doc = r" show"]
|
||||
#[doc = r" ```"]
|
||||
fn inner_show(#[doc = r" The args to do shit to."] args: [f64; 2]) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
|
@ -1,11 +1,54 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_show {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_show0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Show {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Show: Show = Show {};
|
||||
fn boxed_show(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +68,11 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +111,21 @@ impl crate::docs::StdLibFn for Show {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["This is code.\nIt does other shit.\nshow"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_show
|
||||
}
|
||||
@ -77,6 +135,12 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" show"]
|
||||
fn inner_show(#[doc = r" The args to do shit to."] args: Box<f64>) -> Box<f64> {
|
||||
args
|
||||
}
|
||||
|
197
src/wasm-lib/derive-docs/tests/doc_comment_with_code.gen
Normal file
197
src/wasm-lib/derive-docs/tests/doc_comment_with_code.gen
Normal file
@ -0,0 +1,197 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_my_func {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_my_func0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nmyFunc");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_my_func1() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nmyFunc");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: myFunc\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct MyFunc {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: myFunc\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const MyFunc: MyFunc = MyFunc {};
|
||||
fn boxed_my_func(
|
||||
args: crate::std::Args,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn std::future::Future<
|
||||
Output = anyhow::Result<crate::executor::MemoryItem, crate::errors::KclError>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
Box::pin(my_func(args))
|
||||
}
|
||||
|
||||
impl crate::docs::StdLibFn for MyFunc {
|
||||
fn name(&self) -> String {
|
||||
"myFunc".to_string()
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn args(&self) -> Vec<crate::docs::StdLibFnArg> {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = true;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "args".to_string(),
|
||||
type_: "kittycad::types::InputFormat".to_string(),
|
||||
schema: <Option<kittycad::types::InputFormat>>::json_schema(&mut generator),
|
||||
required: false,
|
||||
}]
|
||||
}
|
||||
|
||||
fn return_value(&self) -> Option<crate::docs::StdLibFnArg> {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = true;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "[SketchGroup]".to_string(),
|
||||
schema: <Vec<SketchGroup>>::json_schema(&mut generator),
|
||||
required: true,
|
||||
})
|
||||
}
|
||||
|
||||
fn unpublished(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn deprecated(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec![
|
||||
"This is another code block.\nyes sirrr.\nmyFunc",
|
||||
"This is code.\nIt does other shit.\nmyFunc",
|
||||
];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_my_func
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" myFunc"]
|
||||
#[doc = r""]
|
||||
#[doc = r" ```"]
|
||||
#[doc = r" This is another code block."]
|
||||
#[doc = r" yes sirrr."]
|
||||
#[doc = r" myFunc"]
|
||||
#[doc = r" ```"]
|
||||
fn inner_my_func(
|
||||
#[doc = r" The args to do shit to."] args: Option<kittycad::types::InputFormat>,
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_import {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
#[ignore]
|
||||
async fn serial_test_example_import0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nimport");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
#[ignore]
|
||||
async fn serial_test_example_import1() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nimport");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Import {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Import: Import = Import {};
|
||||
fn boxed_import(
|
||||
args: crate::std::Args,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn std::future::Future<
|
||||
Output = anyhow::Result<crate::executor::MemoryItem, crate::errors::KclError>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
Box::pin(import(args))
|
||||
}
|
||||
|
||||
impl crate::docs::StdLibFn for Import {
|
||||
fn name(&self) -> String {
|
||||
"import".to_string()
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn args(&self) -> Vec<crate::docs::StdLibFnArg> {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = true;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "args".to_string(),
|
||||
type_: "kittycad::types::InputFormat".to_string(),
|
||||
schema: <Option<kittycad::types::InputFormat>>::json_schema(&mut generator),
|
||||
required: false,
|
||||
}]
|
||||
}
|
||||
|
||||
fn return_value(&self) -> Option<crate::docs::StdLibFnArg> {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = true;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "[SketchGroup]".to_string(),
|
||||
schema: <Vec<SketchGroup>>::json_schema(&mut generator),
|
||||
required: true,
|
||||
})
|
||||
}
|
||||
|
||||
fn unpublished(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn deprecated(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec![
|
||||
"This is another code block.\nyes sirrr.\nimport",
|
||||
"This is code.\nIt does other shit.\nimport",
|
||||
];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_import
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" import"]
|
||||
#[doc = r""]
|
||||
#[doc = r" ```"]
|
||||
#[doc = r" This is another code block."]
|
||||
#[doc = r" yes sirrr."]
|
||||
#[doc = r" import"]
|
||||
#[doc = r" ```"]
|
||||
fn inner_import(
|
||||
#[doc = r" The args to do shit to."] args: Option<kittycad::types::InputFormat>,
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
@ -1,11 +1,94 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_line_to {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_line_to0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nlineTo");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_line_to1() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nlineTo");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: lineTo"]
|
||||
#[doc = "Std lib function: lineTo\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct LineTo {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: lineTo"]
|
||||
#[doc = "Std lib function: lineTo\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const LineTo: LineTo = LineTo {};
|
||||
fn boxed_line_to(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +108,11 @@ impl crate::docs::StdLibFn for LineTo {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -76,6 +159,24 @@ impl crate::docs::StdLibFn for LineTo {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec![
|
||||
"This is another code block.\nyes sirrr.\nlineTo",
|
||||
"This is code.\nIt does other shit.\nlineTo",
|
||||
];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_line_to
|
||||
}
|
||||
@ -85,6 +186,18 @@ impl crate::docs::StdLibFn for LineTo {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" lineTo"]
|
||||
#[doc = r""]
|
||||
#[doc = r" ```"]
|
||||
#[doc = r" This is another code block."]
|
||||
#[doc = r" yes sirrr."]
|
||||
#[doc = r" lineTo"]
|
||||
#[doc = r" ```"]
|
||||
fn inner_line_to(
|
||||
data: LineToData,
|
||||
sketch_group: SketchGroup,
|
||||
|
@ -1,11 +1,94 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_min {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_min0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nmin");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_min1() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nmin");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: min"]
|
||||
#[doc = "Std lib function: min\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Min {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: min"]
|
||||
#[doc = "Std lib function: min\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Min: Min = Min {};
|
||||
fn boxed_min(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +108,11 @@ impl crate::docs::StdLibFn for Min {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +151,24 @@ impl crate::docs::StdLibFn for Min {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec![
|
||||
"This is another code block.\nyes sirrr.\nmin",
|
||||
"This is code.\nIt does other shit.\nmin",
|
||||
];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_min
|
||||
}
|
||||
@ -77,6 +178,18 @@ impl crate::docs::StdLibFn for Min {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" min"]
|
||||
#[doc = r""]
|
||||
#[doc = r" ```"]
|
||||
#[doc = r" This is another code block."]
|
||||
#[doc = r" yes sirrr."]
|
||||
#[doc = r" min"]
|
||||
#[doc = r" ```"]
|
||||
fn inner_min(#[doc = r" The args to do shit to."] args: Vec<f64>) -> f64 {
|
||||
let mut min = std::f64::MAX;
|
||||
for arg in args.iter() {
|
||||
|
@ -1,11 +1,54 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_show {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_show0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Show {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Show: Show = Show {};
|
||||
fn boxed_show(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +68,11 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +111,21 @@ impl crate::docs::StdLibFn for Show {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["This is code.\nIt does other shit.\nshow"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_show
|
||||
}
|
||||
@ -77,6 +135,12 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" show"]
|
||||
fn inner_show(#[doc = r" The args to do shit to."] args: Option<f64>) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
|
@ -1,11 +1,55 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_import {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
#[ignore]
|
||||
async fn serial_test_example_import0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nimport");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: import"]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Import {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: import"]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Import: Import = Import {};
|
||||
fn boxed_import(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +69,11 @@ impl crate::docs::StdLibFn for Import {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +112,21 @@ impl crate::docs::StdLibFn for Import {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["This is code.\nIt does other shit.\nimport"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_import
|
||||
}
|
||||
@ -77,6 +136,12 @@ impl crate::docs::StdLibFn for Import {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" import"]
|
||||
fn inner_import(
|
||||
#[doc = r" The args to do shit to."] args: Option<kittycad::types::InputFormat>,
|
||||
) -> Result<Box<f64>> {
|
||||
|
@ -1,11 +1,55 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_import {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
#[ignore]
|
||||
async fn serial_test_example_import0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nimport");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: import"]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Import {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: import"]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Import: Import = Import {};
|
||||
fn boxed_import(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +69,11 @@ impl crate::docs::StdLibFn for Import {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +112,21 @@ impl crate::docs::StdLibFn for Import {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["This is code.\nIt does other shit.\nimport"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_import
|
||||
}
|
||||
@ -77,6 +136,12 @@ impl crate::docs::StdLibFn for Import {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" import"]
|
||||
fn inner_import(
|
||||
#[doc = r" The args to do shit to."] args: Option<kittycad::types::InputFormat>,
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
|
@ -1,11 +1,55 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_import {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
#[ignore]
|
||||
async fn serial_test_example_import0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nimport");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: import"]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Import {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: import"]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Import: Import = Import {};
|
||||
fn boxed_import(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +69,11 @@ impl crate::docs::StdLibFn for Import {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +112,21 @@ impl crate::docs::StdLibFn for Import {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["This is code.\nIt does other shit.\nimport"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_import
|
||||
}
|
||||
@ -77,6 +136,12 @@ impl crate::docs::StdLibFn for Import {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" import"]
|
||||
fn inner_import(
|
||||
#[doc = r" The args to do shit to."] args: Option<kittycad::types::InputFormat>,
|
||||
) -> Result<Vec<SketchGroup>> {
|
||||
|
@ -1,11 +1,54 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_show {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_show0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Show {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Show: Show = Show {};
|
||||
fn boxed_show(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +68,11 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +111,21 @@ impl crate::docs::StdLibFn for Show {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["This is code.\nIt does other shit.\nshow"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_show
|
||||
}
|
||||
@ -77,4 +135,10 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" show"]
|
||||
fn inner_show(#[doc = r" The args to do shit to."] _args: Vec<f64>) {}
|
||||
|
Reference in New Issue
Block a user