BREAKING: KCL @settings are the source of truth for units (#5808)
This commit is contained in:
		@ -816,7 +816,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
 | 
			
		||||
        async fn #test_name() -> miette::Result<()> {
 | 
			
		||||
            let code = #code_block;
 | 
			
		||||
            // Note, `crate` must be kcl_lib
 | 
			
		||||
            let result = match crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm, None).await {
 | 
			
		||||
            let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
                Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                    return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                        error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -31,13 +31,7 @@ mod test_examples_someFn {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_someFn0() -> miette::Result<()> {
 | 
			
		||||
        let code = "someFn()";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -31,13 +31,7 @@ mod test_examples_someFn {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_someFn0() -> miette::Result<()> {
 | 
			
		||||
        let code = "someFn()";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -32,13 +32,7 @@ mod test_examples_show {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_show0() -> miette::Result<()> {
 | 
			
		||||
        let code = "This is another code block.\nyes sirrr.\nshow";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -32,13 +32,7 @@ mod test_examples_show {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_show0() -> miette::Result<()> {
 | 
			
		||||
        let code = "This is code.\nIt does other shit.\nshow";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -33,13 +33,7 @@ mod test_examples_my_func {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_my_func0() -> miette::Result<()> {
 | 
			
		||||
        let code = "This is another code block.\nyes sirrr.\nmyFunc";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -33,13 +33,7 @@ mod test_examples_line_to {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_line_to0() -> miette::Result<()> {
 | 
			
		||||
        let code = "This is another code block.\nyes sirrr.\nlineTo";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -32,13 +32,7 @@ mod test_examples_min {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_min0() -> miette::Result<()> {
 | 
			
		||||
        let code = "This is another code block.\nyes sirrr.\nmin";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -32,13 +32,7 @@ mod test_examples_show {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_show0() -> miette::Result<()> {
 | 
			
		||||
        let code = "This is code.\nIt does other shit.\nshow";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -32,13 +32,7 @@ mod test_examples_import {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_import0() -> miette::Result<()> {
 | 
			
		||||
        let code = "This is code.\nIt does other shit.\nimport";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -32,13 +32,7 @@ mod test_examples_import {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_import0() -> miette::Result<()> {
 | 
			
		||||
        let code = "This is code.\nIt does other shit.\nimport";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -32,13 +32,7 @@ mod test_examples_import {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_import0() -> miette::Result<()> {
 | 
			
		||||
        let code = "This is code.\nIt does other shit.\nimport";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -32,13 +32,7 @@ mod test_examples_show {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_show0() -> miette::Result<()> {
 | 
			
		||||
        let code = "This is code.\nIt does other shit.\nshow";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -31,13 +31,7 @@ mod test_examples_some_function {
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 | 
			
		||||
    async fn kcl_test_example_some_function0() -> miette::Result<()> {
 | 
			
		||||
        let code = "someFunction()";
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(
 | 
			
		||||
            code,
 | 
			
		||||
            crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        {
 | 
			
		||||
        let result = match crate::test_server::execute_and_snapshot(code, None).await {
 | 
			
		||||
            Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                    error: e.error,
 | 
			
		||||
 | 
			
		||||
@ -76,7 +76,7 @@ fn run_benchmarks(c: &mut Criterion) {
 | 
			
		||||
        group.bench_function(format!("execute_{}", dir_name), |b| {
 | 
			
		||||
            b.iter(|| {
 | 
			
		||||
                if let Err(err) = rt.block_on(async {
 | 
			
		||||
                    let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default()).await?;
 | 
			
		||||
                    let ctx = kcl_lib::ExecutorContext::new_with_default_client().await?;
 | 
			
		||||
                    let mut exec_state = kcl_lib::ExecState::new(&ctx);
 | 
			
		||||
                    ctx.run(black_box(&program), &mut exec_state).await?;
 | 
			
		||||
                    ctx.close().await;
 | 
			
		||||
 | 
			
		||||
@ -51,45 +51,6 @@ async fn cache_test(
 | 
			
		||||
    img_results
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_cache_change_units_changes_output() {
 | 
			
		||||
    let code = r#"part001 = startSketchOn('XY')
 | 
			
		||||
  |> startProfileAt([5.5229, 5.25217], %)
 | 
			
		||||
  |> line(end = [10.50433, -1.19122])
 | 
			
		||||
  |> line(end = [8.01362, -5.48731])
 | 
			
		||||
  |> line(end = [-1.02877, -6.76825])
 | 
			
		||||
  |> line(end = [-11.53311, 2.81559])
 | 
			
		||||
  |> close()
 | 
			
		||||
  |> extrude(length = 4)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = cache_test(
 | 
			
		||||
        "change_units_changes_output",
 | 
			
		||||
        vec![
 | 
			
		||||
            Variation {
 | 
			
		||||
                code,
 | 
			
		||||
                settings: &kcl_lib::ExecutorSettings {
 | 
			
		||||
                    units: kcl_lib::UnitLength::In,
 | 
			
		||||
                    ..Default::default()
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
            Variation {
 | 
			
		||||
                code,
 | 
			
		||||
                settings: &kcl_lib::ExecutorSettings {
 | 
			
		||||
                    units: kcl_lib::UnitLength::Mm,
 | 
			
		||||
                    ..Default::default()
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
        ],
 | 
			
		||||
    )
 | 
			
		||||
    .await;
 | 
			
		||||
 | 
			
		||||
    let first = result.first().unwrap();
 | 
			
		||||
    let second = result.last().unwrap();
 | 
			
		||||
 | 
			
		||||
    assert!(first.1 != second.1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_cache_change_grid_visualizes_grid_off_to_on() {
 | 
			
		||||
    let code = r#"part001 = startSketchOn('XY')
 | 
			
		||||
@ -261,9 +222,7 @@ async fn kcl_test_cache_empty_file_pop_cache_empty_file_planes_work() {
 | 
			
		||||
    // Get the current working directory.
 | 
			
		||||
    let code = "";
 | 
			
		||||
 | 
			
		||||
    let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default())
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let ctx = kcl_lib::ExecutorContext::new_with_default_client().await.unwrap();
 | 
			
		||||
    let program = kcl_lib::Program::parse_no_errs(code).unwrap();
 | 
			
		||||
    let outcome = ctx.run_with_caching(program).await.unwrap();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								rust/kcl-lib/e2e/executor/inputs/cylinder-inches.kcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								rust/kcl-lib/e2e/executor/inputs/cylinder-inches.kcl
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
@settings(defaultLengthUnit = in)
 | 
			
		||||
sketch001 = startSketchOn(XZ)
 | 
			
		||||
  |> circle(center = [0, 0], radius = 20)
 | 
			
		||||
extrude001 = extrude(sketch001, length = 10)
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
const sketch001 = startSketchOn(XZ)
 | 
			
		||||
@settings(defaultLengthUnit = in)
 | 
			
		||||
sketch001 = startSketchOn(XZ)
 | 
			
		||||
  |> startProfileAt([75.8, 317.2], %)
 | 
			
		||||
  |> angledLine([0, 268.43], %, $rectangleSegmentA001)
 | 
			
		||||
  |> angledLine([
 | 
			
		||||
@ -11,8 +12,8 @@ const sketch001 = startSketchOn(XZ)
 | 
			
		||||
     ], %, $yo)
 | 
			
		||||
  |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
 | 
			
		||||
  |> close()
 | 
			
		||||
const extrude001 = extrude(sketch001, length = 100)
 | 
			
		||||
const chamf = chamfer(
 | 
			
		||||
extrude001 = extrude(sketch001, length = 100)
 | 
			
		||||
chamf = chamfer(
 | 
			
		||||
  extrude001,
 | 
			
		||||
  length = 30,
 | 
			
		||||
  tags = [
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
const sketch001 = startSketchOn(XZ)
 | 
			
		||||
@settings(defaultLengthUnit = in)
 | 
			
		||||
sketch001 = startSketchOn(XZ)
 | 
			
		||||
  |> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
 | 
			
		||||
  |> angledLine([0, 268.43], %, $rectangleSegmentA001)
 | 
			
		||||
  |> angledLine([
 | 
			
		||||
@ -11,7 +12,7 @@ const sketch001 = startSketchOn(XZ)
 | 
			
		||||
     ], %, $yo)
 | 
			
		||||
  |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
 | 
			
		||||
  |> close()
 | 
			
		||||
const extrude001 = extrude(sketch001, length = 100)
 | 
			
		||||
extrude001 = extrude(sketch001, length = 100)
 | 
			
		||||
  |> chamfer(
 | 
			
		||||
       length = 30,
 | 
			
		||||
       tags = [
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ mod cache;
 | 
			
		||||
 | 
			
		||||
use kcl_lib::{
 | 
			
		||||
    test_server::{execute_and_export_step, execute_and_snapshot, execute_and_snapshot_no_auth},
 | 
			
		||||
    ExecError, UnitLength,
 | 
			
		||||
    ExecError,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// The minimum permissible difference between asserted twenty-twenty images.
 | 
			
		||||
@ -26,7 +26,7 @@ pub(crate) fn assert_out(test_name: &str, result: &image::DynamicImage) -> Strin
 | 
			
		||||
async fn kcl_test_fillet_duplicate_tags() {
 | 
			
		||||
    let code = kcl_input!("fillet_duplicate_tags");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    let err = result.expect_err("Code should have failed due to the duplicate edges being filletted");
 | 
			
		||||
 | 
			
		||||
    let err = err.as_kcl_error().unwrap();
 | 
			
		||||
@ -48,7 +48,7 @@ async fn kcl_test_execute_engine_error_return() {
 | 
			
		||||
  |> extrude(length = 4)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -61,7 +61,7 @@ async fn kcl_test_execute_i_shape() {
 | 
			
		||||
    // This is some code from lee that starts a pipe expression with a variable.
 | 
			
		||||
    let code = kcl_input!("i_shape");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("i_shape", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -70,7 +70,7 @@ async fn kcl_test_execute_i_shape() {
 | 
			
		||||
async fn kcl_test_execute_pipes_on_pipes() {
 | 
			
		||||
    let code = kcl_input!("pipes_on_pipes");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("pipes_on_pipes", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -78,7 +78,7 @@ async fn kcl_test_execute_pipes_on_pipes() {
 | 
			
		||||
async fn kcl_test_execute_cylinder() {
 | 
			
		||||
    let code = kcl_input!("cylinder");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("cylinder", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -86,7 +86,7 @@ async fn kcl_test_execute_cylinder() {
 | 
			
		||||
async fn kcl_test_execute_kittycad_svg() {
 | 
			
		||||
    let code = kcl_input!("kittycad_svg");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("kittycad_svg", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -94,7 +94,7 @@ async fn kcl_test_execute_kittycad_svg() {
 | 
			
		||||
async fn kcl_test_execute_lsystem() {
 | 
			
		||||
    let code = kcl_input!("lsystem");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("lsystem", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -102,7 +102,7 @@ async fn kcl_test_execute_lsystem() {
 | 
			
		||||
async fn kcl_test_member_expression_sketch() {
 | 
			
		||||
    let code = kcl_input!("member_expression_sketch");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("member_expression_sketch", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -110,7 +110,7 @@ async fn kcl_test_member_expression_sketch() {
 | 
			
		||||
async fn kcl_test_helix_defaults() {
 | 
			
		||||
    let code = kcl_input!("helix_defaults");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("helix_defaults", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -118,7 +118,7 @@ async fn kcl_test_helix_defaults() {
 | 
			
		||||
async fn kcl_test_helix_defaults_negative_extrude() {
 | 
			
		||||
    let code = kcl_input!("helix_defaults_negative_extrude");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("helix_defaults_negative_extrude", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -126,7 +126,7 @@ async fn kcl_test_helix_defaults_negative_extrude() {
 | 
			
		||||
async fn kcl_test_helix_with_length() {
 | 
			
		||||
    let code = kcl_input!("helix_with_length");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("helix_with_length", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -134,7 +134,7 @@ async fn kcl_test_helix_with_length() {
 | 
			
		||||
async fn kcl_test_dimensions_match() {
 | 
			
		||||
    let code = kcl_input!("dimensions_match");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("dimensions_match", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -142,7 +142,7 @@ async fn kcl_test_dimensions_match() {
 | 
			
		||||
async fn kcl_test_close_arc() {
 | 
			
		||||
    let code = kcl_input!("close_arc");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("close_arc", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -150,7 +150,7 @@ async fn kcl_test_close_arc() {
 | 
			
		||||
async fn kcl_test_negative_args() {
 | 
			
		||||
    let code = kcl_input!("negative_args");
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("negative_args", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -164,7 +164,7 @@ async fn kcl_test_basic_tangential_arc_with_point() {
 | 
			
		||||
    |> extrude(length = 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("tangential_arc_with_point", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -178,7 +178,7 @@ async fn kcl_test_basic_tangential_arc_to() {
 | 
			
		||||
    |> extrude(length = 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("tangential_arc_to", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -205,7 +205,7 @@ box(30, 43, 18, '-xy')
 | 
			
		||||
let thing = box(-12, -15, 10, 'yz')
 | 
			
		||||
box(-20, -5, 10, 'xy')"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("different_planes_same_drawing", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -263,7 +263,7 @@ part004 = startSketchOn(YZ)
 | 
			
		||||
  |> close()
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("lots_of_planes", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -280,7 +280,7 @@ async fn kcl_test_holes() {
 | 
			
		||||
  |> extrude(length = 2)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("holes", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -299,7 +299,7 @@ async fn optional_params() {
 | 
			
		||||
 | 
			
		||||
thing = other_circle([2, 2], 20)
 | 
			
		||||
"#;
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("optional_params", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -335,7 +335,7 @@ part = roundedRectangle([0, 0], 20, 20, 4)
 | 
			
		||||
  |> extrude(length = 2)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("rounded_with_holes", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -343,7 +343,7 @@ part = roundedRectangle([0, 0], 20, 20, 4)
 | 
			
		||||
async fn kcl_test_top_level_expression() {
 | 
			
		||||
    let code = r#"startSketchOn(XY) |> circle(center = [0,0], radius= 22) |> extrude(length = 14)"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("top_level_expression", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -357,7 +357,7 @@ part =  startSketchOn(XY)
 | 
			
		||||
    |> extrude(length = 1)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("patterns_linear_basic_with_math", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -369,7 +369,7 @@ async fn kcl_test_patterns_linear_basic() {
 | 
			
		||||
    |> extrude(length = 1)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("patterns_linear_basic", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -385,7 +385,7 @@ async fn kcl_test_patterns_linear_basic_3d() {
 | 
			
		||||
    |> patternLinear3d(axis = [1, 0, 1], instances = 4, distance = 6)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("patterns_linear_basic_3d", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -397,7 +397,7 @@ async fn kcl_test_patterns_linear_basic_negative_distance() {
 | 
			
		||||
    |> extrude(length = 1)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("patterns_linear_basic_negative_distance", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -409,7 +409,7 @@ async fn kcl_test_patterns_linear_basic_negative_axis() {
 | 
			
		||||
    |> extrude(length = 1)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("patterns_linear_basic_negative_axis", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -430,7 +430,7 @@ rectangle = startSketchOn(XY)
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("patterns_linear_basic_holes", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -442,7 +442,7 @@ async fn kcl_test_patterns_circular_basic_2d() {
 | 
			
		||||
    |> extrude(length = 1)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("patterns_circular_basic_2d", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -458,7 +458,7 @@ async fn kcl_test_patterns_circular_basic_3d() {
 | 
			
		||||
    |> patternCircular3d(axis = [0,0, 1], center = [-20, -20, -20], instances = 41, arcDegrees = 360, rotateDuplicates = false)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("patterns_circular_basic_3d", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -474,7 +474,7 @@ async fn kcl_test_patterns_circular_3d_tilted_axis() {
 | 
			
		||||
    |> patternCircular3d(axis = [1,1,0], center = [10, 0, 10], instances = 11, arcDegrees = 360, rotateDuplicates = true)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("patterns_circular_3d_tilted_axis", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -483,7 +483,7 @@ async fn kcl_test_import_file_doesnt_exist() {
 | 
			
		||||
    let code = r#"import 'thing.obj'
 | 
			
		||||
model = cube"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -496,7 +496,7 @@ async fn kcl_test_import_obj_with_mtl() {
 | 
			
		||||
    let code = r#"import 'e2e/executor/inputs/cube.obj'
 | 
			
		||||
model = cube"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("import_obj_with_mtl", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -506,7 +506,7 @@ async fn kcl_test_import_obj_with_mtl_units() {
 | 
			
		||||
import 'e2e/executor/inputs/cube.obj'
 | 
			
		||||
model = cube"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("import_obj_with_mtl_units", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -515,7 +515,7 @@ async fn kcl_test_import_stl() {
 | 
			
		||||
    let code = r#"import 'e2e/executor/inputs/2-5-long-m8-chc-screw.stl' as screw
 | 
			
		||||
model = screw"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("import_stl", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -524,7 +524,7 @@ async fn kcl_test_import_gltf_with_bin() {
 | 
			
		||||
    let code = r#"import 'e2e/executor/inputs/cube.gltf'
 | 
			
		||||
model = cube"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("import_gltf_with_bin", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -533,7 +533,7 @@ async fn kcl_test_import_gltf_embedded() {
 | 
			
		||||
    let code = r#"import 'e2e/executor/inputs/cube-embedded.gltf' as cube
 | 
			
		||||
model = cube"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("import_gltf_embedded", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -542,7 +542,7 @@ async fn kcl_test_import_glb() {
 | 
			
		||||
    let code = r#"import 'e2e/executor/inputs/cube.glb'
 | 
			
		||||
model = cube"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("import_glb", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -551,7 +551,7 @@ async fn kcl_test_import_glb_no_assign() {
 | 
			
		||||
    let code = r#"import 'e2e/executor/inputs/cube.glb'
 | 
			
		||||
cube"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("import_glb_no_assign", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -561,7 +561,7 @@ async fn kcl_test_import_ext_doesnt_match() {
 | 
			
		||||
import 'e2e/executor/inputs/cube.gltf'
 | 
			
		||||
model = cube"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -586,14 +586,15 @@ async fn kcl_test_cube_mm() {
 | 
			
		||||
myCube = cube([0,0], 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("cube_mm", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_cube_cm() {
 | 
			
		||||
    let code = r#"fn cube = (pos, scale) => {
 | 
			
		||||
  sg = startSketchOn(XY)
 | 
			
		||||
    let code = r#"@settings(defaultLengthUnit = cm)
 | 
			
		||||
fn cube = (pos, scale) => {
 | 
			
		||||
  sg = startSketchOn('XY')
 | 
			
		||||
    |> startProfileAt(pos, %)
 | 
			
		||||
    |> line(end = [0, scale])
 | 
			
		||||
    |> line(end = [scale, 0])
 | 
			
		||||
@ -607,14 +608,15 @@ async fn kcl_test_cube_cm() {
 | 
			
		||||
myCube = cube([0,0], 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Cm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("cube_cm", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_cube_m() {
 | 
			
		||||
    let code = r#"fn cube = (pos, scale) => {
 | 
			
		||||
  sg = startSketchOn(XY)
 | 
			
		||||
    let code = r#"@settings(defaultLengthUnit = m)
 | 
			
		||||
fn cube = (pos, scale) => {
 | 
			
		||||
  sg = startSketchOn('XY')
 | 
			
		||||
    |> startProfileAt(pos, %)
 | 
			
		||||
    |> line(end = [0, scale])
 | 
			
		||||
    |> line(end = [scale, 0])
 | 
			
		||||
@ -628,14 +630,15 @@ async fn kcl_test_cube_m() {
 | 
			
		||||
myCube = cube([0,0], 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::M, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("cube_m", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_cube_in() {
 | 
			
		||||
    let code = r#"fn cube = (pos, scale) => {
 | 
			
		||||
  sg = startSketchOn(XY)
 | 
			
		||||
    let code = r#"@settings(defaultLengthUnit = in)
 | 
			
		||||
fn cube = (pos, scale) => {
 | 
			
		||||
  sg = startSketchOn('XY')
 | 
			
		||||
    |> startProfileAt(pos, %)
 | 
			
		||||
    |> line(end = [0, scale])
 | 
			
		||||
    |> line(end = [scale, 0])
 | 
			
		||||
@ -649,14 +652,15 @@ async fn kcl_test_cube_in() {
 | 
			
		||||
myCube = cube([0,0], 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::In, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("cube_in", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_cube_ft() {
 | 
			
		||||
    let code = r#"fn cube = (pos, scale) => {
 | 
			
		||||
  sg = startSketchOn(XY)
 | 
			
		||||
    let code = r#"@settings(defaultLengthUnit = ft)
 | 
			
		||||
fn cube = (pos, scale) => {
 | 
			
		||||
  sg = startSketchOn('XY')
 | 
			
		||||
    |> startProfileAt(pos, %)
 | 
			
		||||
    |> line(end = [0, scale])
 | 
			
		||||
    |> line(end = [scale, 0])
 | 
			
		||||
@ -670,14 +674,15 @@ async fn kcl_test_cube_ft() {
 | 
			
		||||
myCube = cube([0,0], 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Ft, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("cube_ft", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_cube_yd() {
 | 
			
		||||
    let code = r#"fn cube = (pos, scale) => {
 | 
			
		||||
  sg = startSketchOn(XY)
 | 
			
		||||
    let code = r#"@settings(defaultLengthUnit = yd)
 | 
			
		||||
fn cube = (pos, scale) => {
 | 
			
		||||
  sg = startSketchOn('XY')
 | 
			
		||||
    |> startProfileAt(pos, %)
 | 
			
		||||
    |> line(end = [0, scale])
 | 
			
		||||
    |> line(end = [scale, 0])
 | 
			
		||||
@ -691,7 +696,7 @@ async fn kcl_test_cube_yd() {
 | 
			
		||||
myCube = cube([0,0], 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Yd, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("cube_yd", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -719,7 +724,7 @@ part002 = startSketchOn(part001, part001.sketch.tags.here)
 | 
			
		||||
  |> extrude(length = 1)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
 | 
			
		||||
    let err = result.err().unwrap();
 | 
			
		||||
    let ExecError::Kcl(err) = err else {
 | 
			
		||||
@ -763,7 +768,7 @@ part003 = startSketchOn(part002, "end")
 | 
			
		||||
  |> extrude(length = 5)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("sketch_on_face_of_face", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -780,7 +785,7 @@ async fn kcl_test_stdlib_kcl_error_right_code_path() {
 | 
			
		||||
  |> extrude(length = 2)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    let err = result.err().unwrap();
 | 
			
		||||
    let ExecError::Kcl(err) = err else {
 | 
			
		||||
        panic!("Expected KCL error, found {err}");
 | 
			
		||||
@ -811,7 +816,7 @@ part002 = startSketchOn(part001, "end")
 | 
			
		||||
  |> extrude(length = 5)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("sketch_on_face_circle", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -853,7 +858,7 @@ part = rectShape([0, 0], 20, 20)
 | 
			
		||||
     )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    let err = result.err().unwrap();
 | 
			
		||||
    let ExecError::Kcl(err) = err else {
 | 
			
		||||
        panic!("Expected KCL error, found {err}");
 | 
			
		||||
@ -880,7 +885,7 @@ async fn kcl_test_simple_revolve() {
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("simple_revolve", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -900,7 +905,7 @@ async fn kcl_test_simple_revolve_uppercase() {
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("simple_revolve_uppercase", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -920,7 +925,7 @@ async fn kcl_test_simple_revolve_negative() {
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("simple_revolve_negative", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -940,7 +945,7 @@ async fn kcl_test_revolve_bad_angle_low() {
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert!(result
 | 
			
		||||
@ -966,7 +971,7 @@ async fn kcl_test_revolve_bad_angle_high() {
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert!(result
 | 
			
		||||
@ -992,7 +997,7 @@ async fn kcl_test_simple_revolve_custom_angle() {
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("simple_revolve_custom_angle", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1012,7 +1017,7 @@ async fn kcl_test_simple_revolve_custom_axis() {
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("simple_revolve_custom_axis", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1036,7 +1041,7 @@ sketch001 = startSketchOn(box, "end")
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("revolve_on_edge", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1060,7 +1065,7 @@ sketch001 = startSketchOn(box, revolveAxis)
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
 | 
			
		||||
    result.unwrap_err();
 | 
			
		||||
    //this fails right now, but slightly differently, lets just say its enough for it to fail - mike
 | 
			
		||||
@ -1088,7 +1093,7 @@ sketch001 = startSketchOn(box, "END")
 | 
			
		||||
    )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("revolve_on_face_circle_edge", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1110,7 +1115,7 @@ sketch001 = startSketchOn(box, "END")
 | 
			
		||||
    )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("revolve_on_face_circle", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1136,7 +1141,7 @@ sketch001 = startSketchOn(box, "end")
 | 
			
		||||
  )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("revolve_on_face", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1150,7 +1155,7 @@ async fn kcl_test_basic_revolve_circle() {
 | 
			
		||||
    )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("basic_revolve_circle", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1177,7 +1182,7 @@ part002 = startSketchOn(part001, 'end')
 | 
			
		||||
    |> extrude(length = 5)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("simple_revolve_sketch_on_edge", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1240,7 +1245,7 @@ plumbus1 = circle1
 | 
			
		||||
      )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("plumbus_fillets", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1248,7 +1253,7 @@ plumbus1 = circle1
 | 
			
		||||
async fn kcl_test_empty_file_is_ok() {
 | 
			
		||||
    let code = r#""#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    result.unwrap();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1278,7 +1283,7 @@ async fn kcl_test_member_expression_in_params() {
 | 
			
		||||
capScrew([0, 0.5, 0], 50, 37.5, 50, 25)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("member_expression_in_params", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1323,7 +1328,7 @@ bracket = startSketchOn(XY)
 | 
			
		||||
     )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    result.unwrap();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1343,7 +1348,7 @@ secondSketch = startSketchOn(part001, '')
 | 
			
		||||
  |> extrude(length = 20)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1374,7 +1379,7 @@ extrusion = startSketchOn(XY)
 | 
			
		||||
  |> extrude(length = height)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1407,7 +1412,7 @@ sketch001 = [profile001, profile002]
 | 
			
		||||
 extrude(sketch001, length = 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("array_of_sketches", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1444,7 +1449,7 @@ pattn1 = patternLinear3d(
 | 
			
		||||
     )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("pattern3d_array_of_extrudes", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1492,7 +1497,7 @@ baseExtrusion = extrude(sketch001, length = width)
 | 
			
		||||
 )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("fillets_referencing_other_fillets", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1540,7 +1545,7 @@ baseExtrusion = extrude(sketch001, length = width)
 | 
			
		||||
   )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("chamfers_referencing_other_chamfers", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1560,7 +1565,7 @@ async fn kcl_test_shell_with_tag() {
 | 
			
		||||
  )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("shell_with_tag", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1591,7 +1596,7 @@ pattn1 = patternLinear3d(
 | 
			
		||||
)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("linear_pattern3d_filleted_sketch", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1618,7 +1623,7 @@ pattn2 = patternCircular3d(part001, axis = [0,0, 1], center = [-20, -20, -20], i
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("circular_pattern3d_filleted_sketch", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1644,7 +1649,7 @@ part001 = cube([0,0], 20)
 | 
			
		||||
pattn2 = patternCircular3d(part001, axis = [0,0, 1], center = [-20, -20, -20], instances = 5, arcDegrees = 360, rotateDuplicates = false)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("circular_pattern3d_chamfered_sketch", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1671,7 +1676,7 @@ part001 = cube([0,0], 20)
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    let err = result.err().unwrap();
 | 
			
		||||
    let ExecError::Kcl(err) = err else {
 | 
			
		||||
        panic!("Expected KCL error, found {err}");
 | 
			
		||||
@ -1701,7 +1706,7 @@ async fn kcl_test_duplicate_tags_should_error() {
 | 
			
		||||
let p = triangle(200)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1712,49 +1717,49 @@ let p = triangle(200)
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_global_tags() {
 | 
			
		||||
    let code = kcl_input!("global-tags");
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("global_tags", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_extrude_inside_fn_with_tags() {
 | 
			
		||||
    let code = kcl_input!("extrude-inside-fn-with-tags");
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("extrude-inside-fn-with-tags", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_pattern_vase() {
 | 
			
		||||
    let code = kcl_input!("pattern_vase");
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("pattern_vase", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_scoped_tags() {
 | 
			
		||||
    let code = kcl_input!("scoped-tags");
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("scoped_tags", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_order_sketch_extrude_in_order() {
 | 
			
		||||
    let code = kcl_input!("order-sketch-extrude-in-order");
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("order-sketch-extrude-in-order", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_order_sketch_extrude_out_of_order() {
 | 
			
		||||
    let code = kcl_input!("order-sketch-extrude-out-of-order");
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("order-sketch-extrude-out-of-order", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_extrude_custom_plane() {
 | 
			
		||||
    let code = kcl_input!("extrude-custom-plane");
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await.unwrap();
 | 
			
		||||
    assert_out("extrude-custom-plane", &result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1776,7 +1781,7 @@ async fn kcl_test_arc_error_same_start_end() {
 | 
			
		||||
     )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1796,7 +1801,7 @@ async fn kcl_test_angled_line_to_x_90() {
 | 
			
		||||
example = extrude(exampleSketch, length = 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1816,7 +1821,7 @@ async fn kcl_test_angled_line_to_x_270() {
 | 
			
		||||
example = extrude(exampleSketch, length = 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1836,7 +1841,7 @@ async fn kcl_test_angled_line_to_y_0() {
 | 
			
		||||
example = extrude(exampleSketch, length = 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1856,7 +1861,7 @@ async fn kcl_test_angled_line_to_y_180() {
 | 
			
		||||
example = extrude(exampleSketch, length = 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1876,7 +1881,7 @@ async fn kcl_test_angled_line_of_x_length_90() {
 | 
			
		||||
extrusion = extrude(sketch001, length = 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1896,7 +1901,7 @@ async fn kcl_test_angled_line_of_x_length_270() {
 | 
			
		||||
extrusion = extrude(sketch001, length = 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1918,7 +1923,7 @@ async fn kcl_test_angled_line_of_y_length_0() {
 | 
			
		||||
example = extrude(exampleSketch, length = 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1940,7 +1945,7 @@ async fn kcl_test_angled_line_of_y_length_180() {
 | 
			
		||||
example = extrude(exampleSketch, length = 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1962,7 +1967,7 @@ async fn kcl_test_angled_line_of_y_length_negative_180() {
 | 
			
		||||
example = extrude(exampleSketch, length = 10)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -1979,7 +1984,7 @@ async fn kcl_test_error_inside_fn_also_has_source_range_of_call_site() {
 | 
			
		||||
someFunction('INVALID')
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -2000,7 +2005,7 @@ async fn kcl_test_error_inside_fn_also_has_source_range_of_call_site_recursive()
 | 
			
		||||
someFunction('INVALID')
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        result.err().unwrap().to_string(),
 | 
			
		||||
@ -2024,7 +2029,7 @@ async fn kcl_test_error_no_auth_websocket() {
 | 
			
		||||
  )
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let result = execute_and_snapshot_no_auth(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot_no_auth(code, None).await;
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    assert!(result
 | 
			
		||||
        .err()
 | 
			
		||||
@ -2050,9 +2055,7 @@ sketch000 = startSketchOn(XY)
 | 
			
		||||
    |> line(end = [0, innerDiameter / 2])
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default())
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let ctx = kcl_lib::ExecutorContext::new_with_default_client().await.unwrap();
 | 
			
		||||
    let mut exec_state = kcl_lib::ExecState::new(&ctx);
 | 
			
		||||
    let program = kcl_lib::Program::parse_no_errs(code).unwrap();
 | 
			
		||||
    ctx.run(&program, &mut exec_state).await.unwrap();
 | 
			
		||||
@ -2075,9 +2078,7 @@ async fn kcl_test_ensure_nothing_left_in_batch_multi_file() {
 | 
			
		||||
    // Change the current working directory to the test directory.
 | 
			
		||||
    std::env::set_current_dir(path.parent().unwrap()).unwrap();
 | 
			
		||||
 | 
			
		||||
    let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default())
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let ctx = kcl_lib::ExecutorContext::new_with_default_client().await.unwrap();
 | 
			
		||||
    let mut exec_state = kcl_lib::ExecState::new(&ctx);
 | 
			
		||||
    let program = kcl_lib::Program::parse_no_errs(&code).unwrap();
 | 
			
		||||
    ctx.run(&program, &mut exec_state).await.unwrap();
 | 
			
		||||
@ -2095,7 +2096,7 @@ async fn kcl_test_better_type_names() {
 | 
			
		||||
  |> circle(center = [-95.51, -74.7], radius = 262.23)
 | 
			
		||||
  |> appearance(metalness = 0.9)
 | 
			
		||||
"#;
 | 
			
		||||
    let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
 | 
			
		||||
    let result = execute_and_snapshot(code, None).await;
 | 
			
		||||
 | 
			
		||||
    let err = match result.err() {
 | 
			
		||||
        Some(x) => match x {
 | 
			
		||||
@ -2114,7 +2115,7 @@ async fn kcl_test_exporting_step_file() {
 | 
			
		||||
    // This tests export like how we do it in cli and kcl.py.
 | 
			
		||||
    let code = kcl_input!("helix_defaults_negative_extrude");
 | 
			
		||||
 | 
			
		||||
    let (_, _, files) = execute_and_export_step(code, UnitLength::Mm, None).await.unwrap();
 | 
			
		||||
    let (_, _, files) = execute_and_export_step(code, None).await.unwrap();
 | 
			
		||||
    for file in files {
 | 
			
		||||
        expectorate::assert_contents(
 | 
			
		||||
            format!("e2e/executor/outputs/helix_defaults_negative_extrude_{}", file.name),
 | 
			
		||||
 | 
			
		||||
@ -1172,7 +1172,7 @@ fn find_examples(text: &str, filename: &str) -> Vec<(String, String)> {
 | 
			
		||||
 | 
			
		||||
async fn run_example(text: &str) -> Result<()> {
 | 
			
		||||
    let program = crate::Program::parse_no_errs(text)?;
 | 
			
		||||
    let ctx = ExecutorContext::new_with_default_client(crate::UnitLength::Mm).await?;
 | 
			
		||||
    let ctx = ExecutorContext::new_with_default_client().await?;
 | 
			
		||||
    let mut exec_state = crate::execution::ExecState::new(&ctx);
 | 
			
		||||
    ctx.run(&program, &mut exec_state).await?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
 | 
			
		||||
@ -1010,20 +1010,17 @@ mod test {
 | 
			
		||||
        let std = walk_prelude();
 | 
			
		||||
        for d in std {
 | 
			
		||||
            for (i, eg) in d.examples().enumerate() {
 | 
			
		||||
                let result =
 | 
			
		||||
                    match crate::test_server::execute_and_snapshot(eg, crate::settings::types::UnitLength::Mm, None)
 | 
			
		||||
                        .await
 | 
			
		||||
                    {
 | 
			
		||||
                        Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                            return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                                error: e.error,
 | 
			
		||||
                                filename: format!("{}{i}", d.name()),
 | 
			
		||||
                                kcl_source: eg.to_string(),
 | 
			
		||||
                            }));
 | 
			
		||||
                        }
 | 
			
		||||
                        Err(other_err) => panic!("{}", other_err),
 | 
			
		||||
                        Ok(img) => img,
 | 
			
		||||
                    };
 | 
			
		||||
                let result = match crate::test_server::execute_and_snapshot(eg, None).await {
 | 
			
		||||
                    Err(crate::errors::ExecError::Kcl(e)) => {
 | 
			
		||||
                        return Err(miette::Report::new(crate::errors::Report {
 | 
			
		||||
                            error: e.error,
 | 
			
		||||
                            filename: format!("{}{i}", d.name()),
 | 
			
		||||
                            kcl_source: eg.to_string(),
 | 
			
		||||
                        }));
 | 
			
		||||
                    }
 | 
			
		||||
                    Err(other_err) => panic!("{}", other_err),
 | 
			
		||||
                    Ok(img) => img,
 | 
			
		||||
                };
 | 
			
		||||
                twenty_twenty::assert_image(
 | 
			
		||||
                    format!("tests/outputs/serial_test_example_{}{i}.png", d.example_name()),
 | 
			
		||||
                    &result,
 | 
			
		||||
 | 
			
		||||
@ -176,6 +176,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
 | 
			
		||||
        )
 | 
			
		||||
        .await?;
 | 
			
		||||
 | 
			
		||||
        // Reset to the default units.  Modules assume the engine starts in the
 | 
			
		||||
        // default state.
 | 
			
		||||
        self.set_units(Default::default(), source_range, id_generator).await?;
 | 
			
		||||
 | 
			
		||||
        // Flush the batch queue, so clear is run right away.
 | 
			
		||||
        // Otherwise the hooks below won't work.
 | 
			
		||||
        self.flush_batch(false, source_range).await?;
 | 
			
		||||
@ -256,9 +260,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
 | 
			
		||||
        self.set_edge_visibility(settings.highlight_edges, source_range, id_generator)
 | 
			
		||||
            .await?;
 | 
			
		||||
 | 
			
		||||
        // Change the units.
 | 
			
		||||
        self.set_units(settings.units, source_range, id_generator).await?;
 | 
			
		||||
 | 
			
		||||
        // Send the command to show the grid.
 | 
			
		||||
        self.modify_grid(!settings.show_grid, source_range, id_generator)
 | 
			
		||||
            .await?;
 | 
			
		||||
 | 
			
		||||
@ -97,15 +97,6 @@ pub(super) async fn get_changed_program(old: CacheInformation<'_>, new: CacheInf
 | 
			
		||||
    // If the settings are different we might need to bust the cache.
 | 
			
		||||
    // We specifically do this before checking if they are the exact same.
 | 
			
		||||
    if old.settings != new.settings {
 | 
			
		||||
        // If the units are different we need to re-execute the whole thing.
 | 
			
		||||
        if old.settings.units != new.settings.units {
 | 
			
		||||
            return CacheResult::ReExecute {
 | 
			
		||||
                clear_scene: true,
 | 
			
		||||
                reapply_settings: true,
 | 
			
		||||
                program: new.ast.clone(),
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If anything else is different we may not need to re-execute, but rather just
 | 
			
		||||
        // run the settings again.
 | 
			
		||||
        reapply_settings = true;
 | 
			
		||||
@ -424,50 +415,6 @@ shell(firstSketch, faces = ['end'], thickness = 0.25)"#;
 | 
			
		||||
        assert_eq!(result, CacheResult::NoAction(false));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Changing the units with the exact same file should bust the cache.
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
    async fn test_get_changed_program_same_code_but_different_units() {
 | 
			
		||||
        let new = r#"// Remove the end face for the extrusion.
 | 
			
		||||
firstSketch = startSketchOn('XY')
 | 
			
		||||
  |> startProfileAt([-12, 12], %)
 | 
			
		||||
  |> line(end = [24, 0])
 | 
			
		||||
  |> line(end = [0, -24])
 | 
			
		||||
  |> line(end = [-24, 0])
 | 
			
		||||
  |> close()
 | 
			
		||||
  |> extrude(length = 6)
 | 
			
		||||
 | 
			
		||||
// Remove the end face for the extrusion.
 | 
			
		||||
shell(firstSketch, faces = ['end'], thickness = 0.25)"#;
 | 
			
		||||
 | 
			
		||||
        let ExecTestResults {
 | 
			
		||||
            program, mut exec_ctxt, ..
 | 
			
		||||
        } = parse_execute(new).await.unwrap();
 | 
			
		||||
 | 
			
		||||
        // Change the settings to cm.
 | 
			
		||||
        exec_ctxt.settings.units = crate::UnitLength::Cm;
 | 
			
		||||
 | 
			
		||||
        let result = get_changed_program(
 | 
			
		||||
            CacheInformation {
 | 
			
		||||
                ast: &program.ast,
 | 
			
		||||
                settings: &Default::default(),
 | 
			
		||||
            },
 | 
			
		||||
            CacheInformation {
 | 
			
		||||
                ast: &program.ast,
 | 
			
		||||
                settings: &exec_ctxt.settings,
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
        .await;
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            result,
 | 
			
		||||
            CacheResult::ReExecute {
 | 
			
		||||
                clear_scene: true,
 | 
			
		||||
                reapply_settings: true,
 | 
			
		||||
                program: program.ast
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Changing the grid settings with the exact same file should NOT bust the cache.
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
    async fn test_get_changed_program_same_code_but_different_grid_setting() {
 | 
			
		||||
@ -615,4 +562,42 @@ startSketchOn('XY')
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Removing the units settings using an annotation, when it was non-default
 | 
			
		||||
    // units, with the exact same file should bust the cache.
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
    async fn test_get_changed_program_same_code_but_removed_unit_setting_using_annotation() {
 | 
			
		||||
        let old_code = r#"@settings(defaultLengthUnit = in)
 | 
			
		||||
startSketchOn('XY')
 | 
			
		||||
"#;
 | 
			
		||||
        let new_code = r#"
 | 
			
		||||
startSketchOn('XY')
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
        let ExecTestResults { program, exec_ctxt, .. } = parse_execute(old_code).await.unwrap();
 | 
			
		||||
 | 
			
		||||
        let mut new_program = crate::Program::parse_no_errs(new_code).unwrap();
 | 
			
		||||
        new_program.compute_digest();
 | 
			
		||||
 | 
			
		||||
        let result = get_changed_program(
 | 
			
		||||
            CacheInformation {
 | 
			
		||||
                ast: &program.ast,
 | 
			
		||||
                settings: &exec_ctxt.settings,
 | 
			
		||||
            },
 | 
			
		||||
            CacheInformation {
 | 
			
		||||
                ast: &new_program.ast,
 | 
			
		||||
                settings: &exec_ctxt.settings,
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
        .await;
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            result,
 | 
			
		||||
            CacheResult::ReExecute {
 | 
			
		||||
                clear_scene: true,
 | 
			
		||||
                reapply_settings: true,
 | 
			
		||||
                program: new_program.ast
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -110,12 +110,7 @@ impl ExecutorContext {
 | 
			
		||||
        let old_units = exec_state.length_unit();
 | 
			
		||||
        let original_execution = self.engine.replace_execution_kind(exec_kind).await;
 | 
			
		||||
 | 
			
		||||
        let mut local_state = ModuleState::new(
 | 
			
		||||
            &self.settings,
 | 
			
		||||
            path.std_path(),
 | 
			
		||||
            exec_state.stack().memory.clone(),
 | 
			
		||||
            Some(module_id),
 | 
			
		||||
        );
 | 
			
		||||
        let mut local_state = ModuleState::new(path.std_path(), exec_state.stack().memory.clone(), Some(module_id));
 | 
			
		||||
        if !preserve_mem {
 | 
			
		||||
            std::mem::swap(&mut exec_state.mod_local, &mut local_state);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -39,7 +39,6 @@ use crate::{
 | 
			
		||||
    fs::FileManager,
 | 
			
		||||
    modules::{ModuleId, ModulePath},
 | 
			
		||||
    parsing::ast::types::{Expr, ImportPath, NodeRef},
 | 
			
		||||
    settings::types::UnitLength,
 | 
			
		||||
    source_range::SourceRange,
 | 
			
		||||
    std::StdLib,
 | 
			
		||||
    CompilationError, ExecError, ExecutionKind, KclErrorWithOutputs,
 | 
			
		||||
@ -265,8 +264,6 @@ pub struct ExecutorContext {
 | 
			
		||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
 | 
			
		||||
#[ts(export)]
 | 
			
		||||
pub struct ExecutorSettings {
 | 
			
		||||
    /// The project-default unit to use in modeling dimensions.
 | 
			
		||||
    pub units: UnitLength,
 | 
			
		||||
    /// Highlight edges of 3D objects?
 | 
			
		||||
    pub highlight_edges: bool,
 | 
			
		||||
    /// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled.
 | 
			
		||||
@ -287,7 +284,6 @@ pub struct ExecutorSettings {
 | 
			
		||||
impl Default for ExecutorSettings {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            units: Default::default(),
 | 
			
		||||
            highlight_edges: true,
 | 
			
		||||
            enable_ssao: false,
 | 
			
		||||
            show_grid: false,
 | 
			
		||||
@ -301,7 +297,6 @@ impl Default for ExecutorSettings {
 | 
			
		||||
impl From<crate::settings::types::Configuration> for ExecutorSettings {
 | 
			
		||||
    fn from(config: crate::settings::types::Configuration) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            units: config.settings.modeling.base_unit,
 | 
			
		||||
            highlight_edges: config.settings.modeling.highlight_edges.into(),
 | 
			
		||||
            enable_ssao: config.settings.modeling.enable_ssao.into(),
 | 
			
		||||
            show_grid: config.settings.modeling.show_scale_grid,
 | 
			
		||||
@ -315,7 +310,6 @@ impl From<crate::settings::types::Configuration> for ExecutorSettings {
 | 
			
		||||
impl From<crate::settings::types::project::ProjectConfiguration> for ExecutorSettings {
 | 
			
		||||
    fn from(config: crate::settings::types::project::ProjectConfiguration) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            units: config.settings.modeling.base_unit,
 | 
			
		||||
            highlight_edges: config.settings.modeling.highlight_edges.into(),
 | 
			
		||||
            enable_ssao: config.settings.modeling.enable_ssao.into(),
 | 
			
		||||
            show_grid: Default::default(),
 | 
			
		||||
@ -329,7 +323,6 @@ impl From<crate::settings::types::project::ProjectConfiguration> for ExecutorSet
 | 
			
		||||
impl From<crate::settings::types::ModelingSettings> for ExecutorSettings {
 | 
			
		||||
    fn from(modeling: crate::settings::types::ModelingSettings) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            units: modeling.base_unit,
 | 
			
		||||
            highlight_edges: modeling.highlight_edges.into(),
 | 
			
		||||
            enable_ssao: modeling.enable_ssao.into(),
 | 
			
		||||
            show_grid: modeling.show_scale_grid,
 | 
			
		||||
@ -343,7 +336,6 @@ impl From<crate::settings::types::ModelingSettings> for ExecutorSettings {
 | 
			
		||||
impl From<crate::settings::types::project::ProjectModelingSettings> for ExecutorSettings {
 | 
			
		||||
    fn from(modeling: crate::settings::types::project::ProjectModelingSettings) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            units: modeling.base_unit,
 | 
			
		||||
            highlight_edges: modeling.highlight_edges.into(),
 | 
			
		||||
            enable_ssao: modeling.enable_ssao.into(),
 | 
			
		||||
            show_grid: Default::default(),
 | 
			
		||||
@ -476,26 +468,17 @@ impl ExecutorContext {
 | 
			
		||||
    /// This allows for passing in `ZOO_API_TOKEN` and `ZOO_HOST` as environment
 | 
			
		||||
    /// variables.
 | 
			
		||||
    #[cfg(not(target_arch = "wasm32"))]
 | 
			
		||||
    pub async fn new_with_default_client(units: UnitLength) -> Result<Self> {
 | 
			
		||||
    pub async fn new_with_default_client() -> Result<Self> {
 | 
			
		||||
        // Create the client.
 | 
			
		||||
        let ctx = Self::new_with_client(
 | 
			
		||||
            ExecutorSettings {
 | 
			
		||||
                units,
 | 
			
		||||
                ..Default::default()
 | 
			
		||||
            },
 | 
			
		||||
            None,
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await?;
 | 
			
		||||
        let ctx = Self::new_with_client(Default::default(), None, None).await?;
 | 
			
		||||
        Ok(ctx)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// For executing unit tests.
 | 
			
		||||
    #[cfg(not(target_arch = "wasm32"))]
 | 
			
		||||
    pub async fn new_for_unit_test(units: UnitLength, engine_addr: Option<String>) -> Result<Self> {
 | 
			
		||||
    pub async fn new_for_unit_test(engine_addr: Option<String>) -> Result<Self> {
 | 
			
		||||
        let ctx = ExecutorContext::new_with_client(
 | 
			
		||||
            ExecutorSettings {
 | 
			
		||||
                units,
 | 
			
		||||
                highlight_edges: true,
 | 
			
		||||
                enable_ssao: false,
 | 
			
		||||
                show_grid: false,
 | 
			
		||||
@ -862,11 +845,6 @@ impl ExecutorContext {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Update the units for the executor.
 | 
			
		||||
    pub(crate) fn update_units(&mut self, units: UnitLength) {
 | 
			
		||||
        self.settings.units = units;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get a snapshot of the current scene.
 | 
			
		||||
    pub async fn prepare_snapshot(&self) -> std::result::Result<TakeSnapshot, ExecError> {
 | 
			
		||||
        // Zoom to fit.
 | 
			
		||||
@ -1008,11 +986,7 @@ mod tests {
 | 
			
		||||
    use pretty_assertions::assert_eq;
 | 
			
		||||
 | 
			
		||||
    use super::*;
 | 
			
		||||
    use crate::{
 | 
			
		||||
        errors::{KclErrorDetails, Severity},
 | 
			
		||||
        execution::memory::Stack,
 | 
			
		||||
        ModuleId,
 | 
			
		||||
    };
 | 
			
		||||
    use crate::{errors::KclErrorDetails, execution::memory::Stack, ModuleId};
 | 
			
		||||
 | 
			
		||||
    /// Convenience function to get a JSON value from memory and unwrap.
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
@ -1615,34 +1589,6 @@ const inInches = 2.0 * inch()"#;
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
    async fn test_unit_suggest() {
 | 
			
		||||
        let src = "foo = 42";
 | 
			
		||||
        let program = crate::Program::parse_no_errs(src).unwrap();
 | 
			
		||||
        let ctx = ExecutorContext {
 | 
			
		||||
            engine: Arc::new(Box::new(
 | 
			
		||||
                crate::engine::conn_mock::EngineConnection::new().await.unwrap(),
 | 
			
		||||
            )),
 | 
			
		||||
            fs: Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: ExecutorSettings {
 | 
			
		||||
                units: UnitLength::Ft,
 | 
			
		||||
                ..Default::default()
 | 
			
		||||
            },
 | 
			
		||||
            context_type: ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        let mut exec_state = ExecState::new(&ctx);
 | 
			
		||||
        ctx.run(&program, &mut exec_state).await.unwrap();
 | 
			
		||||
        let errs = exec_state.errors();
 | 
			
		||||
        assert_eq!(errs.len(), 1, "{errs:?}");
 | 
			
		||||
        let warn = &errs[0];
 | 
			
		||||
        assert_eq!(warn.severity, Severity::Warning);
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            warn.apply_suggestion(src).unwrap(),
 | 
			
		||||
            "@settings(defaultLengthUnit = ft)\nfoo = 42"
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
    async fn test_zero_param_fn() {
 | 
			
		||||
        let ast = r#"const sigmaAllow = 35000 // psi
 | 
			
		||||
@ -1971,9 +1917,7 @@ let w = f() + f()
 | 
			
		||||
)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
        let ctx = crate::test_server::new_context(UnitLength::Mm, true, None)
 | 
			
		||||
            .await
 | 
			
		||||
            .unwrap();
 | 
			
		||||
        let ctx = crate::test_server::new_context(true, None).await.unwrap();
 | 
			
		||||
        let old_program = crate::Program::parse_no_errs(code).unwrap();
 | 
			
		||||
 | 
			
		||||
        // Execute the program.
 | 
			
		||||
@ -2026,9 +1970,7 @@ let w = f() + f()
 | 
			
		||||
)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
        let mut ctx = crate::test_server::new_context(UnitLength::Mm, true, None)
 | 
			
		||||
            .await
 | 
			
		||||
            .unwrap();
 | 
			
		||||
        let mut ctx = crate::test_server::new_context(true, None).await.unwrap();
 | 
			
		||||
        let old_program = crate::Program::parse_no_errs(code).unwrap();
 | 
			
		||||
 | 
			
		||||
        // Execute the program.
 | 
			
		||||
@ -2066,7 +2008,7 @@ let w = f() + f()
 | 
			
		||||
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
    async fn mock_after_not_mock() {
 | 
			
		||||
        let ctx = ExecutorContext::new_with_default_client(UnitLength::Mm).await.unwrap();
 | 
			
		||||
        let ctx = ExecutorContext::new_with_default_client().await.unwrap();
 | 
			
		||||
        let program = crate::Program::parse_no_errs("x = 2").unwrap();
 | 
			
		||||
        let result = ctx.run_with_caching(program).await.unwrap();
 | 
			
		||||
        assert_eq!(result.variables.get("x").unwrap().as_f64().unwrap(), 2.0);
 | 
			
		||||
 | 
			
		||||
@ -82,7 +82,7 @@ impl ExecState {
 | 
			
		||||
    pub fn new(exec_context: &super::ExecutorContext) -> Self {
 | 
			
		||||
        ExecState {
 | 
			
		||||
            global: GlobalState::new(&exec_context.settings),
 | 
			
		||||
            mod_local: ModuleState::new(&exec_context.settings, None, ProgramMemory::new(), Default::default()),
 | 
			
		||||
            mod_local: ModuleState::new(None, ProgramMemory::new(), Default::default()),
 | 
			
		||||
            exec_context: Some(exec_context.clone()),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -92,7 +92,7 @@ impl ExecState {
 | 
			
		||||
 | 
			
		||||
        *self = ExecState {
 | 
			
		||||
            global,
 | 
			
		||||
            mod_local: ModuleState::new(&exec_context.settings, None, ProgramMemory::new(), Default::default()),
 | 
			
		||||
            mod_local: ModuleState::new(None, ProgramMemory::new(), Default::default()),
 | 
			
		||||
            exec_context: Some(exec_context.clone()),
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
@ -289,12 +289,7 @@ impl GlobalState {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ModuleState {
 | 
			
		||||
    pub(super) fn new(
 | 
			
		||||
        exec_settings: &ExecutorSettings,
 | 
			
		||||
        std_path: Option<String>,
 | 
			
		||||
        memory: Arc<ProgramMemory>,
 | 
			
		||||
        module_id: Option<ModuleId>,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
    pub(super) fn new(std_path: Option<String>, memory: Arc<ProgramMemory>, module_id: Option<ModuleId>) -> Self {
 | 
			
		||||
        ModuleState {
 | 
			
		||||
            id_generator: IdGenerator::new(module_id),
 | 
			
		||||
            stack: memory.new_stack(),
 | 
			
		||||
@ -303,14 +298,14 @@ impl ModuleState {
 | 
			
		||||
            explicit_length_units: false,
 | 
			
		||||
            std_path,
 | 
			
		||||
            settings: MetaSettings {
 | 
			
		||||
                default_length_units: exec_settings.units.into(),
 | 
			
		||||
                default_length_units: Default::default(),
 | 
			
		||||
                default_angle_units: Default::default(),
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
 | 
			
		||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq, ts_rs::TS, JsonSchema)]
 | 
			
		||||
#[ts(export)]
 | 
			
		||||
#[serde(rename_all = "camelCase")]
 | 
			
		||||
pub struct MetaSettings {
 | 
			
		||||
 | 
			
		||||
@ -195,6 +195,10 @@ impl Program {
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn is_empty_or_only_settings(&self) -> bool {
 | 
			
		||||
        self.ast.is_empty_or_only_settings()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn lint_all(&self) -> Result<Vec<lint::Discovered>, anyhow::Error> {
 | 
			
		||||
        self.ast.lint_all()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -812,56 +812,6 @@ impl Backend {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn update_units(
 | 
			
		||||
        &self,
 | 
			
		||||
        params: custom_notifications::UpdateUnitsParams,
 | 
			
		||||
    ) -> RpcResult<Option<custom_notifications::UpdateUnitsResponse>> {
 | 
			
		||||
        {
 | 
			
		||||
            let mut ctx = self.executor_ctx.write().await;
 | 
			
		||||
            // Borrow the executor context mutably.
 | 
			
		||||
            let Some(ref mut executor_ctx) = *ctx else {
 | 
			
		||||
                self.client
 | 
			
		||||
                    .log_message(MessageType::ERROR, "no executor context set to update units for")
 | 
			
		||||
                    .await;
 | 
			
		||||
                return Ok(None);
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            self.client
 | 
			
		||||
                .log_message(MessageType::INFO, format!("update units: {:?}", params))
 | 
			
		||||
                .await;
 | 
			
		||||
 | 
			
		||||
            if executor_ctx.settings.units == params.units
 | 
			
		||||
                && !self.has_diagnostics(params.text_document.uri.as_ref()).await
 | 
			
		||||
            {
 | 
			
		||||
                // Return early the units are the same.
 | 
			
		||||
                return Ok(None);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Set the engine units.
 | 
			
		||||
            executor_ctx.update_units(params.units);
 | 
			
		||||
        }
 | 
			
		||||
        // Lock is dropped here since nested.
 | 
			
		||||
        // This is IMPORTANT.
 | 
			
		||||
 | 
			
		||||
        let new_params = TextDocumentItem {
 | 
			
		||||
            uri: params.text_document.uri.clone(),
 | 
			
		||||
            text: std::mem::take(&mut params.text.to_string()),
 | 
			
		||||
            version: Default::default(),
 | 
			
		||||
            language_id: Default::default(),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // Force re-execution.
 | 
			
		||||
        self.inner_on_change(new_params, true).await;
 | 
			
		||||
 | 
			
		||||
        // Check if we have diagnostics.
 | 
			
		||||
        // If we do we return early, since we failed in some way.
 | 
			
		||||
        if self.has_diagnostics(params.text_document.uri.as_ref()).await {
 | 
			
		||||
            return Ok(None);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ok(Some(custom_notifications::UpdateUnitsResponse {}))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn update_can_execute(
 | 
			
		||||
        &self,
 | 
			
		||||
        params: custom_notifications::UpdateCanExecuteParams,
 | 
			
		||||
 | 
			
		||||
@ -42,7 +42,6 @@ pub async fn kcl_lsp_server(execute: bool) -> Result<crate::lsp::kcl::Backend> {
 | 
			
		||||
        can_execute: Arc::new(tokio::sync::RwLock::new(can_execute)),
 | 
			
		||||
        is_initialized: Default::default(),
 | 
			
		||||
    })
 | 
			
		||||
    .custom_method("kcl/updateUnits", crate::lsp::kcl::Backend::update_units)
 | 
			
		||||
    .custom_method("kcl/updateCanExecute", crate::lsp::kcl::Backend::update_can_execute)
 | 
			
		||||
    .finish();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2324,80 +2324,6 @@ async fn kcl_test_kcl_lsp_on_change_update_memory() {
 | 
			
		||||
    server.executor_ctx().await.clone().unwrap().close().await;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
 | 
			
		||||
async fn kcl_test_kcl_lsp_update_units() {
 | 
			
		||||
    let server = kcl_lsp_server(true).await.unwrap();
 | 
			
		||||
 | 
			
		||||
    let same_text = r#"fn cube = (pos, scale) => {
 | 
			
		||||
  sg = startSketchOn(XY)
 | 
			
		||||
    |> startProfileAt(pos, %)
 | 
			
		||||
    |> line(end = [0, scale])
 | 
			
		||||
    |> line(end = [scale, 0])
 | 
			
		||||
    |> line(end = [0, -scale])
 | 
			
		||||
 | 
			
		||||
  return sg
 | 
			
		||||
}
 | 
			
		||||
part001 = cube([0,0], 20)
 | 
			
		||||
    |> close()
 | 
			
		||||
    |> extrude(length = 20)"#
 | 
			
		||||
        .to_string();
 | 
			
		||||
 | 
			
		||||
    // Send open file.
 | 
			
		||||
    server
 | 
			
		||||
        .did_open(tower_lsp::lsp_types::DidOpenTextDocumentParams {
 | 
			
		||||
            text_document: tower_lsp::lsp_types::TextDocumentItem {
 | 
			
		||||
                uri: "file:///test.kcl".try_into().unwrap(),
 | 
			
		||||
                language_id: "kcl".to_string(),
 | 
			
		||||
                version: 1,
 | 
			
		||||
                text: same_text.clone(),
 | 
			
		||||
            },
 | 
			
		||||
        })
 | 
			
		||||
        .await;
 | 
			
		||||
 | 
			
		||||
    // Get the tokens.
 | 
			
		||||
    let tokens = server.token_map.get("file:///test.kcl").unwrap().clone();
 | 
			
		||||
    assert_eq!(tokens.as_slice().len(), 123);
 | 
			
		||||
 | 
			
		||||
    // Get the ast.
 | 
			
		||||
    let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
 | 
			
		||||
    assert_eq!(ast.ast.body.len(), 2);
 | 
			
		||||
 | 
			
		||||
    // Send change file.
 | 
			
		||||
    server
 | 
			
		||||
        .did_change(tower_lsp::lsp_types::DidChangeTextDocumentParams {
 | 
			
		||||
            text_document: tower_lsp::lsp_types::VersionedTextDocumentIdentifier {
 | 
			
		||||
                uri: "file:///test.kcl".try_into().unwrap(),
 | 
			
		||||
                version: 1,
 | 
			
		||||
            },
 | 
			
		||||
            content_changes: vec![tower_lsp::lsp_types::TextDocumentContentChangeEvent {
 | 
			
		||||
                range: None,
 | 
			
		||||
                range_length: None,
 | 
			
		||||
                text: same_text.clone(),
 | 
			
		||||
            }],
 | 
			
		||||
        })
 | 
			
		||||
        .await;
 | 
			
		||||
 | 
			
		||||
    let units = server.executor_ctx.read().await.clone().unwrap().settings.units;
 | 
			
		||||
    assert_eq!(units, crate::settings::types::UnitLength::Mm);
 | 
			
		||||
 | 
			
		||||
    // Update the units.
 | 
			
		||||
    server
 | 
			
		||||
        .update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
 | 
			
		||||
            text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
 | 
			
		||||
                uri: "file:///test.kcl".try_into().unwrap(),
 | 
			
		||||
            },
 | 
			
		||||
            units: crate::settings::types::UnitLength::M,
 | 
			
		||||
            text: same_text.clone(),
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
 | 
			
		||||
    let units = server.executor_ctx().await.clone().unwrap().settings.units;
 | 
			
		||||
    assert_eq!(units, crate::settings::types::UnitLength::M);
 | 
			
		||||
 | 
			
		||||
    server.executor_ctx().await.clone().unwrap().close().await;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_kcl_lsp_empty_file_execute_ok() {
 | 
			
		||||
    let server = kcl_lsp_server(true).await.unwrap();
 | 
			
		||||
@ -2733,145 +2659,6 @@ async fn kcl_test_kcl_lsp_code_and_ast_unchanged_but_has_diagnostics_reexecute()
 | 
			
		||||
    server.executor_ctx().await.clone().unwrap().close().await;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_kcl_lsp_code_and_ast_units_unchanged_but_has_diagnostics_reexecute_on_unit_change() {
 | 
			
		||||
    let server = kcl_lsp_server(true).await.unwrap();
 | 
			
		||||
 | 
			
		||||
    let code = r#"part001 = startSketchOn(XY)
 | 
			
		||||
  |> startProfileAt([-10, -10], %)
 | 
			
		||||
  |> line(end = [20, 0])
 | 
			
		||||
  |> line(end = [0, 20])
 | 
			
		||||
  |> line(end = [-20, 0])
 | 
			
		||||
  |> close()
 | 
			
		||||
  |> extrude(length = 3.14)"#;
 | 
			
		||||
 | 
			
		||||
    // Send open file.
 | 
			
		||||
    server
 | 
			
		||||
        .did_open(tower_lsp::lsp_types::DidOpenTextDocumentParams {
 | 
			
		||||
            text_document: tower_lsp::lsp_types::TextDocumentItem {
 | 
			
		||||
                uri: "file:///test.kcl".try_into().unwrap(),
 | 
			
		||||
                language_id: "kcl".to_string(),
 | 
			
		||||
                version: 1,
 | 
			
		||||
                text: code.to_string(),
 | 
			
		||||
            },
 | 
			
		||||
        })
 | 
			
		||||
        .await;
 | 
			
		||||
 | 
			
		||||
    // Get the ast.
 | 
			
		||||
    let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
 | 
			
		||||
    assert!(ast.ast != Node::<Program>::default());
 | 
			
		||||
 | 
			
		||||
    // Assure we have no diagnostics.
 | 
			
		||||
    assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
 | 
			
		||||
 | 
			
		||||
    // Add some fake diagnostics.
 | 
			
		||||
    server.diagnostics_map.insert(
 | 
			
		||||
        "file:///test.kcl".to_string(),
 | 
			
		||||
        vec![tower_lsp::lsp_types::Diagnostic {
 | 
			
		||||
            range: tower_lsp::lsp_types::Range {
 | 
			
		||||
                start: tower_lsp::lsp_types::Position { line: 0, character: 0 },
 | 
			
		||||
                end: tower_lsp::lsp_types::Position { line: 0, character: 0 },
 | 
			
		||||
            },
 | 
			
		||||
            message: "fake diagnostic".to_string(),
 | 
			
		||||
            severity: Some(tower_lsp::lsp_types::DiagnosticSeverity::ERROR),
 | 
			
		||||
            code: None,
 | 
			
		||||
            source: None,
 | 
			
		||||
            related_information: None,
 | 
			
		||||
            tags: None,
 | 
			
		||||
            data: None,
 | 
			
		||||
            code_description: None,
 | 
			
		||||
        }],
 | 
			
		||||
    );
 | 
			
		||||
    // Assure we have one diagnostics.
 | 
			
		||||
    assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 1);
 | 
			
		||||
 | 
			
		||||
    let units = server.executor_ctx().await.clone().unwrap().settings.units;
 | 
			
		||||
    assert_eq!(units, crate::settings::types::UnitLength::Mm);
 | 
			
		||||
 | 
			
		||||
    // Update the units to the _same_ units.
 | 
			
		||||
    server
 | 
			
		||||
        .update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
 | 
			
		||||
            text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
 | 
			
		||||
                uri: "file:///test.kcl".try_into().unwrap(),
 | 
			
		||||
            },
 | 
			
		||||
            units: crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            text: code.to_string(),
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
 | 
			
		||||
    let units = server.executor_ctx().await.clone().unwrap().settings.units;
 | 
			
		||||
    assert_eq!(units, crate::settings::types::UnitLength::Mm);
 | 
			
		||||
 | 
			
		||||
    // Get the ast.
 | 
			
		||||
    let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
 | 
			
		||||
    assert!(ast.ast != Node::<Program>::default());
 | 
			
		||||
 | 
			
		||||
    // Assure we have no diagnostics.
 | 
			
		||||
    assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
 | 
			
		||||
 | 
			
		||||
    server.executor_ctx().await.clone().unwrap().close().await;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_kcl_lsp_code_and_ast_units_unchanged_but_has_memory_reexecute_on_unit_change() {
 | 
			
		||||
    let server = kcl_lsp_server(true).await.unwrap();
 | 
			
		||||
 | 
			
		||||
    let code = r#"part001 = startSketchOn(XY)
 | 
			
		||||
  |> startProfileAt([-10, -10], %)
 | 
			
		||||
  |> line(end = [20, 0])
 | 
			
		||||
  |> line(end = [0, 20])
 | 
			
		||||
  |> line(end = [-20, 0])
 | 
			
		||||
  |> close()
 | 
			
		||||
  |> extrude(length = 3.14)"#;
 | 
			
		||||
 | 
			
		||||
    // Send open file.
 | 
			
		||||
    server
 | 
			
		||||
        .did_open(tower_lsp::lsp_types::DidOpenTextDocumentParams {
 | 
			
		||||
            text_document: tower_lsp::lsp_types::TextDocumentItem {
 | 
			
		||||
                uri: "file:///test.kcl".try_into().unwrap(),
 | 
			
		||||
                language_id: "kcl".to_string(),
 | 
			
		||||
                version: 1,
 | 
			
		||||
                text: code.to_string(),
 | 
			
		||||
            },
 | 
			
		||||
        })
 | 
			
		||||
        .await;
 | 
			
		||||
 | 
			
		||||
    // Get the ast.
 | 
			
		||||
    let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
 | 
			
		||||
    assert!(ast.ast != Node::<Program>::default());
 | 
			
		||||
 | 
			
		||||
    // Assure we have no diagnostics.
 | 
			
		||||
    assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
 | 
			
		||||
 | 
			
		||||
    let units = server.executor_ctx().await.clone().unwrap().settings.units;
 | 
			
		||||
    assert_eq!(units, crate::settings::types::UnitLength::Mm);
 | 
			
		||||
 | 
			
		||||
    // Update the units to the _same_ units.
 | 
			
		||||
    server
 | 
			
		||||
        .update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
 | 
			
		||||
            text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
 | 
			
		||||
                uri: "file:///test.kcl".try_into().unwrap(),
 | 
			
		||||
            },
 | 
			
		||||
            units: crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            text: code.to_string(),
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
 | 
			
		||||
    let units = server.executor_ctx().await.clone().unwrap().settings.units;
 | 
			
		||||
    assert_eq!(units, crate::settings::types::UnitLength::Mm);
 | 
			
		||||
 | 
			
		||||
    // Get the ast.
 | 
			
		||||
    let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
 | 
			
		||||
    assert!(ast.ast != Node::<Program>::default());
 | 
			
		||||
 | 
			
		||||
    // Assure we have no diagnostics.
 | 
			
		||||
    assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
 | 
			
		||||
 | 
			
		||||
    server.executor_ctx().await.clone().unwrap().close().await;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
async fn kcl_test_kcl_lsp_cant_execute_set() {
 | 
			
		||||
    let server = kcl_lsp_server(true).await.unwrap();
 | 
			
		||||
@ -2903,23 +2690,6 @@ async fn kcl_test_kcl_lsp_cant_execute_set() {
 | 
			
		||||
    // Assure we have no diagnostics.
 | 
			
		||||
    assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
 | 
			
		||||
 | 
			
		||||
    // Update the units to the _same_ units.
 | 
			
		||||
    let units = server.executor_ctx().await.clone().unwrap().settings.units;
 | 
			
		||||
    assert_eq!(units, crate::settings::types::UnitLength::Mm);
 | 
			
		||||
    server
 | 
			
		||||
        .update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
 | 
			
		||||
            text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
 | 
			
		||||
                uri: "file:///test.kcl".try_into().unwrap(),
 | 
			
		||||
            },
 | 
			
		||||
            units: crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            text: code.to_string(),
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
 | 
			
		||||
    let units = server.executor_ctx().await.clone().unwrap().settings.units;
 | 
			
		||||
    assert_eq!(units, crate::settings::types::UnitLength::Mm);
 | 
			
		||||
 | 
			
		||||
    // Get the ast.
 | 
			
		||||
    let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
 | 
			
		||||
    assert!(ast.ast != Node::<Program>::default());
 | 
			
		||||
@ -2936,23 +2706,6 @@ async fn kcl_test_kcl_lsp_cant_execute_set() {
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    assert_eq!(server.can_execute().await, false);
 | 
			
		||||
 | 
			
		||||
    // Update the units to the _same_ units.
 | 
			
		||||
    let units = server.executor_ctx().await.clone().unwrap().settings.units;
 | 
			
		||||
    assert_eq!(units, crate::settings::types::UnitLength::Mm);
 | 
			
		||||
    server
 | 
			
		||||
        .update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
 | 
			
		||||
            text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
 | 
			
		||||
                uri: "file:///test.kcl".try_into().unwrap(),
 | 
			
		||||
            },
 | 
			
		||||
            units: crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            text: code.to_string(),
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
 | 
			
		||||
    let units = server.executor_ctx().await.clone().unwrap().settings.units;
 | 
			
		||||
    assert_eq!(units, crate::settings::types::UnitLength::Mm);
 | 
			
		||||
 | 
			
		||||
    let mut default_hashed = Node::<Program>::default();
 | 
			
		||||
    default_hashed.compute_digest();
 | 
			
		||||
 | 
			
		||||
@ -2970,23 +2723,6 @@ async fn kcl_test_kcl_lsp_cant_execute_set() {
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    assert_eq!(server.can_execute().await, true);
 | 
			
		||||
 | 
			
		||||
    // Update the units to the _same_ units.
 | 
			
		||||
    let units = server.executor_ctx.read().await.clone().unwrap().settings.units;
 | 
			
		||||
    assert_eq!(units, crate::settings::types::UnitLength::Mm);
 | 
			
		||||
    server
 | 
			
		||||
        .update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
 | 
			
		||||
            text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
 | 
			
		||||
                uri: "file:///test.kcl".try_into().unwrap(),
 | 
			
		||||
            },
 | 
			
		||||
            units: crate::settings::types::UnitLength::Mm,
 | 
			
		||||
            text: code.to_string(),
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
 | 
			
		||||
    let units = server.executor_ctx.read().await.clone().unwrap().settings.units;
 | 
			
		||||
    assert_eq!(units, crate::settings::types::UnitLength::Mm);
 | 
			
		||||
 | 
			
		||||
    // Get the ast.
 | 
			
		||||
    let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
 | 
			
		||||
    assert!(ast.ast != Node::<Program>::default());
 | 
			
		||||
 | 
			
		||||
@ -369,6 +369,26 @@ impl Node<Program> {
 | 
			
		||||
 | 
			
		||||
        Ok(new_program)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns true if the given KCL is empty or only contains settings that
 | 
			
		||||
    /// would be auto-generated.
 | 
			
		||||
    pub fn is_empty_or_only_settings(&self) -> bool {
 | 
			
		||||
        if !self.body.is_empty() {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if self.non_code_meta.start_nodes.iter().any(|node| node.is_comment()) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for item in &self.inner_attrs {
 | 
			
		||||
            if item.name() != Some(annotations::SETTINGS) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        true
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Program {
 | 
			
		||||
@ -3564,6 +3584,37 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
    use super::*;
 | 
			
		||||
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    fn parse(code: &str) -> Node<Program> {
 | 
			
		||||
        crate::parsing::top_level_parse(code).unwrap()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_empty_or_only_settings() {
 | 
			
		||||
        // Empty is empty.
 | 
			
		||||
        assert!(parse("").is_empty_or_only_settings());
 | 
			
		||||
 | 
			
		||||
        // Whitespace is empty.
 | 
			
		||||
        assert!(parse(" ").is_empty_or_only_settings());
 | 
			
		||||
 | 
			
		||||
        // Settings are empty.
 | 
			
		||||
        assert!(parse(r#"@settings(defaultLengthUnit = mm)"#).is_empty_or_only_settings());
 | 
			
		||||
 | 
			
		||||
        // Only comments is not empty.
 | 
			
		||||
        assert!(!parse("// comment").is_empty_or_only_settings());
 | 
			
		||||
 | 
			
		||||
        // Any statement is not empty.
 | 
			
		||||
        assert!(!parse("5").is_empty_or_only_settings());
 | 
			
		||||
 | 
			
		||||
        // Any statement is not empty, even with settings.
 | 
			
		||||
        let code = r#"@settings(defaultLengthUnit = mm)
 | 
			
		||||
5"#;
 | 
			
		||||
        assert!(!parse(code).is_empty_or_only_settings());
 | 
			
		||||
 | 
			
		||||
        // Non-settings attributes are not empty.
 | 
			
		||||
        assert!(!parse("@foo").is_empty_or_only_settings());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // We have this as a test so we can ensure it never panics with an unwrap in the server.
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_variable_kind_to_completion() {
 | 
			
		||||
 | 
			
		||||
@ -155,13 +155,9 @@ async fn execute_test(test: &Test, render_to_png: bool, export_step: bool) {
 | 
			
		||||
    let ast = crate::Program::parse_no_errs(&input).unwrap();
 | 
			
		||||
 | 
			
		||||
    // Run the program.
 | 
			
		||||
    let exec_res = crate::test_server::execute_and_snapshot_ast(
 | 
			
		||||
        ast,
 | 
			
		||||
        crate::settings::types::UnitLength::Mm,
 | 
			
		||||
        Some(test.input_dir.join(&test.entry_point)),
 | 
			
		||||
        export_step,
 | 
			
		||||
    )
 | 
			
		||||
    .await;
 | 
			
		||||
    let exec_res =
 | 
			
		||||
        crate::test_server::execute_and_snapshot_ast(ast, Some(test.input_dir.join(&test.entry_point)), export_step)
 | 
			
		||||
            .await;
 | 
			
		||||
    match exec_res {
 | 
			
		||||
        Ok((exec_state, env_ref, png, step)) => {
 | 
			
		||||
            let fail_path = test.output_dir.join("execution_error.snap");
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
//! Run all the KCL samples in the `kcl_samples` directory.
 | 
			
		||||
use std::panic::{catch_unwind, AssertUnwindSafe};
 | 
			
		||||
use std::{
 | 
			
		||||
    fs,
 | 
			
		||||
    panic::{catch_unwind, AssertUnwindSafe},
 | 
			
		||||
    path::{Path, PathBuf},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -165,7 +165,7 @@ async fn inner_fillet(
 | 
			
		||||
                edge_id,
 | 
			
		||||
                object_id: solid.id,
 | 
			
		||||
                radius: LengthUnit(radius),
 | 
			
		||||
                tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
 | 
			
		||||
                tolerance: LengthUnit(tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into()))),
 | 
			
		||||
                cut_type: CutType::Fillet,
 | 
			
		||||
                // We make this a none so that we can remove it in the future.
 | 
			
		||||
                face_id: None,
 | 
			
		||||
 | 
			
		||||
@ -159,7 +159,7 @@ async fn inner_loft(
 | 
			
		||||
            section_ids: sketches.iter().map(|group| group.id).collect(),
 | 
			
		||||
            base_curve_index,
 | 
			
		||||
            bez_approximate_rational,
 | 
			
		||||
            tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
 | 
			
		||||
            tolerance: LengthUnit(tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into()))),
 | 
			
		||||
            v_degree,
 | 
			
		||||
        }),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
@ -273,7 +273,9 @@ async fn inner_revolve(
 | 
			
		||||
                        target: sketch.id.into(),
 | 
			
		||||
                        axis,
 | 
			
		||||
                        origin,
 | 
			
		||||
                        tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
 | 
			
		||||
                        tolerance: LengthUnit(
 | 
			
		||||
                            tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into())),
 | 
			
		||||
                        ),
 | 
			
		||||
                        axis_is_2d: true,
 | 
			
		||||
                    }),
 | 
			
		||||
                )
 | 
			
		||||
@ -287,7 +289,9 @@ async fn inner_revolve(
 | 
			
		||||
                        angle,
 | 
			
		||||
                        target: sketch.id.into(),
 | 
			
		||||
                        edge_id,
 | 
			
		||||
                        tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
 | 
			
		||||
                        tolerance: LengthUnit(
 | 
			
		||||
                            tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into())),
 | 
			
		||||
                        ),
 | 
			
		||||
                    }),
 | 
			
		||||
                )
 | 
			
		||||
                .await?;
 | 
			
		||||
 | 
			
		||||
@ -191,7 +191,7 @@ async fn inner_sweep(
 | 
			
		||||
                target: sketch.id.into(),
 | 
			
		||||
                trajectory,
 | 
			
		||||
                sectional: sectional.unwrap_or(false),
 | 
			
		||||
                tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
 | 
			
		||||
                tolerance: LengthUnit(tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into()))),
 | 
			
		||||
            }),
 | 
			
		||||
        )
 | 
			
		||||
        .await?;
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,6 @@ use crate::{
 | 
			
		||||
    engine::new_zoo_client,
 | 
			
		||||
    errors::ExecErrorWithState,
 | 
			
		||||
    execution::{EnvironmentRef, ExecState, ExecutorContext, ExecutorSettings},
 | 
			
		||||
    settings::types::UnitLength,
 | 
			
		||||
    ConnectionError, ExecError, KclError, KclErrorWithOutputs, Program,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -19,12 +18,8 @@ pub struct RequestBody {
 | 
			
		||||
 | 
			
		||||
/// Executes a kcl program and takes a snapshot of the result.
 | 
			
		||||
/// This returns the bytes of the snapshot.
 | 
			
		||||
pub async fn execute_and_snapshot(
 | 
			
		||||
    code: &str,
 | 
			
		||||
    units: UnitLength,
 | 
			
		||||
    current_file: Option<PathBuf>,
 | 
			
		||||
) -> Result<image::DynamicImage, ExecError> {
 | 
			
		||||
    let ctx = new_context(units, true, current_file).await?;
 | 
			
		||||
pub async fn execute_and_snapshot(code: &str, current_file: Option<PathBuf>) -> Result<image::DynamicImage, ExecError> {
 | 
			
		||||
    let ctx = new_context(true, current_file).await?;
 | 
			
		||||
    let program = Program::parse_no_errs(code).map_err(KclErrorWithOutputs::no_outputs)?;
 | 
			
		||||
    let res = do_execute_and_snapshot(&ctx, program)
 | 
			
		||||
        .await
 | 
			
		||||
@ -38,11 +33,10 @@ pub async fn execute_and_snapshot(
 | 
			
		||||
/// This returns the bytes of the snapshot.
 | 
			
		||||
pub async fn execute_and_snapshot_ast(
 | 
			
		||||
    ast: Program,
 | 
			
		||||
    units: UnitLength,
 | 
			
		||||
    current_file: Option<PathBuf>,
 | 
			
		||||
    with_export_step: bool,
 | 
			
		||||
) -> Result<(ExecState, EnvironmentRef, image::DynamicImage, Option<Vec<u8>>), ExecErrorWithState> {
 | 
			
		||||
    let ctx = new_context(units, true, current_file).await?;
 | 
			
		||||
    let ctx = new_context(true, current_file).await?;
 | 
			
		||||
    let (exec_state, env, img) = do_execute_and_snapshot(&ctx, ast).await?;
 | 
			
		||||
    let mut step = None;
 | 
			
		||||
    if with_export_step {
 | 
			
		||||
@ -64,10 +58,9 @@ pub async fn execute_and_snapshot_ast(
 | 
			
		||||
 | 
			
		||||
pub async fn execute_and_snapshot_no_auth(
 | 
			
		||||
    code: &str,
 | 
			
		||||
    units: UnitLength,
 | 
			
		||||
    current_file: Option<PathBuf>,
 | 
			
		||||
) -> Result<(image::DynamicImage, EnvironmentRef), ExecError> {
 | 
			
		||||
    let ctx = new_context(units, false, current_file).await?;
 | 
			
		||||
    let ctx = new_context(false, current_file).await?;
 | 
			
		||||
    let program = Program::parse_no_errs(code).map_err(KclErrorWithOutputs::no_outputs)?;
 | 
			
		||||
    let res = do_execute_and_snapshot(&ctx, program)
 | 
			
		||||
        .await
 | 
			
		||||
@ -111,11 +104,7 @@ async fn do_execute_and_snapshot(
 | 
			
		||||
    Ok((exec_state, result.0, img))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn new_context(
 | 
			
		||||
    units: UnitLength,
 | 
			
		||||
    with_auth: bool,
 | 
			
		||||
    current_file: Option<PathBuf>,
 | 
			
		||||
) -> Result<ExecutorContext, ConnectionError> {
 | 
			
		||||
pub async fn new_context(with_auth: bool, current_file: Option<PathBuf>) -> Result<ExecutorContext, ConnectionError> {
 | 
			
		||||
    let mut client = new_zoo_client(if with_auth { None } else { Some("bad_token".to_string()) }, None)
 | 
			
		||||
        .map_err(ConnectionError::CouldNotMakeClient)?;
 | 
			
		||||
    if !with_auth {
 | 
			
		||||
@ -126,7 +115,6 @@ pub async fn new_context(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let mut settings = ExecutorSettings {
 | 
			
		||||
        units,
 | 
			
		||||
        highlight_edges: true,
 | 
			
		||||
        enable_ssao: false,
 | 
			
		||||
        show_grid: false,
 | 
			
		||||
@ -145,7 +133,6 @@ pub async fn new_context(
 | 
			
		||||
 | 
			
		||||
pub async fn execute_and_export_step(
 | 
			
		||||
    code: &str,
 | 
			
		||||
    units: UnitLength,
 | 
			
		||||
    current_file: Option<PathBuf>,
 | 
			
		||||
) -> Result<
 | 
			
		||||
    (
 | 
			
		||||
@ -155,7 +142,7 @@ pub async fn execute_and_export_step(
 | 
			
		||||
    ),
 | 
			
		||||
    ExecErrorWithState,
 | 
			
		||||
> {
 | 
			
		||||
    let ctx = new_context(units, true, current_file).await?;
 | 
			
		||||
    let ctx = new_context(true, current_file).await?;
 | 
			
		||||
    let mut exec_state = ExecState::new(&ctx);
 | 
			
		||||
    let program = Program::parse_no_errs(code)
 | 
			
		||||
        .map_err(|err| ExecErrorWithState::new(KclErrorWithOutputs::no_outputs(err).into(), exec_state.clone()))?;
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands add_lots.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands angled_line.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands argument_error.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands array_elem_pop.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands array_elem_pop_empty_fail.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands array_elem_pop_fail.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands array_elem_push.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands array_elem_push_fail.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands array_index_oob.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands array_range_expr.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands array_range_negative_expr.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands artifact_graph_example_code1.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands artifact_graph_example_code_no_3d.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands artifact_graph_example_code_offset_planes.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands assembly_mixed_units_cubes.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands assembly_non_default_units.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands bad_units_in_annotation.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands basic_fillet_cube_close_opposite.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands basic_fillet_cube_end.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands basic_fillet_cube_next_adjacent.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands basic_fillet_cube_previous_adjacent.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands basic_fillet_cube_start.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands big_number_angle_to_match_length_x.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands big_number_angle_to_match_length_y.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands boolean_logical_and.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands boolean_logical_multiple.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands boolean_logical_or.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands circle_three_point.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands circular_pattern3d_a_pattern.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands comparisons.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands comparisons_multiple.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands computed_var.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands crazy_multi_profile.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands cube.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands cube_with_error.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands double_map_fn.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands fillet-and-shell.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands flush_batch_on_end.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands function_sketch.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands function_sketch_with_position.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands helix_ccw.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands helix_simple.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands i_shape.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands if_else.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands import_constant.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands import_cycle1.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands import_export.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands import_file_not_exist_error.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands import_file_parse_error.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands import_foreign.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands import_function_not_sketch.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands import_glob.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands import_side_effect.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands import_transform.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands import_whole.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands index_of_array.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands intersect_cubes.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands invalid_index_fractional.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands invalid_index_negative.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
@ -11,14 +11,6 @@ description: Artifact commands invalid_index_str.kcl
 | 
			
		||||
      "hidden": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
    "command": {
 | 
			
		||||
      "type": "set_scene_units",
 | 
			
		||||
      "unit": "mm"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "cmdId": "[uuid]",
 | 
			
		||||
    "range": [],
 | 
			
		||||
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user