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:
Jess Frazelle
2024-03-13 12:56:46 -07:00
committed by GitHub
parent 6bab45a56a
commit a60bdd4cc3
36 changed files with 3584 additions and 538 deletions

View File

@ -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"

View File

@ -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(),
);
}
}

View 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"
);
}

View 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
}

View File

@ -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
}

View File

@ -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
}

View 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
}

View File

@ -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
}

View File

@ -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,

View File

@ -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() {

View File

@ -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
}

View File

@ -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>> {

View File

@ -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>>> {

View File

@ -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>> {

View File

@ -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>) {}