diff --git a/.github/actions/github-release/package.json b/.github/actions/github-release/package.json index af12a33a056..9c9e4a9ffcd 100644 --- a/.github/actions/github-release/package.json +++ b/.github/actions/github-release/package.json @@ -5,6 +5,6 @@ "dependencies": { "@actions/core": "^1.6", "@actions/github": "^6.0", - "glob": "^11.0.1" + "glob": "^13.0.0" } } diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 12086773d26..1fa69668a6e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,7 +9,6 @@ updates: schedule: interval: weekly day: saturday - time: '03:00' timezone: America/Los_Angeles open-pull-requests-limit: 5 groups: @@ -50,7 +49,6 @@ updates: schedule: interval: weekly day: saturday - time: '03:00' timezone: America/Los_Angeles open-pull-requests-limit: 5 groups: @@ -88,12 +86,15 @@ updates: - patch cooldown: default-days: 7 + exclude: + - '*kcl*' + - '*zoo*' + - '*kittycad*' - package-ecosystem: cargo directory: /rust/kcl-lib/fuzz schedule: interval: weekly day: saturday - time: '03:00' timezone: America/Los_Angeles open-pull-requests-limit: 5 groups: @@ -131,12 +132,15 @@ updates: - patch cooldown: default-days: 7 + exclude: + - '*kcl*' + - '*zoo*' + - '*kittycad*' - package-ecosystem: npm directory: / schedule: interval: weekly day: saturday - time: '03:00' timezone: America/Los_Angeles open-pull-requests-limit: 5 groups: @@ -174,12 +178,15 @@ updates: - patch cooldown: default-days: 7 + exclude: + - '*kcl*' + - '*zoo*' + - '*kittycad*' - package-ecosystem: npm directory: /packages/codemirror-lang-kcl schedule: interval: weekly day: saturday - time: '03:00' timezone: America/Los_Angeles open-pull-requests-limit: 5 groups: @@ -217,12 +224,15 @@ updates: - patch cooldown: default-days: 7 + exclude: + - '*kcl*' + - '*zoo*' + - '*kittycad*' - package-ecosystem: npm directory: /rust/kcl-language-server schedule: interval: weekly day: saturday - time: '03:00' timezone: America/Los_Angeles open-pull-requests-limit: 5 groups: @@ -260,12 +270,15 @@ updates: - patch cooldown: default-days: 7 + exclude: + - '*kcl*' + - '*zoo*' + - '*kittycad*' - package-ecosystem: npm directory: /public/fonts/source-code-pro schedule: interval: weekly day: saturday - time: '03:00' timezone: America/Los_Angeles open-pull-requests-limit: 5 groups: @@ -303,12 +316,15 @@ updates: - patch cooldown: default-days: 7 + exclude: + - '*kcl*' + - '*zoo*' + - '*kittycad*' - package-ecosystem: npm directory: /packages/codemirror-lsp-client schedule: interval: weekly day: saturday - time: '03:00' timezone: America/Los_Angeles open-pull-requests-limit: 5 groups: @@ -346,12 +362,15 @@ updates: - patch cooldown: default-days: 7 + exclude: + - '*kcl*' + - '*zoo*' + - '*kittycad*' - package-ecosystem: npm directory: /.github/actions/github-release schedule: interval: weekly day: saturday - time: '03:00' timezone: America/Los_Angeles open-pull-requests-limit: 5 groups: @@ -389,12 +408,15 @@ updates: - patch cooldown: default-days: 7 + exclude: + - '*kcl*' + - '*zoo*' + - '*kittycad*' - package-ecosystem: pip directory: /rust/kcl-python-bindings schedule: interval: weekly day: saturday - time: '03:00' timezone: America/Los_Angeles open-pull-requests-limit: 5 groups: @@ -432,12 +454,15 @@ updates: - patch cooldown: default-days: 7 + exclude: + - '*kcl*' + - '*zoo*' + - '*kittycad*' - package-ecosystem: docker directory: /.github/actions/github-release schedule: interval: weekly day: saturday - time: '03:00' timezone: America/Los_Angeles open-pull-requests-limit: 5 groups: @@ -475,3 +500,7 @@ updates: - patch cooldown: default-days: 7 + exclude: + - '*kcl*' + - '*zoo*' + - '*kittycad*' diff --git a/.github/workflows/build-and-store-wasm.yml b/.github/workflows/build-and-store-wasm.yml index 36e83473fe5..312dc21c759 100644 --- a/.github/workflows/build-and-store-wasm.yml +++ b/.github/workflows/build-and-store-wasm.yml @@ -24,7 +24,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1 with: cache: false # Configured below. - - uses: taiki-e/install-action@c5b1b6f479c32f356cc6f4ba672a47f63853b13b + - uses: taiki-e/install-action@493d7f216ecab2af0602481ce809ab2c72836fa1 with: tool: wasm-pack - name: Rust Cache diff --git a/.github/workflows/build-apps.yml b/.github/workflows/build-apps.yml index fafacd07316..0bee5eb617a 100644 --- a/.github/workflows/build-apps.yml +++ b/.github/workflows/build-apps.yml @@ -76,7 +76,7 @@ jobs: with: cache: false # Configured below. - - uses: taiki-e/install-action@c5b1b6f479c32f356cc6f4ba672a47f63853b13b + - uses: taiki-e/install-action@493d7f216ecab2af0602481ce809ab2c72836fa1 if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }} with: tool: wasm-pack diff --git a/.github/workflows/build-wasm.yml b/.github/workflows/build-wasm.yml index f2bada2423b..d956132d00b 100644 --- a/.github/workflows/build-wasm.yml +++ b/.github/workflows/build-wasm.yml @@ -30,7 +30,7 @@ jobs: with: cache: false # configured below - - uses: taiki-e/install-action@c5b1b6f479c32f356cc6f4ba672a47f63853b13b + - uses: taiki-e/install-action@493d7f216ecab2af0602481ce809ab2c72836fa1 with: tool: wasm-pack diff --git a/.github/workflows/cargo-test.yml b/.github/workflows/cargo-test.yml index d1d5c784793..9010f84d185 100644 --- a/.github/workflows/cargo-test.yml +++ b/.github/workflows/cargo-test.yml @@ -265,7 +265,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1 with: cache: false # Configured below. - - uses: taiki-e/install-action@c5b1b6f479c32f356cc6f4ba672a47f63853b13b + - uses: taiki-e/install-action@493d7f216ecab2af0602481ce809ab2c72836fa1 with: tool: wasm-pack - name: Rust Cache diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 2a962ef9456..f54ab6091db 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -80,7 +80,7 @@ jobs: with: cache: false # Configured below. - - uses: taiki-e/install-action@c5b1b6f479c32f356cc6f4ba672a47f63853b13b + - uses: taiki-e/install-action@493d7f216ecab2af0602481ce809ab2c72836fa1 if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }} with: tool: wasm-pack diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index a78e486e282..e03db6c540d 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -156,4 +156,4 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Run codespell - uses: crate-ci/typos@v1.38.1 + uses: crate-ci/typos@v1.40.0 diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index caafbce2958..40736205c67 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -34,7 +34,7 @@ jobs: cache: 'npm' - run: npm install - - uses: taiki-e/install-action@c5b1b6f479c32f356cc6f4ba672a47f63853b13b + - uses: taiki-e/install-action@493d7f216ecab2af0602481ce809ab2c72836fa1 with: tool: wasm-pack @@ -78,7 +78,7 @@ jobs: cache: 'npm' - run: npm install - - uses: taiki-e/install-action@c5b1b6f479c32f356cc6f4ba672a47f63853b13b + - uses: taiki-e/install-action@493d7f216ecab2af0602481ce809ab2c72836fa1 with: tool: wasm-pack diff --git a/e2e/playwright/editor-tests.spec.ts b/e2e/playwright/editor-tests.spec.ts index b9ff0ffdfde..fa82189acbe 100644 --- a/e2e/playwright/editor-tests.spec.ts +++ b/e2e/playwright/editor-tests.spec.ts @@ -672,7 +672,11 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10)) // Wait for highlighting to kick in, a good proxy that the LSP is ready. await expect - .poll(() => page.evaluate(() => document.querySelector('.ͼj') !== null)) + .poll(() => + page.evaluate( + () => document.querySelector('.cm-line > span[class*="ͼ"]') !== null + ) + ) .toBe(true) // Expect the signature help to NOT be visible diff --git a/package-lock.json b/package-lock.json index 1d5d6cc08c5..ea305437366 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "@headlessui/react": "^1.7.19", "@headlessui/tailwindcss": "^0.2.2", "@kittycad/lib": "^3.1.7", - "@kittycad/react-shared": "^0.1.6", + "@kittycad/react-shared": "^0.1.10", "@lezer/highlight": "^1.2.1", "@lezer/lr": "^1.4.1", "@microlink/react-json-view": "^1.27.0", @@ -4613,9 +4613,9 @@ } }, "node_modules/@kittycad/react-shared": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/@kittycad/react-shared/-/react-shared-0.1.9.tgz", - "integrity": "sha512-DKnCEBmrhU+xCxoG+XSuQOSkRNHrqT04IF2VydqP8dJTdwB3IvraBnaQsQ8vVYS91cZHiIwNPL3t3MA4CPwVtA==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@kittycad/react-shared/-/react-shared-0.1.10.tgz", + "integrity": "sha512-RuX36UIVYfZesxEDnjyOeCiLo9DlHM647P/glj09L1obKYnWwvPAL3yWBlPMzOWUAYxPNuNCowxNsgD+Yn6Lbw==", "license": "MIT", "dependencies": { "@fortawesome/free-brands-svg-icons": "^6.7.2", @@ -25949,7 +25949,7 @@ "@vscode/vsce": "^3.3.2", "cross-env": "^10.1.0", "esbuild": "^0.27.0", - "glob": "^11.0.3", + "glob": "^13.0.0", "mocha": "^11.1.0", "typescript": "^5.8.3" }, @@ -26454,22 +26454,16 @@ } }, "rust/kcl-language-server/node_modules/glob": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", - "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "foreground-child": "^3.3.1", - "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, "engines": { "node": "20 || >=22" }, diff --git a/package.json b/package.json index 838a4b6e28e..d08f4c95fb9 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@headlessui/react": "^1.7.19", "@headlessui/tailwindcss": "^0.2.2", "@kittycad/lib": "^3.1.7", - "@kittycad/react-shared": "^0.1.6", + "@kittycad/react-shared": "^0.1.10", "@lezer/highlight": "^1.2.1", "@lezer/lr": "^1.4.1", "@microlink/react-json-view": "^1.27.0", @@ -226,4 +226,4 @@ "vitest-webgl-canvas-mock": "^1.1.0", "ws": "^8.18.3" } -} \ No newline at end of file +} diff --git a/rust/Cargo.lock b/rust/Cargo.lock index d25035e906f..3150cda7800 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -673,12 +673,13 @@ dependencies = [ [[package]] name = "csscolorparser" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9e6b904cb9ee4cb0bb93ba2b1bf3dcd2d3fc58c25557934a4b56cbd2ad9f88" +checksum = "02ee6eae4d99456f92dc379ba21cf08f783ef5525f193c3854b4e921ece045c5" dependencies = [ "num-traits 0.2.19", "phf", + "serde", "uncased", ] @@ -1980,9 +1981,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.44.1" +version = "1.44.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8732d3774162a0851e3f2b150eb98f31a9885dd75985099421d393385a01dfd" +checksum = "b5c943d4415edd8153251b6f197de5eb1640e56d84e8d9159bea190421c73698" dependencies = [ "console", "once_cell", @@ -2096,9 +2097,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.82" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", @@ -5024,9 +5025,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" dependencies = [ "once_cell", "valuable", @@ -5055,9 +5056,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ "nu-ansi-term", "serde", @@ -5345,9 +5346,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", @@ -5358,9 +5359,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.55" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ "cfg-if", "futures-core", @@ -5372,9 +5373,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5382,9 +5383,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ "bumpalo", "proc-macro2", @@ -5395,21 +5396,29 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-bindgen-test" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfc379bfb624eb59050b509c13e77b4eb53150c350db69628141abce842f2373" +checksum = "25e90e66d265d3a1efc0e72a54809ab90b9c0c515915c67cdf658689d2c22c6c" dependencies = [ + "async-trait", + "cast", "js-sys", + "libm", "minicov", + "nu-ansi-term", + "num-traits 0.2.19", + "oorandom", + "serde", + "serde_json", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test-macro", @@ -5417,9 +5426,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "085b2df989e1e6f9620c1311df6c996e83fe16f57792b272ce1e024ac16a90f1" +checksum = "7150335716dce6028bead2b848e72f47b45e7b9422f64cccdc23bedca89affc1" dependencies = [ "proc-macro2", "quote", @@ -5441,9 +5450,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.82" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", @@ -5626,9 +5635,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index f25bbf7d873..9076576d580 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -47,7 +47,7 @@ slog-json = "2.6.1" slog-term = "2.9.2" tokio = { version = "1" } tower-lsp = { version = "0.20.0", default-features = false } -tracing-subscriber = { version = "0.3.20", features = [ +tracing-subscriber = { version = "0.3.22", features = [ "registry", "std", "fmt", diff --git a/rust/kcl-language-server/package.json b/rust/kcl-language-server/package.json index 982febb509a..675dfd58731 100644 --- a/rust/kcl-language-server/package.json +++ b/rust/kcl-language-server/package.json @@ -124,7 +124,7 @@ "@vscode/vsce": "^3.3.2", "cross-env": "^10.1.0", "esbuild": "^0.27.0", - "glob": "^11.0.3", + "glob": "^13.0.0", "mocha": "^11.1.0", "typescript": "^5.8.3" }, diff --git a/rust/kcl-lib/Cargo.toml b/rust/kcl-lib/Cargo.toml index 8ec40219531..3f93ebc01f5 100644 --- a/rust/kcl-lib/Cargo.toml +++ b/rust/kcl-lib/Cargo.toml @@ -52,7 +52,7 @@ clap = { version = "4.5.53", default-features = false, optional = true, features "derive", ] } convert_case = "0.10.0" -csscolorparser = "0.8.0" +csscolorparser = "0.8.1" dashmap = { workspace = true } dhat = { version = "0.3", optional = true } fnv = "1.0.7" @@ -144,7 +144,7 @@ criterion = { version = "0.7.0", features = ["async_tokio"] } expectorate = "1.2.0" handlebars = "6.3.2" image = { version = "0.25.9", default-features = false, features = ["png"] } -insta = { version = "1.44.1", features = ["json", "filters", "redactions"] } +insta = { version = "1.44.3", features = ["json", "filters", "redactions"] } kcl-directory-test-macro = { version = "0.1", path = "../kcl-directory-test-macro" } miette = { version = "7.6.0", features = ["fancy"] } pretty_assertions = "1.4.1" diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 6ea1284aa66..6fe8bdee360 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -406,9 +406,22 @@ impl ExecutorContext { exec_state.mod_local.being_declared = prev_being_declared; let rhs = rhs_result?; - exec_state - .mut_stack() - .add(var_name.clone(), rhs.clone(), source_range)?; + let should_bind_name = + if let Some(fn_name) = variable_declaration.declaration.init.fn_declaring_name() { + // Declaring a function with a name, so only bind + // the variable name if it differs from the function + // name. + var_name != fn_name + } else { + // Not declaring a function, so we should bind the + // variable name. + true + }; + if should_bind_name { + exec_state + .mut_stack() + .add(var_name.clone(), rhs.clone(), source_range)?; + } // Track operations, for the feature tree. // Don't track these operations if the KCL code being executed is in the stdlib, @@ -792,7 +805,7 @@ impl ExecutorContext { // Check the KCL @(feature_tree = ) annotation. let include_in_feature_tree = attrs.unwrap_or_default().include_in_feature_tree; - if let Some(attrs) = attrs + let closure = if let Some(attrs) = attrs && (attrs.impl_ == annotations::Impl::Rust || attrs.impl_ == annotations::Impl::RustConstrainable || attrs.impl_ == annotations::Impl::RustConstraint) @@ -825,7 +838,17 @@ impl ExecutorContext { )), meta: vec![metadata.to_owned()], } + }; + + // If the function expression has a name, i.e. `fn name() {}`, + // bind it in the current scope. + if let Some(fn_name) = &function_expression.name { + exec_state + .mut_stack() + .add(fn_name.name.clone(), closure.clone(), metadata.source_range)?; } + + closure } Expr::CallExpressionKw(call_expression) => call_expression.execute(exec_state, self).await?, Expr::PipeExpression(pipe_expression) => pipe_expression.get_result(exec_state, self).await?, @@ -2493,129 +2516,145 @@ impl Node { impl Node { pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result { - if self.operator == UnaryOperator::Not { - let value = self.argument.get_result(exec_state, ctx).await?; - let KclValue::Bool { - value: bool_value, - meta: _, - } = value - else { - return Err(KclError::new_semantic(KclErrorDetails::new( - format!( - "Cannot apply unary operator ! to non-boolean value: {}", - value.human_friendly_type() - ), - vec![self.into()], - ))); - }; - let meta = vec![Metadata { - source_range: self.into(), - }]; - let negated = KclValue::Bool { - value: !bool_value, - meta, - }; - - return Ok(negated); - } - - let value = &self.argument.get_result(exec_state, ctx).await?; - let err = || { - KclError::new_semantic(KclErrorDetails::new( - format!( - "You can only negate numbers, planes, or lines, but this is a {}", - value.human_friendly_type() - ), - vec![self.into()], - )) - }; - match value { - KclValue::Number { value, ty, .. } => { + match self.operator { + UnaryOperator::Not => { + let value = self.argument.get_result(exec_state, ctx).await?; + let KclValue::Bool { + value: bool_value, + meta: _, + } = value + else { + return Err(KclError::new_semantic(KclErrorDetails::new( + format!( + "Cannot apply unary operator ! to non-boolean value: {}", + value.human_friendly_type() + ), + vec![self.into()], + ))); + }; let meta = vec![Metadata { source_range: self.into(), }]; - Ok(KclValue::Number { - value: -value, + let negated = KclValue::Bool { + value: !bool_value, meta, - ty: *ty, - }) - } - KclValue::Plane { value } => { - let mut plane = value.clone(); - if plane.info.x_axis.x != 0.0 { - plane.info.x_axis.x *= -1.0; - } - if plane.info.x_axis.y != 0.0 { - plane.info.x_axis.y *= -1.0; - } - if plane.info.x_axis.z != 0.0 { - plane.info.x_axis.z *= -1.0; - } + }; - plane.value = PlaneType::Uninit; - plane.id = exec_state.next_uuid(); - Ok(KclValue::Plane { value: plane }) + Ok(negated) } - KclValue::Object { - value: values, meta, .. - } => { - // Special-case for negating line-like objects. - let Some(direction) = values.get("direction") else { - return Err(err()); + UnaryOperator::Neg => { + let value = &self.argument.get_result(exec_state, ctx).await?; + let err = || { + KclError::new_semantic(KclErrorDetails::new( + format!( + "You can only negate numbers, planes, or lines, but this is a {}", + value.human_friendly_type() + ), + vec![self.into()], + )) }; - - let direction = match direction { - KclValue::Tuple { value: values, meta } => { - let values = values - .iter() - .map(|v| match v { - KclValue::Number { value, ty, meta } => Ok(KclValue::Number { - value: *value * -1.0, - ty: *ty, - meta: meta.clone(), - }), - _ => Err(err()), - }) - .collect::, _>>()?; - - KclValue::Tuple { - value: values, - meta: meta.clone(), + match value { + KclValue::Number { value, ty, .. } => { + let meta = vec![Metadata { + source_range: self.into(), + }]; + Ok(KclValue::Number { + value: -value, + meta, + ty: *ty, + }) + } + KclValue::Plane { value } => { + let mut plane = value.clone(); + if plane.info.x_axis.x != 0.0 { + plane.info.x_axis.x *= -1.0; } + if plane.info.x_axis.y != 0.0 { + plane.info.x_axis.y *= -1.0; + } + if plane.info.x_axis.z != 0.0 { + plane.info.x_axis.z *= -1.0; + } + + plane.value = PlaneType::Uninit; + plane.id = exec_state.next_uuid(); + Ok(KclValue::Plane { value: plane }) } - KclValue::HomArray { - value: values, - ty: ty @ RuntimeType::Primitive(PrimitiveType::Number(_)), + KclValue::Object { + value: values, meta, .. } => { - let values = values - .iter() - .map(|v| match v { - KclValue::Number { value, ty, meta } => Ok(KclValue::Number { - value: *value * -1.0, - ty: *ty, + // Special-case for negating line-like objects. + let Some(direction) = values.get("direction") else { + return Err(err()); + }; + + let direction = match direction { + KclValue::Tuple { value: values, meta } => { + let values = values + .iter() + .map(|v| match v { + KclValue::Number { value, ty, meta } => Ok(KclValue::Number { + value: *value * -1.0, + ty: *ty, + meta: meta.clone(), + }), + _ => Err(err()), + }) + .collect::, _>>()?; + + KclValue::Tuple { + value: values, meta: meta.clone(), - }), - _ => Err(err()), - }) - .collect::, _>>()?; - - KclValue::HomArray { - value: values, - ty: ty.clone(), - } - } - _ => return Err(err()), - }; + } + } + KclValue::HomArray { + value: values, + ty: ty @ RuntimeType::Primitive(PrimitiveType::Number(_)), + } => { + let values = values + .iter() + .map(|v| match v { + KclValue::Number { value, ty, meta } => Ok(KclValue::Number { + value: *value * -1.0, + ty: *ty, + meta: meta.clone(), + }), + _ => Err(err()), + }) + .collect::, _>>()?; + + KclValue::HomArray { + value: values, + ty: ty.clone(), + } + } + _ => return Err(err()), + }; - let mut value = values.clone(); - value.insert("direction".to_owned(), direction); - Ok(KclValue::Object { - value, - meta: meta.clone(), - constrainable: false, - }) + let mut value = values.clone(); + value.insert("direction".to_owned(), direction); + Ok(KclValue::Object { + value, + meta: meta.clone(), + constrainable: false, + }) + } + _ => Err(err()), + } + } + UnaryOperator::Plus => { + let operand = &self.argument.get_result(exec_state, ctx).await?; + match operand { + KclValue::Number { .. } | KclValue::Plane { .. } => Ok(operand.clone()), + _ => Err(KclError::new_semantic(KclErrorDetails::new( + format!( + "You can only apply unary + to numbers or planes, but this is a {}", + operand.human_friendly_type() + ), + vec![self.into()], + ))), + } } - _ => Err(err()), } } } diff --git a/rust/kcl-lib/src/execution/fn_call.rs b/rust/kcl-lib/src/execution/fn_call.rs index 068ad460244..42ae53e6e08 100644 --- a/rust/kcl-lib/src/execution/fn_call.rs +++ b/rust/kcl-lib/src/execution/fn_call.rs @@ -951,6 +951,7 @@ mod test { ] { // Run each test. let func_expr = Node::no_src(FunctionExpression { + name: None, params, body: Program::empty(), return_type: None, diff --git a/rust/kcl-lib/src/lint/checks/chained_profiles.rs b/rust/kcl-lib/src/lint/checks/chained_profiles.rs index d49e8fbd5d0..f9c1dfd82d2 100644 --- a/rust/kcl-lib/src/lint/checks/chained_profiles.rs +++ b/rust/kcl-lib/src/lint/checks/chained_profiles.rs @@ -310,7 +310,11 @@ fn find_defined_names_expr(expr: &Expr, defined_names: &mut HashSet) { find_defined_names_binary_part(&bin_expr.left, defined_names); find_defined_names_binary_part(&bin_expr.right, defined_names); } - Expr::FunctionExpression(_) => {} + Expr::FunctionExpression(func) => { + if let Some(name) = &func.name { + defined_names.insert(name.name.to_owned()); + } + } Expr::PipeSubstitution(_) => {} Expr::ArrayExpression(array) => { for element in &array.elements { diff --git a/rust/kcl-lib/src/parsing/ast/digest.rs b/rust/kcl-lib/src/parsing/ast/digest.rs index eedf872c304..ab7372d9976 100644 --- a/rust/kcl-lib/src/parsing/ast/digest.rs +++ b/rust/kcl-lib/src/parsing/ast/digest.rs @@ -274,6 +274,11 @@ impl KclNone { impl FunctionExpression { compute_digest!(|slf, hasher| { + if let Some(name) = &mut slf.name { + hasher.update(name.compute_digest()); + } else { + hasher.update(b"FunctionExpression::name::None"); + } hasher.update(slf.params.len().to_ne_bytes()); for param in slf.params.iter_mut() { hasher.update(param.compute_digest()); diff --git a/rust/kcl-lib/src/parsing/ast/types/mod.rs b/rust/kcl-lib/src/parsing/ast/types/mod.rs index 54a2fa8561d..79d28e09e08 100644 --- a/rust/kcl-lib/src/parsing/ast/types/mod.rs +++ b/rust/kcl-lib/src/parsing/ast/types/mod.rs @@ -1268,6 +1268,33 @@ impl Expr { _ => None, } } + + /// If we have a named function expression, return the name being declared. + /// This is a purely lexical check to handle the fact that we copy the fn + /// variable declaration name to the function expression name while parsing. + pub fn fn_declaring_name(&self) -> Option<&str> { + match self { + Expr::Literal(_) => None, + Expr::Name(_) => None, + Expr::TagDeclarator(_) => None, + Expr::BinaryExpression(_) => None, + Expr::FunctionExpression(func) => func.name.as_ref().map(|name| name.name.as_str()), + Expr::CallExpressionKw(_) => None, + Expr::PipeExpression(_) => None, + Expr::PipeSubstitution(_) => None, + Expr::ArrayExpression(_) => None, + Expr::ArrayRangeExpression(_) => None, + Expr::ObjectExpression(_) => None, + Expr::MemberExpression(_) => None, + Expr::UnaryExpression(_) => None, + Expr::IfExpression(_) => None, + Expr::LabelledExpression(node) => node.expr.fn_declaring_name(), + Expr::AscribedExpression(node) => node.expr.fn_declaring_name(), + Expr::SketchBlock(_) => None, + Expr::SketchVar(_) => None, + Expr::None(_) => None, + } + } } impl From for SourceRange { @@ -3297,6 +3324,10 @@ pub enum UnaryOperator { #[serde(rename = "!")] #[display("!")] Not, + /// Identity for numbers. + #[serde(rename = "+")] + #[display("+")] + Plus, } impl UnaryOperator { @@ -3304,6 +3335,7 @@ impl UnaryOperator { match self { UnaryOperator::Neg => *b"neg", UnaryOperator::Not => *b"not", + UnaryOperator::Plus => *b"pls", } } } @@ -3687,6 +3719,8 @@ fn return_true() -> bool { #[ts(export)] #[serde(tag = "type")] pub struct FunctionExpression { + #[serde(default, skip_serializing_if = "Option::is_none")] + pub name: Option>, pub params: Vec, pub body: Node, #[serde(skip)] @@ -3724,6 +3758,7 @@ impl FunctionExpression { &self, ) -> Result<(&[Parameter], &[Parameter]), RequiredParamAfterOptionalParam> { let Self { + name: _, params, body: _, digest: _, @@ -3794,6 +3829,7 @@ impl FunctionExpression { pub fn dummy() -> Box> { Box::new(Node::new( FunctionExpression { + name: None, params: Vec::new(), body: Node::new(Program::default(), 0, 0, ModuleId::default()), return_type: None, @@ -4336,6 +4372,7 @@ cylinder = startSketchOn(-XZ) "no params", (0..=0), Node::no_src(FunctionExpression { + name: None, params: vec![], body: Program::empty(), return_type: None, @@ -4346,6 +4383,7 @@ cylinder = startSketchOn(-XZ) "all required params", (1..=1), Node::no_src(FunctionExpression { + name: None, params: vec![Parameter { identifier: Node::no_src(Identifier { name: "foo".to_owned(), @@ -4365,6 +4403,7 @@ cylinder = startSketchOn(-XZ) "all optional params", (0..=1), Node::no_src(FunctionExpression { + name: None, params: vec![Parameter { identifier: Node::no_src(Identifier { name: "foo".to_owned(), @@ -4384,6 +4423,7 @@ cylinder = startSketchOn(-XZ) "mixed params", (1..=2), Node::no_src(FunctionExpression { + name: None, params: vec![ Parameter { identifier: Node::no_src(Identifier { diff --git a/rust/kcl-lib/src/parsing/ast/types/path.rs b/rust/kcl-lib/src/parsing/ast/types/path.rs index 3a4c7f9b213..cd325209fb3 100644 --- a/rust/kcl-lib/src/parsing/ast/types/path.rs +++ b/rust/kcl-lib/src/parsing/ast/types/path.rs @@ -41,6 +41,7 @@ pub enum Step { ExpressionStatementExpr, VariableDeclarationDeclaration, VariableDeclarationInit, + FunctionExpressionName, FunctionExpressionParam { index: usize }, FunctionExpressionBody, FunctionExpressionBodyItem { index: usize }, @@ -194,6 +195,12 @@ impl NodePath { } } Expr::FunctionExpression(node) => { + if let Some(name) = &node.name + && name.contains_range(&range) + { + path.push(Step::FunctionExpressionName); + return Some(path); + } for (i, param) in node.params.iter().enumerate() { // TODO: Check the type annotation and default value. if param.contains_range(&range) { diff --git a/rust/kcl-lib/src/parsing/parser.rs b/rust/kcl-lib/src/parsing/parser.rs index 18a7a1c4702..1a272d4d5ff 100644 --- a/rust/kcl-lib/src/parsing/parser.rs +++ b/rust/kcl-lib/src/parsing/parser.rs @@ -564,9 +564,22 @@ fn minus_sign(i: &mut TokenSlice) -> ModalResult { .parse_next(i) } +fn plus_sign(i: &mut TokenSlice) -> ModalResult { + any.verify_map(|token: Token| { + if token.token_type == TokenType::Operator && token.value == "+" { + Some(token) + } else { + None + } + }) + .context(expected("a plus sign `+`")) + .parse_next(i) +} + /// Numeric literal with suffix and optional leading negative sign. fn numeric_literal(i: &mut TokenSlice) -> ModalResult> { - let negative_token = opt(minus_sign).parse_next(i)?; + let prefix_token = opt(alt((minus_sign, plus_sign))).parse_next(i)?; + let is_negative = prefix_token.as_ref().is_some_and(|tok| tok.value == "-"); let (value, suffix, number_token) = any .try_map(|token: Token| match token.token_type { TokenType::Number => { @@ -585,14 +598,14 @@ fn numeric_literal(i: &mut TokenSlice) -> ModalResult> { }) .context(expected("a number literal (e.g. 3 or 12.5)")) .parse_next(i)?; - let start = negative_token.as_ref().map(|t| t.start).unwrap_or(number_token.start); + let start = prefix_token.as_ref().map(|t| t.start).unwrap_or(number_token.start); Ok(Node::new( NumericLiteral { - value: if negative_token.is_some() { -value } else { value }, + value: if is_negative { -value } else { value }, suffix, raw: format!( "{}{}", - negative_token.map(|t| t.value).unwrap_or_default(), + prefix_token.map(|t| t.value).unwrap_or_default(), number_token.value ), digest: None, @@ -1488,7 +1501,11 @@ fn if_expr(i: &mut TokenSlice) -> ModalResult> { fn function_expr(i: &mut TokenSlice) -> ModalResult { let fn_tok = opt(fun).parse_next(i)?; ignore_whitespace(i); - let result = function_decl.parse_next(i)?; + let name = opt(binding_name).parse_next(i)?; + ignore_whitespace(i); + let mut result = function_decl.parse_next(i)?; + // Make the function expression aware of its name. + result.name = name; if fn_tok.is_none() { let err = CompilationError::fatal(result.as_source_range(), "Anonymous function requires `fn` before `(`"); return Err(ErrMode::Cut(err.into())); @@ -1521,6 +1538,7 @@ fn function_decl(i: &mut TokenSlice) -> ModalResult> { let end = close.end; let result = Node::new( FunctionExpression { + name: None, params, body: body.into(), return_type, @@ -2430,6 +2448,11 @@ fn declaration(i: &mut TokenSlice) -> ModalResult> ignore_whitespace(i); let val = function_decl + .map(|mut func| { + // Make the function expression aware of its name. + func.name = Some(id.clone()); + func + }) .map(Box::new) .map(Expr::FunctionExpression) .context(expected("a KCL function expression, like () { return 1 }")) @@ -2768,6 +2791,7 @@ fn unary_expression(i: &mut TokenSlice) -> ModalResult> { let (operator, op_token) = any .try_map(|token: Token| match token.token_type { TokenType::Operator if token.value == "-" => Ok((UnaryOperator::Neg, token)), + TokenType::Operator if token.value == "+" => Ok((UnaryOperator::Plus, token)), TokenType::Operator => Err(CompilationError::fatal( token.as_source_range(), format!("{EXPECTED} but found {} which is an operator, but not a unary one (unary operators apply to just a single operand, your operator applies to two or more operands)", token.value.as_str(),), @@ -4916,15 +4940,6 @@ e assert_err_contains(r#"fn)n-"#, "expected whitespace, found ')' which is brace"); } - #[test] - fn test_parse_weird_lots_of_slashes() { - assert_err_contains( - r#"J///////////o//+///////////P++++*++++++P///////˟ -++4"#, - "Unexpected token: +", - ); - } - #[test] fn test_optional_param_order() { for (i, (params, expect_ok)) in [ @@ -5025,6 +5040,18 @@ e assert!(errs[0].message.contains("Define a function with `fn name()` instead") && errs[0].suggestion.is_some()); } + #[test] + fn function_defined_with_var_and_recursive_name() { + let code = r#" + foo = fn bar(@x) { + return x + } + answer = foo(2) + "#; + let (_, errs) = assert_no_err(code); + assert!(errs[0].message.contains("Define a function with `fn name()` instead") && errs[0].suggestion.is_some()); + } + #[test] fn test_error_keyword_in_variable() { assert_err( diff --git a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__ad.snap b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__ad.snap index 08afb454ff2..793be228486 100644 --- a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__ad.snap +++ b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__ad.snap @@ -50,6 +50,14 @@ expression: actual "commentStart": 24, "end": 51, "moduleId": 0, + "name": { + "commentStart": 8, + "end": 24, + "moduleId": 0, + "name": "firstPrimeNumber", + "start": 8, + "type": "Identifier" + }, "params": [], "start": 24, "type": "FunctionExpression", diff --git a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__ae.snap b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__ae.snap index fd9275284fb..c6de2f503e5 100644 --- a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__ae.snap +++ b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__ae.snap @@ -47,6 +47,14 @@ expression: actual "commentStart": 8, "end": 43, "moduleId": 0, + "name": { + "commentStart": 3, + "end": 8, + "moduleId": 0, + "name": "thing", + "start": 3, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__av.snap b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__av.snap index a860c8018eb..c70b7def34d 100644 --- a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__av.snap +++ b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__av.snap @@ -118,6 +118,14 @@ expression: actual "commentStart": 4, "end": 59, "moduleId": 0, + "name": { + "commentStart": 3, + "end": 4, + "moduleId": 0, + "name": "f", + "start": 3, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__g.snap b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__g.snap index e7d23fa5792..ba51ae99895 100644 --- a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__g.snap +++ b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__g.snap @@ -81,6 +81,14 @@ expression: actual "commentStart": 4, "end": 52, "moduleId": 0, + "name": { + "commentStart": 3, + "end": 4, + "moduleId": 0, + "name": "x", + "start": 3, + "type": "Identifier" + }, "params": [], "start": 4, "type": "FunctionExpression", diff --git a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_all_labeled.snap b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_all_labeled.snap index 6522217d6c9..a3e0506f81d 100644 --- a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_all_labeled.snap +++ b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_all_labeled.snap @@ -50,6 +50,14 @@ expression: actual "commentStart": 6, "end": 25, "moduleId": 0, + "name": { + "commentStart": 3, + "end": 6, + "moduleId": 0, + "name": "foo", + "start": 3, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_first_unlabeled.snap b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_first_unlabeled.snap index 5c95bd3d712..ed4670b0c3c 100644 --- a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_first_unlabeled.snap +++ b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_first_unlabeled.snap @@ -50,6 +50,14 @@ expression: actual "commentStart": 6, "end": 26, "moduleId": 0, + "name": { + "commentStart": 3, + "end": 6, + "moduleId": 0, + "name": "foo", + "start": 3, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_with_default_and_type.snap b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_with_default_and_type.snap index f6de63cfeff..3c998a6f756 100644 --- a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_with_default_and_type.snap +++ b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_with_default_and_type.snap @@ -50,6 +50,14 @@ expression: actual "commentStart": 6, "end": 35, "moduleId": 0, + "name": { + "commentStart": 3, + "end": 6, + "moduleId": 0, + "name": "foo", + "start": 3, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_with_default_no_type.snap b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_with_default_no_type.snap index c8319f22946..3632f6cda40 100644 --- a/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_with_default_no_type.snap +++ b/rust/kcl-lib/src/parsing/snapshots/kcl_lib__parsing__parser__snapshot_tests__kw_function_decl_with_default_no_type.snap @@ -50,6 +50,14 @@ expression: actual "commentStart": 6, "end": 27, "moduleId": 0, + "name": { + "commentStart": 3, + "end": 6, + "moduleId": 0, + "name": "foo", + "start": 3, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/src/simulation_tests.rs b/rust/kcl-lib/src/simulation_tests.rs index eca11f2ffa3..17b4a2e31d9 100644 --- a/rust/kcl-lib/src/simulation_tests.rs +++ b/rust/kcl-lib/src/simulation_tests.rs @@ -2340,6 +2340,27 @@ mod kw_fn_with_defaults { super::execute(TEST_NAME, false).await } } +mod function_expr_with_name { + const TEST_NAME: &str = "function_expr_with_name"; + + /// Test parsing KCL. + #[test] + fn parse() { + super::parse(TEST_NAME) + } + + /// Test that parsing and unparsing KCL produces the original KCL input. + #[tokio::test(flavor = "multi_thread")] + async fn unparse() { + super::unparse(TEST_NAME).await + } + + /// Test that KCL is executed correctly. + #[tokio::test(flavor = "multi_thread")] + async fn kcl_test_execute() { + super::execute(TEST_NAME, false).await + } +} mod boolean_logical_and { const TEST_NAME: &str = "boolean_logical_and"; @@ -4204,3 +4225,24 @@ mod sketch_on_face_normal_inches { super::execute(TEST_NAME, true).await } } +mod pos_literals { + const TEST_NAME: &str = "pos_literals"; + + /// Test parsing KCL. + #[test] + fn parse() { + super::parse(TEST_NAME) + } + + /// Test that parsing and unparsing KCL produces the original KCL input. + #[tokio::test(flavor = "multi_thread")] + async fn unparse() { + super::unparse(TEST_NAME).await + } + + /// Test that KCL is executed correctly. + #[tokio::test(flavor = "multi_thread")] + async fn kcl_test_execute() { + super::execute(TEST_NAME, true).await + } +} diff --git a/rust/kcl-lib/src/unparser.rs b/rust/kcl-lib/src/unparser.rs index 02cab29cf0a..ea4e10eff3e 100644 --- a/rust/kcl-lib/src/unparser.rs +++ b/rust/kcl-lib/src/unparser.rs @@ -305,7 +305,7 @@ impl ImportStatement { #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub(crate) enum ExprContext { Pipe, - Decl, + FnDecl, Other, } @@ -317,7 +317,7 @@ impl Expr { indentation_level: usize, mut ctxt: ExprContext, ) { - let is_decl = matches!(ctxt, ExprContext::Decl); + let is_decl = matches!(ctxt, ExprContext::FnDecl); if is_decl { // Just because this expression is being bound to a variable, doesn't mean that every child // expression is being bound. So, reset the expression context if necessary. @@ -336,6 +336,10 @@ impl Expr { Expr::FunctionExpression(func_exp) => { if !is_decl { buf.push_str("fn"); + if let Some(name) = &func_exp.name { + buf.push(' '); + buf.push_str(&name.name); + } } func_exp.recast(buf, options, indentation_level); } @@ -537,9 +541,9 @@ impl VariableDeclaration { ItemVisibility::Export => buf.push_str("export "), }; - let (keyword, eq) = match self.kind { - VariableKind::Fn => ("fn ", ""), - VariableKind::Const => ("", " = "), + let (keyword, eq, ctxt) = match self.kind { + VariableKind::Fn => ("fn ", "", ExprContext::FnDecl), + VariableKind::Const => ("", " = ", ExprContext::Other), }; buf.push_str(keyword); buf.push_str(&self.declaration.id.name); @@ -553,7 +557,7 @@ impl VariableDeclaration { let mut tmp_buf = String::new(); self.declaration .init - .recast(&mut tmp_buf, options, indentation_level, ExprContext::Decl); + .recast(&mut tmp_buf, options, indentation_level, ctxt); buf.push_str(tmp_buf.trim_start()); } } diff --git a/rust/kcl-lib/tests/add_lots/ast.snap b/rust/kcl-lib/tests/add_lots/ast.snap index 6948583a5d5..21129229bb5 100644 --- a/rust/kcl-lib/tests/add_lots/ast.snap +++ b/rust/kcl-lib/tests/add_lots/ast.snap @@ -78,6 +78,14 @@ description: Result of parsing add_lots.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "f", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/any_type/ast.snap b/rust/kcl-lib/tests/any_type/ast.snap index 17b2143f2ba..912d38bcd8a 100644 --- a/rust/kcl-lib/tests/any_type/ast.snap +++ b/rust/kcl-lib/tests/any_type/ast.snap @@ -56,6 +56,14 @@ description: Result of parsing any_type.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "id", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -154,6 +162,14 @@ description: Result of parsing any_type.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "singleton", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -393,6 +409,14 @@ description: Result of parsing any_type.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "len", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/argument_error/ast.snap b/rust/kcl-lib/tests/argument_error/ast.snap index 52f0b342649..18ed93dc812 100644 --- a/rust/kcl-lib/tests/argument_error/ast.snap +++ b/rust/kcl-lib/tests/argument_error/ast.snap @@ -51,6 +51,14 @@ description: Result of parsing argument_error.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "f", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/bad_units_in_annotation/ast.snap b/rust/kcl-lib/tests/bad_units_in_annotation/ast.snap index 69fe43b9f04..e61b5c84111 100644 --- a/rust/kcl-lib/tests/bad_units_in_annotation/ast.snap +++ b/rust/kcl-lib/tests/bad_units_in_annotation/ast.snap @@ -411,6 +411,14 @@ description: Result of parsing bad_units_in_annotation.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "createAtom", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/cube/ast.snap b/rust/kcl-lib/tests/cube/ast.snap index 3134689b368..8c16968b91b 100644 --- a/rust/kcl-lib/tests/cube/ast.snap +++ b/rust/kcl-lib/tests/cube/ast.snap @@ -1202,6 +1202,14 @@ description: Result of parsing cube.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/cube_with_error/ast.snap b/rust/kcl-lib/tests/cube_with_error/ast.snap index 82aa4761fa4..2a22ba4f471 100644 --- a/rust/kcl-lib/tests/cube_with_error/ast.snap +++ b/rust/kcl-lib/tests/cube_with_error/ast.snap @@ -1202,6 +1202,14 @@ description: Result of parsing cube_with_error.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/double_map_fn/ast.snap b/rust/kcl-lib/tests/double_map_fn/ast.snap index f4bcad0d0c5..c4a4ee3acb9 100644 --- a/rust/kcl-lib/tests/double_map_fn/ast.snap +++ b/rust/kcl-lib/tests/double_map_fn/ast.snap @@ -78,6 +78,14 @@ description: Result of parsing double_map_fn.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "increment", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/error_inside_fn_also_has_source_range_of_call_site_recursive/ast.snap b/rust/kcl-lib/tests/error_inside_fn_also_has_source_range_of_call_site_recursive/ast.snap index d5703e40895..c8564df1457 100644 --- a/rust/kcl-lib/tests/error_inside_fn_also_has_source_range_of_call_site_recursive/ast.snap +++ b/rust/kcl-lib/tests/error_inside_fn_also_has_source_range_of_call_site_recursive/ast.snap @@ -98,6 +98,14 @@ description: Result of parsing error_inside_fn_also_has_source_range_of_call_sit "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "someNestedFunction", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -205,6 +213,14 @@ description: Result of parsing error_inside_fn_also_has_source_range_of_call_sit "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "someFunction", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/export_var_only_at_top_level/ast.snap b/rust/kcl-lib/tests/export_var_only_at_top_level/ast.snap index b46f1619b9d..1d21267d7f4 100644 --- a/rust/kcl-lib/tests/export_var_only_at_top_level/ast.snap +++ b/rust/kcl-lib/tests/export_var_only_at_top_level/ast.snap @@ -89,6 +89,14 @@ description: Result of parsing export_var_only_at_top_level.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "main", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-lib/tests/fillet-and-shell/ast.snap b/rust/kcl-lib/tests/fillet-and-shell/ast.snap index 3b1ee60a251..ee264d60475 100644 --- a/rust/kcl-lib/tests/fillet-and-shell/ast.snap +++ b/rust/kcl-lib/tests/fillet-and-shell/ast.snap @@ -2793,6 +2793,14 @@ description: Result of parsing fillet-and-shell.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "m25Screw", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/function_expr_with_name/artifact_commands.snap b/rust/kcl-lib/tests/function_expr_with_name/artifact_commands.snap new file mode 100644 index 00000000000..42290a9eb2a --- /dev/null +++ b/rust/kcl-lib/tests/function_expr_with_name/artifact_commands.snap @@ -0,0 +1,5 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Artifact commands function_expr_with_name.kcl +--- +{} diff --git a/rust/kcl-lib/tests/function_expr_with_name/artifact_graph_flowchart.snap b/rust/kcl-lib/tests/function_expr_with_name/artifact_graph_flowchart.snap new file mode 100644 index 00000000000..c9985e33004 --- /dev/null +++ b/rust/kcl-lib/tests/function_expr_with_name/artifact_graph_flowchart.snap @@ -0,0 +1,6 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Artifact graph flowchart function_expr_with_name.kcl +extension: md +snapshot_kind: binary +--- diff --git a/rust/kcl-lib/tests/function_expr_with_name/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/function_expr_with_name/artifact_graph_flowchart.snap.md new file mode 100644 index 00000000000..13e53350976 --- /dev/null +++ b/rust/kcl-lib/tests/function_expr_with_name/artifact_graph_flowchart.snap.md @@ -0,0 +1,3 @@ +```mermaid +flowchart LR +``` diff --git a/rust/kcl-lib/tests/function_expr_with_name/ast.snap b/rust/kcl-lib/tests/function_expr_with_name/ast.snap new file mode 100644 index 00000000000..3dc452c0c45 --- /dev/null +++ b/rust/kcl-lib/tests/function_expr_with_name/ast.snap @@ -0,0 +1,746 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Result of parsing function_expr_with_name.kcl +--- +{ + "Ok": { + "body": [ + { + "commentStart": 0, + "declaration": { + "commentStart": 0, + "end": 0, + "id": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "square", + "start": 0, + "type": "Identifier" + }, + "init": { + "body": { + "body": [ + { + "argument": { + "commentStart": 0, + "end": 0, + "left": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "x", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + "moduleId": 0, + "operator": "*", + "right": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "x", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + "start": 0, + "type": "BinaryExpression", + "type": "BinaryExpression" + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ReturnStatement", + "type": "ReturnStatement" + } + ], + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0 + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "sq", + "start": 0, + "type": "Identifier" + }, + "params": [ + { + "type": "Parameter", + "identifier": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "x", + "start": 0, + "type": "Identifier" + }, + "labeled": false + } + ], + "start": 0, + "type": "FunctionExpression", + "type": "FunctionExpression" + }, + "moduleId": 0, + "start": 0, + "type": "VariableDeclarator" + }, + "end": 0, + "kind": "const", + "moduleId": 0, + "start": 0, + "type": "VariableDeclaration", + "type": "VariableDeclaration" + }, + { + "commentStart": 0, + "declaration": { + "commentStart": 0, + "end": 0, + "id": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "result", + "start": 0, + "type": "Identifier" + }, + "init": { + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "f", + "start": 0, + "type": "Identifier" + }, + "arg": { + "body": { + "body": [ + { + "argument": { + "commentStart": 0, + "end": 0, + "left": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "x", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + "moduleId": 0, + "operator": "+", + "right": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "1", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 1.0, + "suffix": "None" + } + }, + "start": 0, + "type": "BinaryExpression", + "type": "BinaryExpression" + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ReturnStatement", + "type": "ReturnStatement" + } + ], + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0 + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "inc", + "start": 0, + "type": "Identifier" + }, + "params": [ + { + "type": "Parameter", + "identifier": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "x", + "start": 0, + "type": "Identifier" + }, + "labeled": false + } + ], + "start": 0, + "type": "FunctionExpression", + "type": "FunctionExpression" + } + } + ], + "callee": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "map", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name" + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0, + "type": "CallExpressionKw", + "type": "CallExpressionKw", + "unlabeled": { + "commentStart": 0, + "elements": [ + { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "1", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 1.0, + "suffix": "None" + } + }, + { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "2", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 2.0, + "suffix": "None" + } + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + }, + "moduleId": 0, + "start": 0, + "type": "VariableDeclarator" + }, + "end": 0, + "kind": "const", + "moduleId": 0, + "start": 0, + "type": "VariableDeclaration", + "type": "VariableDeclaration" + }, + { + "commentStart": 0, + "end": 0, + "expression": { + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "isEqualTo", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "2", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 2.0, + "suffix": "None" + } + } + } + ], + "callee": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "assert", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name" + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0, + "type": "CallExpressionKw", + "type": "CallExpressionKw", + "unlabeled": { + "commentStart": 0, + "computed": true, + "end": 0, + "moduleId": 0, + "object": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "result", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + "property": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "0", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 0.0, + "suffix": "None" + } + }, + "start": 0, + "type": "MemberExpression", + "type": "MemberExpression" + } + }, + "moduleId": 0, + "start": 0, + "type": "ExpressionStatement", + "type": "ExpressionStatement" + }, + { + "commentStart": 0, + "end": 0, + "expression": { + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "isEqualTo", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "3", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 3.0, + "suffix": "None" + } + } + } + ], + "callee": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "assert", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name" + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0, + "type": "CallExpressionKw", + "type": "CallExpressionKw", + "unlabeled": { + "commentStart": 0, + "computed": true, + "end": 0, + "moduleId": 0, + "object": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "result", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + "property": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "1", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 1.0, + "suffix": "None" + } + }, + "start": 0, + "type": "MemberExpression", + "type": "MemberExpression" + } + }, + "moduleId": 0, + "start": 0, + "type": "ExpressionStatement", + "type": "ExpressionStatement" + }, + { + "commentStart": 0, + "end": 0, + "expression": { + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "isEqualTo", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "2", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 2.0, + "suffix": "None" + } + } + } + ], + "callee": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "assert", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name" + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0, + "type": "CallExpressionKw", + "type": "CallExpressionKw", + "unlabeled": { + "arguments": [], + "callee": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "count", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name" + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0, + "type": "CallExpressionKw", + "type": "CallExpressionKw", + "unlabeled": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "result", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + } + } + }, + "moduleId": 0, + "start": 0, + "type": "ExpressionStatement", + "type": "ExpressionStatement" + }, + { + "commentStart": 0, + "end": 0, + "expression": { + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "isEqualTo", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "42", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 42.0, + "suffix": "None" + } + } + } + ], + "callee": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "assert", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name" + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0, + "type": "CallExpressionKw", + "type": "CallExpressionKw", + "unlabeled": { + "arguments": [], + "callee": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "inc", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name" + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0, + "type": "CallExpressionKw", + "type": "CallExpressionKw", + "unlabeled": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "41", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 41.0, + "suffix": "None" + } + } + } + }, + "moduleId": 0, + "preComments": [ + "", + "", + "// Make sure inc was bound." + ], + "start": 0, + "type": "ExpressionStatement", + "type": "ExpressionStatement" + } + ], + "commentStart": 0, + "end": 0, + "moduleId": 0, + "nonCodeMeta": { + "nonCodeNodes": { + "0": [ + { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0, + "type": "NonCodeNode", + "value": { + "type": "newLine" + } + } + ], + "1": [ + { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0, + "type": "NonCodeNode", + "value": { + "type": "newLine" + } + } + ] + }, + "startNodes": [] + }, + "start": 0 + } +} diff --git a/rust/kcl-lib/tests/function_expr_with_name/execution_success.snap b/rust/kcl-lib/tests/function_expr_with_name/execution_success.snap new file mode 100644 index 00000000000..9117d111981 --- /dev/null +++ b/rust/kcl-lib/tests/function_expr_with_name/execution_success.snap @@ -0,0 +1,5 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Execution success function_expr_with_name.kcl +--- +null diff --git a/rust/kcl-lib/tests/function_expr_with_name/input.kcl b/rust/kcl-lib/tests/function_expr_with_name/input.kcl new file mode 100644 index 00000000000..ffd0299b877 --- /dev/null +++ b/rust/kcl-lib/tests/function_expr_with_name/input.kcl @@ -0,0 +1,14 @@ +square = fn sq(@x) { + return x * x +} + +result = map([1, 2], f = fn inc(@x) { + return x + 1 +}) + +assert(result[0], isEqualTo = 2) +assert(result[1], isEqualTo = 3) +assert(count(result), isEqualTo = 2) + +// Make sure inc was bound. +assert(inc(41), isEqualTo = 42) diff --git a/rust/kcl-lib/tests/function_expr_with_name/ops.snap b/rust/kcl-lib/tests/function_expr_with_name/ops.snap new file mode 100644 index 00000000000..90a39fa99b0 --- /dev/null +++ b/rust/kcl-lib/tests/function_expr_with_name/ops.snap @@ -0,0 +1,432 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Operations executed function_expr_with_name.kcl +--- +{ + "rust/kcl-lib/tests/function_expr_with_name/input.kcl": [ + { + "type": "GroupBegin", + "group": { + "type": "FunctionCall", + "name": null, + "functionSourceRange": [], + "unlabeledArg": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + }, + "sourceRange": [] + }, + "labeledArgs": {} + }, + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 1 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "GroupEnd" + }, + { + "type": "GroupBegin", + "group": { + "type": "FunctionCall", + "name": null, + "functionSourceRange": [], + "unlabeledArg": { + "value": { + "type": "Number", + "value": 2.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + }, + "sourceRange": [] + }, + "labeledArgs": {} + }, + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 1 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "GroupEnd" + }, + { + "type": "GroupBegin", + "group": { + "type": "FunctionCall", + "name": null, + "functionSourceRange": [], + "unlabeledArg": { + "value": { + "type": "Number", + "value": 2.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + }, + "sourceRange": [] + }, + "labeledArgs": { + "accum": { + "value": { + "type": "Number", + "value": 0.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + }, + "sourceRange": [] + } + } + }, + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 5 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + }, + { + "type": "FunctionExpressionBody" + }, + { + "type": "FunctionExpressionBodyItem", + "index": 0 + }, + { + "type": "ReturnStatementArg" + } + ] + }, + "sourceRange": [] + }, + { + "type": "GroupEnd" + }, + { + "type": "GroupBegin", + "group": { + "type": "FunctionCall", + "name": null, + "functionSourceRange": [], + "unlabeledArg": { + "value": { + "type": "Number", + "value": 3.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + }, + "sourceRange": [] + }, + "labeledArgs": { + "accum": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + }, + "sourceRange": [] + } + } + }, + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 5 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + }, + { + "type": "FunctionExpressionBody" + }, + { + "type": "FunctionExpressionBodyItem", + "index": 0 + }, + { + "type": "ReturnStatementArg" + } + ] + }, + "sourceRange": [] + }, + { + "type": "GroupEnd" + }, + { + "type": "GroupBegin", + "group": { + "type": "FunctionCall", + "name": "inc", + "functionSourceRange": [], + "unlabeledArg": { + "value": { + "type": "Number", + "value": 41.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + }, + "sourceRange": [] + }, + "labeledArgs": {} + }, + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 5 + }, + { + "type": "ExpressionStatementExpr" + }, + { + "type": "CallKwUnlabeledArg" + } + ] + }, + "sourceRange": [] + }, + { + "type": "GroupEnd" + } + ], + "std::math": [ + { + "type": "VariableDeclaration", + "name": "PI", + "value": { + "type": "Number", + "value": 3.141592653589793, + "ty": { + "type": "Unknown" + } + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 1 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "VariableDeclaration", + "name": "E", + "value": { + "type": "Number", + "value": 2.718281828459045, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 2 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "VariableDeclaration", + "name": "TAU", + "value": { + "type": "Number", + "value": 6.283185307179586, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 3 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + } + ], + "std::prelude": [ + { + "type": "VariableDeclaration", + "name": "START", + "value": { + "type": "String", + "value": "start" + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 20 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "VariableDeclaration", + "name": "END", + "value": { + "type": "String", + "value": "end" + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 21 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "VariableDeclaration", + "name": "NEW", + "value": { + "type": "String", + "value": "new" + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 22 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "VariableDeclaration", + "name": "MERGE", + "value": { + "type": "String", + "value": "merge" + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 23 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + } + ] +} diff --git a/rust/kcl-lib/tests/function_expr_with_name/program_memory.snap b/rust/kcl-lib/tests/function_expr_with_name/program_memory.snap new file mode 100644 index 00000000000..8c479f1c1e6 --- /dev/null +++ b/rust/kcl-lib/tests/function_expr_with_name/program_memory.snap @@ -0,0 +1,41 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Variables in memory after executing function_expr_with_name.kcl +--- +{ + "inc": { + "type": "Function", + "value": null + }, + "result": { + "type": "HomArray", + "value": [ + { + "type": "Number", + "value": 2.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + }, + { + "type": "Number", + "value": 3.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + } + ] + }, + "sq": { + "type": "Function", + "value": null + }, + "square": { + "type": "Function", + "value": null + } +} diff --git a/rust/kcl-lib/tests/function_expr_with_name/unparsed.snap b/rust/kcl-lib/tests/function_expr_with_name/unparsed.snap new file mode 100644 index 00000000000..b71753d9c01 --- /dev/null +++ b/rust/kcl-lib/tests/function_expr_with_name/unparsed.snap @@ -0,0 +1,21 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Result of unparsing function_expr_with_name.kcl +--- +square = fn sq(@x) { + return x * x +} + +result = map( + [1, 2], + f = fn inc(@x) { + return x + 1 + }, +) + +assert(result[0], isEqualTo = 2) +assert(result[1], isEqualTo = 3) +assert(count(result), isEqualTo = 2) + +// Make sure inc was bound. +assert(inc(41), isEqualTo = 42) diff --git a/rust/kcl-lib/tests/function_sketch/ast.snap b/rust/kcl-lib/tests/function_sketch/ast.snap index 26d91836242..86786e1df62 100644 --- a/rust/kcl-lib/tests/function_sketch/ast.snap +++ b/rust/kcl-lib/tests/function_sketch/ast.snap @@ -566,6 +566,14 @@ description: Result of parsing function_sketch.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "box", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/function_sketch_with_position/ast.snap b/rust/kcl-lib/tests/function_sketch_with_position/ast.snap index 11f0e1471f7..476dd2d7473 100644 --- a/rust/kcl-lib/tests/function_sketch_with_position/ast.snap +++ b/rust/kcl-lib/tests/function_sketch_with_position/ast.snap @@ -548,6 +548,14 @@ description: Result of parsing function_sketch_with_position.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "box", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/import_async/ast.snap b/rust/kcl-lib/tests/import_async/ast.snap index 8fa2c483703..79086331e8a 100644 --- a/rust/kcl-lib/tests/import_async/ast.snap +++ b/rust/kcl-lib/tests/import_async/ast.snap @@ -3320,6 +3320,14 @@ description: Result of parsing import_async.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "helicalGearSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -3794,6 +3802,14 @@ description: Result of parsing import_async.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "helicalGear", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/import_cycle1/ast.snap b/rust/kcl-lib/tests/import_cycle1/ast.snap index fc44c94ff7f..6e35c63a807 100644 --- a/rust/kcl-lib/tests/import_cycle1/ast.snap +++ b/rust/kcl-lib/tests/import_cycle1/ast.snap @@ -120,6 +120,14 @@ description: Result of parsing import_cycle1.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "one", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-lib/tests/import_function_not_sketch/ast.snap b/rust/kcl-lib/tests/import_function_not_sketch/ast.snap index 63601b2a25e..a85dd7eab3e 100644 --- a/rust/kcl-lib/tests/import_function_not_sketch/ast.snap +++ b/rust/kcl-lib/tests/import_function_not_sketch/ast.snap @@ -120,6 +120,14 @@ description: Result of parsing import_function_not_sketch.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "one", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-lib/tests/import_only_at_top_level/ast.snap b/rust/kcl-lib/tests/import_only_at_top_level/ast.snap index 3a03cc292e1..7ec3447c268 100644 --- a/rust/kcl-lib/tests/import_only_at_top_level/ast.snap +++ b/rust/kcl-lib/tests/import_only_at_top_level/ast.snap @@ -67,6 +67,14 @@ description: Result of parsing import_only_at_top_level.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "main", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-lib/tests/intersect_cubes/ast.snap b/rust/kcl-lib/tests/intersect_cubes/ast.snap index 6c79be53831..720e9b73162 100644 --- a/rust/kcl-lib/tests/intersect_cubes/ast.snap +++ b/rust/kcl-lib/tests/intersect_cubes/ast.snap @@ -930,6 +930,14 @@ description: Result of parsing intersect_cubes.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/angle-gauge/ast.snap b/rust/kcl-lib/tests/kcl_samples/angle-gauge/ast.snap index f0ed5e96179..852e27d4cdb 100644 --- a/rust/kcl-lib/tests/kcl_samples/angle-gauge/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/angle-gauge/ast.snap @@ -1585,6 +1585,14 @@ description: Result of parsing angle-gauge.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "gauge", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/battery-module-cooling-plate/ast.snap b/rust/kcl-lib/tests/kcl_samples/battery-module-cooling-plate/ast.snap index 38847fd99a7..f94f7ec89e5 100644 --- a/rust/kcl-lib/tests/kcl_samples/battery-module-cooling-plate/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/battery-module-cooling-plate/ast.snap @@ -1831,6 +1831,14 @@ description: Result of parsing battery-module-cooling-plate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "getOverlap", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -4837,6 +4845,14 @@ description: Result of parsing battery-module-cooling-plate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "coolingSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -6395,6 +6411,14 @@ description: Result of parsing battery-module-cooling-plate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "coolingSketchNoArms", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -6850,6 +6874,14 @@ description: Result of parsing battery-module-cooling-plate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "drawCoolingSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -7604,6 +7636,14 @@ description: Result of parsing battery-module-cooling-plate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "drawCoolingSketchFlipped", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/bone-plate/ast.snap b/rust/kcl-lib/tests/kcl_samples/bone-plate/ast.snap index 77723ae383d..6e2c124bbb4 100644 --- a/rust/kcl-lib/tests/kcl_samples/bone-plate/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/bone-plate/ast.snap @@ -2185,6 +2185,14 @@ description: Result of parsing bone-plate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "holeFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/brake-rotor/ast.snap b/rust/kcl-lib/tests/kcl_samples/brake-rotor/ast.snap index 08469fe302a..ffcc3e0157a 100644 --- a/rust/kcl-lib/tests/kcl_samples/brake-rotor/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/brake-rotor/ast.snap @@ -1733,6 +1733,14 @@ description: Result of parsing brake-rotor.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "drillHole", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -3056,6 +3064,14 @@ description: Result of parsing brake-rotor.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "createDiscHalf", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/clock/ast.snap b/rust/kcl-lib/tests/kcl_samples/clock/ast.snap index ffae4e31d81..3b5cf2046c5 100644 --- a/rust/kcl-lib/tests/kcl_samples/clock/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/clock/ast.snap @@ -11737,6 +11737,14 @@ description: Result of parsing clock.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "letterI", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -13719,6 +13727,14 @@ description: Result of parsing clock.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "letterX", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -14907,6 +14923,14 @@ description: Result of parsing clock.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "letterV", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/color-cube/ast.snap b/rust/kcl-lib/tests/kcl_samples/color-cube/ast.snap index 7cb62b8ac4d..95b51e31a59 100644 --- a/rust/kcl-lib/tests/kcl_samples/color-cube/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/color-cube/ast.snap @@ -1778,6 +1778,14 @@ description: Result of parsing color-cube.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "sketchRectangle", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/counterdrilled-weldment/ast.snap b/rust/kcl-lib/tests/kcl_samples/counterdrilled-weldment/ast.snap index f6fc8571f44..738bcd0a51a 100644 --- a/rust/kcl-lib/tests/kcl_samples/counterdrilled-weldment/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/counterdrilled-weldment/ast.snap @@ -3317,6 +3317,14 @@ description: Result of parsing counterdrilled-weldment.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "counterdrill", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -5882,6 +5890,14 @@ description: Result of parsing counterdrilled-weldment.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "fin", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/countersunk-plate/ast.snap b/rust/kcl-lib/tests/kcl_samples/countersunk-plate/ast.snap index 6926f9e9bd9..5fb899309e0 100644 --- a/rust/kcl-lib/tests/kcl_samples/countersunk-plate/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/countersunk-plate/ast.snap @@ -2602,6 +2602,14 @@ description: Result of parsing countersunk-plate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "countersink", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/cpu-cooler/ast.snap b/rust/kcl-lib/tests/kcl_samples/cpu-cooler/ast.snap index a770bca9a06..2908421fc9e 100644 --- a/rust/kcl-lib/tests/kcl_samples/cpu-cooler/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/cpu-cooler/ast.snap @@ -603,6 +603,14 @@ description: Result of parsing cpu-cooler.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "translatePart", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/curtain-wall-anchor-plate/ast.snap b/rust/kcl-lib/tests/kcl_samples/curtain-wall-anchor-plate/ast.snap index 1292aa182db..e06b88dbe8d 100644 --- a/rust/kcl-lib/tests/kcl_samples/curtain-wall-anchor-plate/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/curtain-wall-anchor-plate/ast.snap @@ -1553,6 +1553,14 @@ description: Result of parsing curtain-wall-anchor-plate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "lProfileFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -2339,6 +2347,14 @@ description: Result of parsing curtain-wall-anchor-plate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "hexagonFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -3095,6 +3111,14 @@ description: Result of parsing curtain-wall-anchor-plate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "boltFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -4616,6 +4640,14 @@ description: Result of parsing curtain-wall-anchor-plate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "boltWithPlateAndNutFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/ast.snap b/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/ast.snap index 7cc74eeb438..ad176b8a377 100644 --- a/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/ast.snap @@ -1578,6 +1578,14 @@ description: Result of parsing cycloidal-gear.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "gearSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -1876,6 +1884,14 @@ description: Result of parsing cycloidal-gear.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cycloidalGear", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/dodecahedron/ast.snap b/rust/kcl-lib/tests/kcl_samples/dodecahedron/ast.snap index b9c0d2a641c..4abbf369c39 100644 --- a/rust/kcl-lib/tests/kcl_samples/dodecahedron/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/dodecahedron/ast.snap @@ -1041,6 +1041,14 @@ description: Result of parsing dodecahedron.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "createFaceTemplate", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -2794,6 +2802,14 @@ description: Result of parsing dodecahedron.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "calculateArrayLength", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -2944,6 +2960,14 @@ description: Result of parsing dodecahedron.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "reduceIntersect", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -3331,6 +3355,14 @@ description: Result of parsing dodecahedron.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "createIntersection", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/enclosure/ast.snap b/rust/kcl-lib/tests/kcl_samples/enclosure/ast.snap index 99f6c4c609a..6ff3595b920 100644 --- a/rust/kcl-lib/tests/kcl_samples/enclosure/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/enclosure/ast.snap @@ -2399,6 +2399,14 @@ description: Result of parsing enclosure.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "function001", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/end-effector-gripper-fingers/ast.snap b/rust/kcl-lib/tests/kcl_samples/end-effector-gripper-fingers/ast.snap index a5e69f33176..f799882c3df 100644 --- a/rust/kcl-lib/tests/kcl_samples/end-effector-gripper-fingers/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/end-effector-gripper-fingers/ast.snap @@ -1676,6 +1676,14 @@ description: Result of parsing end-effector-gripper-fingers.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "sectionSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/exhaust-manifold/ast.snap b/rust/kcl-lib/tests/kcl_samples/exhaust-manifold/ast.snap index 82927c95ebd..00737be3a09 100644 --- a/rust/kcl-lib/tests/kcl_samples/exhaust-manifold/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/exhaust-manifold/ast.snap @@ -1822,6 +1822,14 @@ description: Result of parsing exhaust-manifold.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "primaryTube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/focusrite-scarlett-mounting-bracket/ast.snap b/rust/kcl-lib/tests/kcl_samples/focusrite-scarlett-mounting-bracket/ast.snap index 56473f3f390..9e2239be7b8 100644 --- a/rust/kcl-lib/tests/kcl_samples/focusrite-scarlett-mounting-bracket/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/focusrite-scarlett-mounting-bracket/ast.snap @@ -2312,6 +2312,14 @@ description: Result of parsing focusrite-scarlett-mounting-bracket.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "bracketSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/food-service-spatula/ast.snap b/rust/kcl-lib/tests/kcl_samples/food-service-spatula/ast.snap index 23e75d0e16c..d4c669a18d0 100644 --- a/rust/kcl-lib/tests/kcl_samples/food-service-spatula/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/food-service-spatula/ast.snap @@ -2645,6 +2645,14 @@ description: Result of parsing food-service-spatula.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "slot", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/gear-rack/ast.snap b/rust/kcl-lib/tests/kcl_samples/gear-rack/ast.snap index 95f16bcf020..c6c691ba93e 100644 --- a/rust/kcl-lib/tests/kcl_samples/gear-rack/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/gear-rack/ast.snap @@ -1642,6 +1642,14 @@ description: Result of parsing gear-rack.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "tooth", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate-magnets/ast.snap b/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate-magnets/ast.snap index ece8f9503ed..1bc53181113 100644 --- a/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate-magnets/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate-magnets/ast.snap @@ -1018,6 +1018,14 @@ description: Result of parsing gridfinity-baseplate-magnets.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "face", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -5770,6 +5778,14 @@ description: Result of parsing gridfinity-baseplate-magnets.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "magnetCenterCutout", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -6381,6 +6397,14 @@ description: Result of parsing gridfinity-baseplate-magnets.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "magnetBase", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate/ast.snap b/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate/ast.snap index f00e7d8211a..8827540dc7a 100644 --- a/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate/ast.snap @@ -907,6 +907,14 @@ description: Result of parsing gridfinity-baseplate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "face", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/gridfinity-bins-stacking-lip/ast.snap b/rust/kcl-lib/tests/kcl_samples/gridfinity-bins-stacking-lip/ast.snap index 5cb70e497df..ce7091cb0ad 100644 --- a/rust/kcl-lib/tests/kcl_samples/gridfinity-bins-stacking-lip/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/gridfinity-bins-stacking-lip/ast.snap @@ -1673,6 +1673,14 @@ description: Result of parsing gridfinity-bins-stacking-lip.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "face", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -8331,6 +8339,14 @@ description: Result of parsing gridfinity-bins-stacking-lip.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "lipFace", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/gridfinity-bins/ast.snap b/rust/kcl-lib/tests/kcl_samples/gridfinity-bins/ast.snap index c8cc367bd1a..1dd81e97493 100644 --- a/rust/kcl-lib/tests/kcl_samples/gridfinity-bins/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/gridfinity-bins/ast.snap @@ -1301,6 +1301,14 @@ description: Result of parsing gridfinity-bins.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "face", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/helical-gear/ast.snap b/rust/kcl-lib/tests/kcl_samples/helical-gear/ast.snap index 55d1284626e..655e44380d8 100644 --- a/rust/kcl-lib/tests/kcl_samples/helical-gear/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/helical-gear/ast.snap @@ -3115,6 +3115,14 @@ description: Result of parsing helical-gear.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "helicalGearSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -3589,6 +3597,14 @@ description: Result of parsing helical-gear.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "helicalGear", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/helical-planetary-gearset/ast.snap b/rust/kcl-lib/tests/kcl_samples/helical-planetary-gearset/ast.snap index c0c262b4e77..ab7fdf17da2 100644 --- a/rust/kcl-lib/tests/kcl_samples/helical-planetary-gearset/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/helical-planetary-gearset/ast.snap @@ -3203,6 +3203,14 @@ description: Result of parsing helical-planetary-gearset.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "helicalGearSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -3677,6 +3685,14 @@ description: Result of parsing helical-planetary-gearset.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "helicalGear", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -6118,6 +6134,14 @@ description: Result of parsing helical-planetary-gearset.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "ringGearSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -6597,6 +6621,14 @@ description: Result of parsing helical-planetary-gearset.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "ringGear", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/herringbone-gear/ast.snap b/rust/kcl-lib/tests/kcl_samples/herringbone-gear/ast.snap index 7a144e3a0eb..ff5ca1d3d4d 100644 --- a/rust/kcl-lib/tests/kcl_samples/herringbone-gear/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/herringbone-gear/ast.snap @@ -2192,6 +2192,14 @@ description: Result of parsing herringbone-gear.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "herringboneGearSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -2764,6 +2772,14 @@ description: Result of parsing herringbone-gear.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "herringboneGear", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/herringbone-planetary-gearset/ast.snap b/rust/kcl-lib/tests/kcl_samples/herringbone-planetary-gearset/ast.snap index ea8210fbab4..0c0c9c7690e 100644 --- a/rust/kcl-lib/tests/kcl_samples/herringbone-planetary-gearset/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/herringbone-planetary-gearset/ast.snap @@ -2192,6 +2192,14 @@ description: Result of parsing herringbone-planetary-gearset.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "herringboneGearSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -2764,6 +2772,14 @@ description: Result of parsing herringbone-planetary-gearset.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "herringboneGear", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -5205,6 +5221,14 @@ description: Result of parsing herringbone-planetary-gearset.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "ringGearSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -5777,6 +5801,14 @@ description: Result of parsing herringbone-planetary-gearset.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "ringGear", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/hex-nut/ast.snap b/rust/kcl-lib/tests/kcl_samples/hex-nut/ast.snap index b247693e1b9..7027856179e 100644 --- a/rust/kcl-lib/tests/kcl_samples/hex-nut/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/hex-nut/ast.snap @@ -1143,6 +1143,14 @@ description: Result of parsing hex-nut.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "hexNut", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/keyboard/ast.snap b/rust/kcl-lib/tests/kcl_samples/keyboard/ast.snap index a66e498f293..f94245dd51e 100644 --- a/rust/kcl-lib/tests/kcl_samples/keyboard/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/keyboard/ast.snap @@ -4537,6 +4537,14 @@ description: Result of parsing keyboard.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "keyFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -12097,6 +12105,14 @@ description: Result of parsing keyboard.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "z", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -14117,6 +14133,14 @@ description: Result of parsing keyboard.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "o", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/kitt/ast.snap b/rust/kcl-lib/tests/kcl_samples/kitt/ast.snap index d393c1cc745..be2c4b1fa1c 100644 --- a/rust/kcl-lib/tests/kcl_samples/kitt/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/kitt/ast.snap @@ -699,6 +699,14 @@ description: Result of parsing kitt.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "pixelBox", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -13507,6 +13515,14 @@ description: Result of parsing kitt.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "kitLeg", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -15826,6 +15842,14 @@ description: Result of parsing kitt.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "kitEar", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/makeup-mirror/ast.snap b/rust/kcl-lib/tests/kcl_samples/makeup-mirror/ast.snap index aebea199ad8..5688775f739 100644 --- a/rust/kcl-lib/tests/kcl_samples/makeup-mirror/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/makeup-mirror/ast.snap @@ -825,6 +825,14 @@ description: Result of parsing makeup-mirror.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "hingeFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -2465,6 +2473,14 @@ description: Result of parsing makeup-mirror.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "armFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -4161,6 +4177,14 @@ description: Result of parsing makeup-mirror.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "mirrorFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/manhole-cover/ast.snap b/rust/kcl-lib/tests/kcl_samples/manhole-cover/ast.snap index 74fa67d3fce..23e8ffcb497 100644 --- a/rust/kcl-lib/tests/kcl_samples/manhole-cover/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/manhole-cover/ast.snap @@ -1411,6 +1411,14 @@ description: Result of parsing manhole-cover.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "slot", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/pdu-faceplate/ast.snap b/rust/kcl-lib/tests/kcl_samples/pdu-faceplate/ast.snap index 39514209b65..f3391fcdf37 100644 --- a/rust/kcl-lib/tests/kcl_samples/pdu-faceplate/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/pdu-faceplate/ast.snap @@ -3264,6 +3264,14 @@ description: Result of parsing pdu-faceplate.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "boxModuleFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/sash-window/ast.snap b/rust/kcl-lib/tests/kcl_samples/sash-window/ast.snap index 3f7e063f243..dd107a74522 100644 --- a/rust/kcl-lib/tests/kcl_samples/sash-window/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/sash-window/ast.snap @@ -3305,6 +3305,14 @@ description: Result of parsing sash-window.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "panelFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/shepherds-hook-bolt/ast.snap b/rust/kcl-lib/tests/kcl_samples/shepherds-hook-bolt/ast.snap index 1c5095af60f..b1dff89088c 100644 --- a/rust/kcl-lib/tests/kcl_samples/shepherds-hook-bolt/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/shepherds-hook-bolt/ast.snap @@ -1212,6 +1212,14 @@ description: Result of parsing shepherds-hook-bolt.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "polarToCartesian", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/spinning-highrise-tower/ast.snap b/rust/kcl-lib/tests/kcl_samples/spinning-highrise-tower/ast.snap index 7a6fe51433d..4f4c2cdfa3b 100644 --- a/rust/kcl-lib/tests/kcl_samples/spinning-highrise-tower/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/spinning-highrise-tower/ast.snap @@ -1612,6 +1612,14 @@ description: Result of parsing spinning-highrise-tower.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "boxFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -1891,6 +1899,14 @@ description: Result of parsing spinning-highrise-tower.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "transformFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/spool/ast.snap b/rust/kcl-lib/tests/kcl_samples/spool/ast.snap index cace2b21268..04da3d00fe5 100644 --- a/rust/kcl-lib/tests/kcl_samples/spool/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/spool/ast.snap @@ -2036,6 +2036,14 @@ description: Result of parsing spool.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "score", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/spur-gear/ast.snap b/rust/kcl-lib/tests/kcl_samples/spur-gear/ast.snap index 0c8b7cc0822..a1b5bb9b5cb 100644 --- a/rust/kcl-lib/tests/kcl_samples/spur-gear/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/spur-gear/ast.snap @@ -2969,6 +2969,14 @@ description: Result of parsing spur-gear.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "spurGear", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/spur-reduction-gearset/ast.snap b/rust/kcl-lib/tests/kcl_samples/spur-reduction-gearset/ast.snap index f604200c2ce..0d5a10871c3 100644 --- a/rust/kcl-lib/tests/kcl_samples/spur-reduction-gearset/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/spur-reduction-gearset/ast.snap @@ -1949,6 +1949,14 @@ description: Result of parsing spur-reduction-gearset.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "spurGear", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/stylized-car/ast.snap b/rust/kcl-lib/tests/kcl_samples/stylized-car/ast.snap index a64168c85c2..ca47e50a763 100644 --- a/rust/kcl-lib/tests/kcl_samples/stylized-car/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/stylized-car/ast.snap @@ -3277,6 +3277,14 @@ description: Result of parsing stylized-car.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "makeWheelCutout", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -8244,6 +8252,14 @@ description: Result of parsing stylized-car.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "wheelFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/stylized-cybertruck/ast.snap b/rust/kcl-lib/tests/kcl_samples/stylized-cybertruck/ast.snap index 569648430f0..656ce070c0f 100644 --- a/rust/kcl-lib/tests/kcl_samples/stylized-cybertruck/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/stylized-cybertruck/ast.snap @@ -3090,6 +3090,14 @@ description: Result of parsing stylized-cybertruck.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "makeWheelCutout", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -8245,6 +8253,14 @@ description: Result of parsing stylized-cybertruck.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "wheelFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/stylized-dump-truck/ast.snap b/rust/kcl-lib/tests/kcl_samples/stylized-dump-truck/ast.snap index 42a991f8e09..08d6c899aa1 100644 --- a/rust/kcl-lib/tests/kcl_samples/stylized-dump-truck/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/stylized-dump-truck/ast.snap @@ -3301,6 +3301,14 @@ description: Result of parsing stylized-dump-truck.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "makeWheelCutout", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -9142,6 +9150,14 @@ description: Result of parsing stylized-dump-truck.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "wheelFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/stylized-firetruck/ast.snap b/rust/kcl-lib/tests/kcl_samples/stylized-firetruck/ast.snap index 48c0c0197e2..3b8cb43dae3 100644 --- a/rust/kcl-lib/tests/kcl_samples/stylized-firetruck/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/stylized-firetruck/ast.snap @@ -3513,6 +3513,14 @@ description: Result of parsing stylized-firetruck.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "makeWheelCutout", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -9892,6 +9900,14 @@ description: Result of parsing stylized-firetruck.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "wheelFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/stylized-mini-bus/ast.snap b/rust/kcl-lib/tests/kcl_samples/stylized-mini-bus/ast.snap index eac117f5d12..d2ab9711faf 100644 --- a/rust/kcl-lib/tests/kcl_samples/stylized-mini-bus/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/stylized-mini-bus/ast.snap @@ -3309,6 +3309,14 @@ description: Result of parsing stylized-mini-bus.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "makeWheelCutout", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -8276,6 +8284,14 @@ description: Result of parsing stylized-mini-bus.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "wheelFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/stylized-pickup-truck/ast.snap b/rust/kcl-lib/tests/kcl_samples/stylized-pickup-truck/ast.snap index 5e14c642474..c2a2ff43c4d 100644 --- a/rust/kcl-lib/tests/kcl_samples/stylized-pickup-truck/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/stylized-pickup-truck/ast.snap @@ -3277,6 +3277,14 @@ description: Result of parsing stylized-pickup-truck.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "makeWheelCutout", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -9322,6 +9330,14 @@ description: Result of parsing stylized-pickup-truck.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "wheelFn", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/t-slot-frame/ast.snap b/rust/kcl-lib/tests/kcl_samples/t-slot-frame/ast.snap index 88aa861e1cd..0ffa68d656b 100644 --- a/rust/kcl-lib/tests/kcl_samples/t-slot-frame/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/t-slot-frame/ast.snap @@ -2618,6 +2618,14 @@ description: Result of parsing t-slot-frame.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "railTslot", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/t-slot-rail/ast.snap b/rust/kcl-lib/tests/kcl_samples/t-slot-rail/ast.snap index 45e6b408654..d67f2641ee9 100644 --- a/rust/kcl-lib/tests/kcl_samples/t-slot-rail/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/t-slot-rail/ast.snap @@ -2470,6 +2470,14 @@ description: Result of parsing t-slot-rail.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "railTslot", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/t-slot-rectangle/ast.snap b/rust/kcl-lib/tests/kcl_samples/t-slot-rectangle/ast.snap index 75b1268e052..1a68e1ad7d7 100644 --- a/rust/kcl-lib/tests/kcl_samples/t-slot-rectangle/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/t-slot-rectangle/ast.snap @@ -2581,6 +2581,14 @@ description: Result of parsing t-slot-rectangle.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "railTslot", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/t-slot-shelf/ast.snap b/rust/kcl-lib/tests/kcl_samples/t-slot-shelf/ast.snap index ee636c43909..54ce422467b 100644 --- a/rust/kcl-lib/tests/kcl_samples/t-slot-shelf/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/t-slot-shelf/ast.snap @@ -2655,6 +2655,14 @@ description: Result of parsing t-slot-shelf.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "railTslot", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/telemetry-antenna/ast.snap b/rust/kcl-lib/tests/kcl_samples/telemetry-antenna/ast.snap index 6965c695b65..44477449b88 100644 --- a/rust/kcl-lib/tests/kcl_samples/telemetry-antenna/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/telemetry-antenna/ast.snap @@ -2373,6 +2373,14 @@ description: Result of parsing telemetry-antenna.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "countersink", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/thermal-block-insert/ast.snap b/rust/kcl-lib/tests/kcl_samples/thermal-block-insert/ast.snap index f461c72d1fc..231cf206c91 100644 --- a/rust/kcl-lib/tests/kcl_samples/thermal-block-insert/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/thermal-block-insert/ast.snap @@ -1334,6 +1334,14 @@ description: Result of parsing thermal-block-insert.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "tongueBlockFn", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-lib/tests/kcl_samples/tooling-nest-block/ast.snap b/rust/kcl-lib/tests/kcl_samples/tooling-nest-block/ast.snap index ad6edc39671..2d066083540 100644 --- a/rust/kcl-lib/tests/kcl_samples/tooling-nest-block/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/tooling-nest-block/ast.snap @@ -2051,6 +2051,14 @@ description: Result of parsing tooling-nest-block.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "nest", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/wind-turbine-blade-root-inserts/ast.snap b/rust/kcl-lib/tests/kcl_samples/wind-turbine-blade-root-inserts/ast.snap index 6052661dd41..2e7b3c47317 100644 --- a/rust/kcl-lib/tests/kcl_samples/wind-turbine-blade-root-inserts/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/wind-turbine-blade-root-inserts/ast.snap @@ -5877,6 +5877,14 @@ description: Result of parsing wind-turbine-blade-root-inserts.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "fanBladeSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -7033,6 +7041,14 @@ description: Result of parsing wind-turbine-blade-root-inserts.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "endCapSketch", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kcl_samples/zoo-logo/ast.snap b/rust/kcl-lib/tests/kcl_samples/zoo-logo/ast.snap index 26da393c13b..05620e4531e 100644 --- a/rust/kcl-lib/tests/kcl_samples/zoo-logo/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/zoo-logo/ast.snap @@ -2216,6 +2216,14 @@ description: Result of parsing zoo-logo.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "ZOO_O", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -2819,6 +2827,14 @@ description: Result of parsing zoo-logo.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "rot", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -8503,6 +8519,14 @@ description: Result of parsing zoo-logo.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "ZOO", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kw_fn/ast.snap b/rust/kcl-lib/tests/kw_fn/ast.snap index 0308ea0c8e9..aecca7e2584 100644 --- a/rust/kcl-lib/tests/kw_fn/ast.snap +++ b/rust/kcl-lib/tests/kw_fn/ast.snap @@ -78,6 +78,14 @@ description: Result of parsing kw_fn.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "increment", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -185,6 +193,14 @@ description: Result of parsing kw_fn.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "add", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kw_fn_too_few_args/ast.snap b/rust/kcl-lib/tests/kw_fn_too_few_args/ast.snap index 256844ed514..ed36f5a628e 100644 --- a/rust/kcl-lib/tests/kw_fn_too_few_args/ast.snap +++ b/rust/kcl-lib/tests/kw_fn_too_few_args/ast.snap @@ -83,6 +83,14 @@ description: Result of parsing kw_fn_too_few_args.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "add", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kw_fn_unlabeled_but_has_label/ast.snap b/rust/kcl-lib/tests/kw_fn_unlabeled_but_has_label/ast.snap index 2e66f63309d..28f1cf5b1bf 100644 --- a/rust/kcl-lib/tests/kw_fn_unlabeled_but_has_label/ast.snap +++ b/rust/kcl-lib/tests/kw_fn_unlabeled_but_has_label/ast.snap @@ -78,6 +78,14 @@ description: Result of parsing kw_fn_unlabeled_but_has_label.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "add", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/kw_fn_with_defaults/ast.snap b/rust/kcl-lib/tests/kw_fn_with_defaults/ast.snap index 344f280a015..7d2abe87779 100644 --- a/rust/kcl-lib/tests/kw_fn_with_defaults/ast.snap +++ b/rust/kcl-lib/tests/kw_fn_with_defaults/ast.snap @@ -83,6 +83,14 @@ description: Result of parsing kw_fn_with_defaults.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "increment", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/loop_tag/ast.snap b/rust/kcl-lib/tests/loop_tag/ast.snap index 9ade9709127..f43b0f08cba 100644 --- a/rust/kcl-lib/tests/loop_tag/ast.snap +++ b/rust/kcl-lib/tests/loop_tag/ast.snap @@ -521,6 +521,14 @@ description: Result of parsing loop_tag.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "calculatePoint", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/multi_transform/ast.snap b/rust/kcl-lib/tests/multi_transform/ast.snap index 5c6b496d28f..eade302c450 100644 --- a/rust/kcl-lib/tests/multi_transform/ast.snap +++ b/rust/kcl-lib/tests/multi_transform/ast.snap @@ -239,6 +239,14 @@ description: Result of parsing multi_transform.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "transform", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/pentagon_fillet_sugar/ast.snap b/rust/kcl-lib/tests/pentagon_fillet_sugar/ast.snap index e993e84bba1..80699cc4463 100644 --- a/rust/kcl-lib/tests/pentagon_fillet_sugar/ast.snap +++ b/rust/kcl-lib/tests/pentagon_fillet_sugar/ast.snap @@ -1069,6 +1069,14 @@ description: Result of parsing pentagon_fillet_sugar.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "circl", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/pipe_as_arg/ast.snap b/rust/kcl-lib/tests/pipe_as_arg/ast.snap index 85e97bfea7b..f1f9adcdfbc 100644 --- a/rust/kcl-lib/tests/pipe_as_arg/ast.snap +++ b/rust/kcl-lib/tests/pipe_as_arg/ast.snap @@ -56,6 +56,14 @@ description: Result of parsing pipe_as_arg.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -168,6 +176,14 @@ description: Result of parsing pipe_as_arg.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "double", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", @@ -243,6 +259,14 @@ description: Result of parsing pipe_as_arg.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "width", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-lib/tests/pipe_substitution_inside_function_called_from_pipeline/ast.snap b/rust/kcl-lib/tests/pipe_substitution_inside_function_called_from_pipeline/ast.snap index 0228a83bf79..015c0f86962 100644 --- a/rust/kcl-lib/tests/pipe_substitution_inside_function_called_from_pipeline/ast.snap +++ b/rust/kcl-lib/tests/pipe_substitution_inside_function_called_from_pipeline/ast.snap @@ -46,6 +46,14 @@ description: Result of parsing pipe_substitution_inside_function_called_from_pip "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "f", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/pos_literals/artifact_commands.snap b/rust/kcl-lib/tests/pos_literals/artifact_commands.snap new file mode 100644 index 00000000000..9481474edf3 --- /dev/null +++ b/rust/kcl-lib/tests/pos_literals/artifact_commands.snap @@ -0,0 +1,5 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Artifact commands pos_literals.kcl +--- +{} diff --git a/rust/kcl-lib/tests/pos_literals/artifact_graph_flowchart.snap b/rust/kcl-lib/tests/pos_literals/artifact_graph_flowchart.snap new file mode 100644 index 00000000000..fc2c9ff50ff --- /dev/null +++ b/rust/kcl-lib/tests/pos_literals/artifact_graph_flowchart.snap @@ -0,0 +1,6 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Artifact graph flowchart pos_literals.kcl +extension: md +snapshot_kind: binary +--- diff --git a/rust/kcl-lib/tests/pos_literals/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/pos_literals/artifact_graph_flowchart.snap.md new file mode 100644 index 00000000000..13e53350976 --- /dev/null +++ b/rust/kcl-lib/tests/pos_literals/artifact_graph_flowchart.snap.md @@ -0,0 +1,3 @@ +```mermaid +flowchart LR +``` diff --git a/rust/kcl-lib/tests/pos_literals/ast.snap b/rust/kcl-lib/tests/pos_literals/ast.snap new file mode 100644 index 00000000000..7bfb8934af2 --- /dev/null +++ b/rust/kcl-lib/tests/pos_literals/ast.snap @@ -0,0 +1,132 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Result of parsing pos_literals.kcl +--- +{ + "Ok": { + "body": [ + { + "commentStart": 0, + "declaration": { + "commentStart": 0, + "end": 0, + "id": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "x", + "start": 0, + "type": "Identifier" + }, + "init": { + "argument": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "2", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 2.0, + "suffix": "None" + } + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "operator": "+", + "start": 0, + "type": "UnaryExpression", + "type": "UnaryExpression" + }, + "moduleId": 0, + "start": 0, + "type": "VariableDeclarator" + }, + "end": 0, + "kind": "const", + "moduleId": 0, + "start": 0, + "type": "VariableDeclaration", + "type": "VariableDeclaration" + }, + { + "commentStart": 0, + "declaration": { + "commentStart": 0, + "end": 0, + "id": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "y", + "start": 0, + "type": "Identifier" + }, + "init": { + "arguments": [], + "callee": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "abs", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name" + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0, + "type": "CallExpressionKw", + "type": "CallExpressionKw", + "unlabeled": { + "argument": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "2", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 2.0, + "suffix": "None" + } + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "operator": "+", + "start": 0, + "type": "UnaryExpression", + "type": "UnaryExpression" + } + }, + "moduleId": 0, + "start": 0, + "type": "VariableDeclarator" + }, + "end": 0, + "kind": "const", + "moduleId": 0, + "start": 0, + "type": "VariableDeclaration", + "type": "VariableDeclaration" + } + ], + "commentStart": 0, + "end": 0, + "moduleId": 0, + "start": 0 + } +} diff --git a/rust/kcl-lib/tests/pos_literals/execution_success.snap b/rust/kcl-lib/tests/pos_literals/execution_success.snap new file mode 100644 index 00000000000..41e00c8e5ba --- /dev/null +++ b/rust/kcl-lib/tests/pos_literals/execution_success.snap @@ -0,0 +1,5 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Execution success pos_literals.kcl +--- +null diff --git a/rust/kcl-lib/tests/pos_literals/input.kcl b/rust/kcl-lib/tests/pos_literals/input.kcl new file mode 100644 index 00000000000..9bd5e258ad2 --- /dev/null +++ b/rust/kcl-lib/tests/pos_literals/input.kcl @@ -0,0 +1,2 @@ +x = +2 +y = abs(+2) diff --git a/rust/kcl-lib/tests/pos_literals/ops.snap b/rust/kcl-lib/tests/pos_literals/ops.snap new file mode 100644 index 00000000000..a272687120a --- /dev/null +++ b/rust/kcl-lib/tests/pos_literals/ops.snap @@ -0,0 +1,249 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Operations executed pos_literals.kcl +--- +{ + "rust/kcl-lib/tests/pos_literals/input.kcl": [ + { + "type": "VariableDeclaration", + "name": "x", + "value": { + "type": "Number", + "value": 2.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + }, + "visibility": "default", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 0 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "VariableDeclaration", + "name": "y", + "value": { + "type": "Number", + "value": 2.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + }, + "visibility": "default", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 1 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + } + ], + "std::math": [ + { + "type": "VariableDeclaration", + "name": "PI", + "value": { + "type": "Number", + "value": 3.141592653589793, + "ty": { + "type": "Unknown" + } + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 1 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "VariableDeclaration", + "name": "E", + "value": { + "type": "Number", + "value": 2.718281828459045, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 2 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "VariableDeclaration", + "name": "TAU", + "value": { + "type": "Number", + "value": 6.283185307179586, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 3 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + } + ], + "std::prelude": [ + { + "type": "VariableDeclaration", + "name": "START", + "value": { + "type": "String", + "value": "start" + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 20 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "VariableDeclaration", + "name": "END", + "value": { + "type": "String", + "value": "end" + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 21 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "VariableDeclaration", + "name": "NEW", + "value": { + "type": "String", + "value": "new" + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 22 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + }, + { + "type": "VariableDeclaration", + "name": "MERGE", + "value": { + "type": "String", + "value": "merge" + }, + "visibility": "export", + "nodePath": { + "steps": [ + { + "type": "ProgramBodyItem", + "index": 23 + }, + { + "type": "VariableDeclarationDeclaration" + }, + { + "type": "VariableDeclarationInit" + } + ] + }, + "sourceRange": [] + } + ] +} diff --git a/rust/kcl-lib/tests/pos_literals/program_memory.snap b/rust/kcl-lib/tests/pos_literals/program_memory.snap new file mode 100644 index 00000000000..830fb6ba38e --- /dev/null +++ b/rust/kcl-lib/tests/pos_literals/program_memory.snap @@ -0,0 +1,24 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Variables in memory after executing pos_literals.kcl +--- +{ + "x": { + "type": "Number", + "value": 2.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + }, + "y": { + "type": "Number", + "value": 2.0, + "ty": { + "type": "Default", + "len": "mm", + "angle": "degrees" + } + } +} diff --git a/rust/kcl-lib/tests/pos_literals/unparsed.snap b/rust/kcl-lib/tests/pos_literals/unparsed.snap new file mode 100644 index 00000000000..261aad58290 --- /dev/null +++ b/rust/kcl-lib/tests/pos_literals/unparsed.snap @@ -0,0 +1,6 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Result of unparsing pos_literals.kcl +--- +x = +2 +y = abs(+2) diff --git a/rust/kcl-lib/tests/property_access_not_found_on_solid/ast.snap b/rust/kcl-lib/tests/property_access_not_found_on_solid/ast.snap index 41ff0eafc03..6edabf6fe06 100644 --- a/rust/kcl-lib/tests/property_access_not_found_on_solid/ast.snap +++ b/rust/kcl-lib/tests/property_access_not_found_on_solid/ast.snap @@ -529,6 +529,14 @@ description: Result of parsing property_access_not_found_on_solid.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "myFunction", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-lib/tests/riddle_small/ast.snap b/rust/kcl-lib/tests/riddle_small/ast.snap index 9fc3f566bfe..1e7e6b61be5 100644 --- a/rust/kcl-lib/tests/riddle_small/ast.snap +++ b/rust/kcl-lib/tests/riddle_small/ast.snap @@ -164,6 +164,14 @@ description: Result of parsing riddle_small.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "t", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/rotate_after_fillet/ast.snap b/rust/kcl-lib/tests/rotate_after_fillet/ast.snap index f6b69626e41..8ab96b338a2 100644 --- a/rust/kcl-lib/tests/rotate_after_fillet/ast.snap +++ b/rust/kcl-lib/tests/rotate_after_fillet/ast.snap @@ -2166,6 +2166,14 @@ description: Result of parsing rotate_after_fillet.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "bolt", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-lib/tests/scale_after_fillet/ast.snap b/rust/kcl-lib/tests/scale_after_fillet/ast.snap index 366f5eba0d7..5b42ed7a207 100644 --- a/rust/kcl-lib/tests/scale_after_fillet/ast.snap +++ b/rust/kcl-lib/tests/scale_after_fillet/ast.snap @@ -2166,6 +2166,14 @@ description: Result of parsing scale_after_fillet.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "bolt", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/artifact_graph_flowchart.snap.md index 173e2c40685..80904b526ee 100644 --- a/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/artifact_graph_flowchart.snap.md +++ b/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/artifact_graph_flowchart.snap.md @@ -1,5 +1,5 @@ ```mermaid flowchart LR - 1["SketchBlock
[58, 216, 0]"] + 1["SketchBlock
[58, 217, 0]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlock] ``` diff --git a/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/ast.snap b/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/ast.snap index ff1dcaaa04c..f338cab929d 100644 --- a/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/ast.snap +++ b/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/ast.snap @@ -123,7 +123,7 @@ description: Result of parsing sketch_block_basic_fixed_constraints.kcl "commentStart": 0, "end": 0, "moduleId": 0, - "raw": "10", + "raw": "+10", "start": 0, "suffix": "None", "type": "NumericLiteral", diff --git a/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/input.kcl b/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/input.kcl index f789ddb0b56..b71d1ec91af 100644 --- a/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/input.kcl +++ b/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/input.kcl @@ -4,7 +4,7 @@ myParam = 4 s = sketch() { x = var 0 - y = var 10 + y = var +10 x == 1 + 2 y == max([5 * myParam, 0]) diff --git a/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/unparsed.snap b/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/unparsed.snap index 3545ade68c4..3a9a587d151 100644 --- a/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/unparsed.snap +++ b/rust/kcl-lib/tests/sketch_block_basic_fixed_constraints/unparsed.snap @@ -8,7 +8,7 @@ myParam = 4 s = sketch() { x = var 0 - y = var 10 + y = var +10 x == 1 + 2 y == max([5 * myParam, 0]) diff --git a/rust/kcl-lib/tests/sketch_in_object/ast.snap b/rust/kcl-lib/tests/sketch_in_object/ast.snap index bba3abfd73e..79ca8d02ba9 100644 --- a/rust/kcl-lib/tests/sketch_in_object/ast.snap +++ b/rust/kcl-lib/tests/sketch_in_object/ast.snap @@ -435,6 +435,14 @@ description: Result of parsing sketch_in_object.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "test", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", @@ -931,6 +939,14 @@ description: Result of parsing sketch_in_object.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "test2", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-lib/tests/sketch_on_face_circle_tagged/ast.snap b/rust/kcl-lib/tests/sketch_on_face_circle_tagged/ast.snap index 47c2365cd22..2faa48a9f67 100644 --- a/rust/kcl-lib/tests/sketch_on_face_circle_tagged/ast.snap +++ b/rust/kcl-lib/tests/sketch_on_face_circle_tagged/ast.snap @@ -457,6 +457,14 @@ description: Result of parsing sketch_on_face_circle_tagged.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/sketch_on_face_end/ast.snap b/rust/kcl-lib/tests/sketch_on_face_end/ast.snap index 0c577d7279f..61f44e16ab0 100644 --- a/rust/kcl-lib/tests/sketch_on_face_end/ast.snap +++ b/rust/kcl-lib/tests/sketch_on_face_end/ast.snap @@ -457,6 +457,14 @@ description: Result of parsing sketch_on_face_end.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/sketch_on_face_end_negative_extrude/ast.snap b/rust/kcl-lib/tests/sketch_on_face_end_negative_extrude/ast.snap index b3bbeae907e..b1ab7b2059c 100644 --- a/rust/kcl-lib/tests/sketch_on_face_end_negative_extrude/ast.snap +++ b/rust/kcl-lib/tests/sketch_on_face_end_negative_extrude/ast.snap @@ -457,6 +457,14 @@ description: Result of parsing sketch_on_face_end_negative_extrude.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/sketch_on_face_start/ast.snap b/rust/kcl-lib/tests/sketch_on_face_start/ast.snap index 204fc472453..5ace9ca7c87 100644 --- a/rust/kcl-lib/tests/sketch_on_face_start/ast.snap +++ b/rust/kcl-lib/tests/sketch_on_face_start/ast.snap @@ -457,6 +457,14 @@ description: Result of parsing sketch_on_face_start.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/subtract_cylinder_from_cube/ast.snap b/rust/kcl-lib/tests/subtract_cylinder_from_cube/ast.snap index d814bc6631c..b5e769b41bc 100644 --- a/rust/kcl-lib/tests/subtract_cylinder_from_cube/ast.snap +++ b/rust/kcl-lib/tests/subtract_cylinder_from_cube/ast.snap @@ -863,6 +863,14 @@ description: Result of parsing subtract_cylinder_from_cube.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/subtract_doesnt_need_brackets/ast.snap b/rust/kcl-lib/tests/subtract_doesnt_need_brackets/ast.snap index 2d2062c4368..6a86a08f6bd 100644 --- a/rust/kcl-lib/tests/subtract_doesnt_need_brackets/ast.snap +++ b/rust/kcl-lib/tests/subtract_doesnt_need_brackets/ast.snap @@ -903,6 +903,14 @@ description: Result of parsing subtract_doesnt_need_brackets.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/subtract_self/ast.snap b/rust/kcl-lib/tests/subtract_self/ast.snap index aa9b7cfd907..86cf892ebea 100644 --- a/rust/kcl-lib/tests/subtract_self/ast.snap +++ b/rust/kcl-lib/tests/subtract_self/ast.snap @@ -930,6 +930,14 @@ description: Result of parsing subtract_self.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/subtract_self_multiple_tools/ast.snap b/rust/kcl-lib/tests/subtract_self_multiple_tools/ast.snap index ac0f19bbb85..c6e2f65b1b4 100644 --- a/rust/kcl-lib/tests/subtract_self_multiple_tools/ast.snap +++ b/rust/kcl-lib/tests/subtract_self_multiple_tools/ast.snap @@ -930,6 +930,14 @@ description: Result of parsing subtract_self_multiple_tools.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/translate_after_fillet/ast.snap b/rust/kcl-lib/tests/translate_after_fillet/ast.snap index 800d902112a..5083db620f9 100644 --- a/rust/kcl-lib/tests/translate_after_fillet/ast.snap +++ b/rust/kcl-lib/tests/translate_after_fillet/ast.snap @@ -2166,6 +2166,14 @@ description: Result of parsing translate_after_fillet.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "bolt", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-lib/tests/union_cubes/ast.snap b/rust/kcl-lib/tests/union_cubes/ast.snap index 4a42a7fbff7..6bd4518f6ca 100644 --- a/rust/kcl-lib/tests/union_cubes/ast.snap +++ b/rust/kcl-lib/tests/union_cubes/ast.snap @@ -930,6 +930,14 @@ description: Result of parsing union_cubes.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/union_self/ast.snap b/rust/kcl-lib/tests/union_self/ast.snap index be3f9c8f334..a6a186d4e22 100644 --- a/rust/kcl-lib/tests/union_self/ast.snap +++ b/rust/kcl-lib/tests/union_self/ast.snap @@ -930,6 +930,14 @@ description: Result of parsing union_self.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/user_reported_union_2_bug/ast.snap b/rust/kcl-lib/tests/user_reported_union_2_bug/ast.snap index da41d5995b2..743ce62db38 100644 --- a/rust/kcl-lib/tests/user_reported_union_2_bug/ast.snap +++ b/rust/kcl-lib/tests/user_reported_union_2_bug/ast.snap @@ -1523,6 +1523,14 @@ description: Result of parsing user_reported_union_2_bug.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "createCube", + "start": 0, + "type": "Identifier" + }, "params": [ { "type": "Parameter", diff --git a/rust/kcl-lib/tests/var_ref_in_own_def_decl/ast.snap b/rust/kcl-lib/tests/var_ref_in_own_def_decl/ast.snap index def025ee0a3..adfe6014050 100644 --- a/rust/kcl-lib/tests/var_ref_in_own_def_decl/ast.snap +++ b/rust/kcl-lib/tests/var_ref_in_own_def_decl/ast.snap @@ -93,6 +93,14 @@ description: Result of parsing var_ref_in_own_def_decl.kcl "commentStart": 0, "end": 0, "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "declare", + "start": 0, + "type": "Identifier" + }, "params": [], "start": 0, "type": "FunctionExpression", diff --git a/rust/kcl-wasm-lib/Cargo.toml b/rust/kcl-wasm-lib/Cargo.toml index 36532e810e5..3d3428a9a80 100644 --- a/rust/kcl-wasm-lib/Cargo.toml +++ b/rust/kcl-wasm-lib/Cargo.toml @@ -49,7 +49,7 @@ features = [ [dev-dependencies] anyhow.workspace = true pretty_assertions = "1.4.1" -wasm-bindgen-test = "0.3.55" +wasm-bindgen-test = "0.3.56" # Local development only. Placeholder to speed up development cycle #[package.metadata.wasm-pack.profile.release] diff --git a/src/App.tsx b/src/App.tsx index b06954c9496..b2cf93fd6b2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -143,7 +143,7 @@ export function App() { kclManager ) - useEngineConnectionSubscriptions(kclManager) + useEngineConnectionSubscriptions() useEffect(() => { // Not too useful for regular flows but on modeling view refresh, diff --git a/src/components/CommandBar/CommandBarKclInput.tsx b/src/components/CommandBar/CommandBarKclInput.tsx index f55fe06164b..4d9759cfde4 100644 --- a/src/components/CommandBar/CommandBarKclInput.tsx +++ b/src/components/CommandBar/CommandBarKclInput.tsx @@ -26,7 +26,7 @@ import type { CommandArgument, KclCommandValue } from '@src/lib/commandTypes' import { kclManager, rustContext } from '@src/lib/singletons' import { useSettings } from '@src/lib/singletons' import { commandBarActor, useCommandBarState } from '@src/lib/singletons' -import { getSystemTheme } from '@src/lib/theme' +import { getResolvedTheme } from '@src/lib/theme' import { err } from '@src/lib/trap' import { useCalculateKclExpression } from '@src/lib/useCalculateKclExpression' import { roundOff, roundOffWithUnits } from '@src/lib/utils' @@ -34,6 +34,7 @@ import { varMentions } from '@src/lib/varCompletionExtension' import { useModelingContext } from '@src/hooks/useModelingContext' import styles from './CommandBarKclInput.module.css' +import { editorTheme } from '@src/lib/codeEditor' // TODO: remove the need for this selector once we decouple all actors from React const machineContextSelector = (snapshot?: SnapshotFrom) => @@ -179,11 +180,9 @@ function CommandBarKclInput({ ? previouslySetValue.valueText.length : defaultValue.length, }, - theme: - settings.app.theme.current === 'system' - ? getSystemTheme() - : settings.app.theme.current, extensions: [ + // Typically we prefer to update CodeMirror outside of React, but this "micro-editor" doesn't exist outside of React. + editorTheme[getResolvedTheme(settings.app.theme.current)], varMentionsExtension, EditorView.updateListener.of((vu: ViewUpdate) => { if (vu.docChanged) { diff --git a/src/components/CommandBar/CommandBarSelectionInput.tsx b/src/components/CommandBar/CommandBarSelectionInput.tsx index b161637474c..334f585c608 100644 --- a/src/components/CommandBar/CommandBarSelectionInput.tsx +++ b/src/components/CommandBar/CommandBarSelectionInput.tsx @@ -9,7 +9,11 @@ import { getSelectionTypeDisplayText, getSemanticSelectionType, } from '@src/lib/selections' -import { engineCommandManager, kclManager } from '@src/lib/singletons' +import { + engineCommandManager, + kclManager, + sceneEntitiesManager, +} from '@src/lib/singletons' import { commandBarActor, useCommandBarState } from '@src/lib/singletons' import { reportRejection } from '@src/lib/trap' import { toSync } from '@src/lib/utils' @@ -60,7 +64,12 @@ function CommandBarSelectionInput({ return () => { toSync(() => { const promises = [ - new Promise(() => kclManager.setSelectionFilterToDefault(selection)), + new Promise(() => + kclManager.setSelectionFilterToDefault( + sceneEntitiesManager, + selection + ) + ), ] if (!kclManager._isAstEmpty(kclManager.ast)) { promises.push(kclManager.hidePlanes()) @@ -144,8 +153,10 @@ function CommandBarSelectionInput({ // Set selection filter if needed, and reset it when the component unmounts useEffect(() => { - arg.selectionFilter && kclManager.setSelectionFilter(arg.selectionFilter) - return () => kclManager.setSelectionFilterToDefault(selection) + arg.selectionFilter && + kclManager.setSelectionFilter(arg.selectionFilter, sceneEntitiesManager) + return () => + kclManager.setSelectionFilterToDefault(sceneEntitiesManager, selection) // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: blanket-ignored fix me! }, [arg.selectionFilter]) diff --git a/src/components/CommandBar/CommandBarSelectionMixedInput.tsx b/src/components/CommandBar/CommandBarSelectionMixedInput.tsx index 0412ea48a69..88b49dcc77f 100644 --- a/src/components/CommandBar/CommandBarSelectionMixedInput.tsx +++ b/src/components/CommandBar/CommandBarSelectionMixedInput.tsx @@ -8,7 +8,11 @@ import { getSelectionTypeDisplayText, handleSelectionBatch, } from '@src/lib/selections' -import { kclManager, engineCommandManager } from '@src/lib/singletons' +import { + kclManager, + engineCommandManager, + sceneEntitiesManager, +} from '@src/lib/singletons' import { commandBarActor, useCommandBarState } from '@src/lib/singletons' import { coerceSelectionsToBody } from '@src/lang/std/artifactGraph' import { err } from '@src/lib/trap' @@ -132,23 +136,25 @@ export default function CommandBarSelectionMixedInput({ if (arg.selectionFilter && hasCoercedSelections) { // Batch the filter change with selection restoration // This is critical for body-only commands where we've coerced face/edge selections to bodies - setSelectionFilter( - arg.selectionFilter, + setSelectionFilter({ + filter: arg.selectionFilter, engineCommandManager, kclManager, - selection, - handleSelectionBatch - ) + sceneEntitiesManager, + selectionsToRestore: selection, + handleSelectionBatchFn: handleSelectionBatch, + }) } return () => { if (arg.selectionFilter && hasCoercedSelections) { // Restore default filter with selections on cleanup - setSelectionFilterToDefault( + setSelectionFilterToDefault({ engineCommandManager, kclManager, - selection, - handleSelectionBatch - ) + sceneEntitiesManager, + selectionsToRestore: selection, + handleSelectionBatchFn: handleSelectionBatch, + }) } } }, [arg.selectionFilter, selection, hasCoercedSelections]) diff --git a/src/components/ConnectionStream.tsx b/src/components/ConnectionStream.tsx index dcead7c8093..b72c7f8e190 100644 --- a/src/components/ConnectionStream.tsx +++ b/src/components/ConnectionStream.tsx @@ -39,6 +39,13 @@ import { EngineDebugger } from '@src/lib/debugger' const TIME_TO_CONNECT = 30_000 +// Object defined outside of React to prevent rerenders +const systemDeps = { + engineCommandManager, + kclManager, + sceneInfra, +} + export const ConnectionStream = (props: { pool: string | null authToken: string | undefined @@ -90,7 +97,9 @@ export const ConnectionStream = (props: { if (sceneInfra.camControls.wasDragging === true) return if (btnName(e.nativeEvent).left) { - sendSelectEventToEngine(e, videoRef.current).catch(reportRejection) + sendSelectEventToEngine(e, videoRef.current, { + engineCommandManager, + }).catch(reportRejection) } } @@ -111,7 +120,9 @@ export const ConnectionStream = (props: { return } - sendSelectEventToEngine(e, videoRef.current) + sendSelectEventToEngine(e, videoRef.current, { + engineCommandManager, + }) .then((result) => { if (!result) { return @@ -149,6 +160,7 @@ export const ConnectionStream = (props: { timeToConnect: TIME_TO_CONNECT, settings: settingsEngine, setShowManualConnect, + sceneInfra, }) .then(() => { // Take a screen shot after the page mounts and zoom to fit runs @@ -199,6 +211,7 @@ export const ConnectionStream = (props: { timeToConnect: TIME_TO_CONNECT, settings: settingsEngine, setShowManualConnect, + sceneInfra, }).catch((e) => { console.warn(e) setShowManualConnect(true) @@ -222,6 +235,7 @@ export const ConnectionStream = (props: { timeToConnect: TIME_TO_CONNECT, settings: settingsEngine, setShowManualConnect, + sceneInfra, }).catch((e) => { console.warn(e) setShowManualConnect(true) @@ -247,6 +261,7 @@ export const ConnectionStream = (props: { timeToConnect: TIME_TO_CONNECT, settings: settingsEngine, setShowManualConnect, + sceneInfra, }).catch((e) => { console.warn(e) setShowManualConnect(true) @@ -267,6 +282,7 @@ export const ConnectionStream = (props: { timeToConnect: TIME_TO_CONNECT, settings: settingsEngine, setShowManualConnect, + sceneInfra, }).catch((e) => { console.warn(e) setShowManualConnect(true) @@ -296,6 +312,7 @@ export const ConnectionStream = (props: { timeToConnect: TIME_TO_CONNECT, settings: settingsEngine, setShowManualConnect, + sceneInfra, }).catch((e) => { console.warn(e) setShowManualConnect(true) @@ -305,9 +322,8 @@ export const ConnectionStream = (props: { useOnFileRoute({ file, isStreamAcceptingInput, - engineCommandManager, - kclManager, resetCameraPosition, + systemDeps, }) useOnOfflineToExitSketchMode({ @@ -379,6 +395,7 @@ export const ConnectionStream = (props: { timeToConnect: TIME_TO_CONNECT, settings: settingsEngine, setShowManualConnect, + sceneInfra, }).catch((e) => { console.warn(e) setShowManualConnect(true) diff --git a/src/components/LspProvider.tsx b/src/components/LspProvider.tsx index 81d56a314de..6470493e15b 100644 --- a/src/components/LspProvider.tsx +++ b/src/components/LspProvider.tsx @@ -24,7 +24,7 @@ import { PROJECT_ENTRYPOINT } from '@src/lib/constants' import { isDesktop } from '@src/lib/isDesktop' import { PATHS } from '@src/lib/paths' import type { FileEntry } from '@src/lib/project' -import { kclManager } from '@src/lib/singletons' +import { kclManager, sceneEntitiesManager } from '@src/lib/singletons' import { useToken } from '@src/lib/singletons' import { err } from '@src/lib/trap' import { withAPIBaseURL } from '@src/lib/withBaseURL' @@ -164,7 +164,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => { } }, }, - kclManager + { kclManager, sceneEntitiesManager } ) plugin = lsp diff --git a/src/components/MlEphantConversation2.tsx b/src/components/MlEphantConversation2.tsx index 446c55f674d..5b30f436237 100644 --- a/src/components/MlEphantConversation2.tsx +++ b/src/components/MlEphantConversation2.tsx @@ -194,7 +194,7 @@ function BillingStatusBarItem(props: { billingContext: BillingContext }) { hoverOnly wrapperClassName="ui-open:!hidden" > - Text-to-CAD credits + Zookeeper credits )} diff --git a/src/components/ModelingMachineProvider.tsx b/src/components/ModelingMachineProvider.tsx index 1c3d7ee6ecb..7b4159fbeee 100644 --- a/src/components/ModelingMachineProvider.tsx +++ b/src/components/ModelingMachineProvider.tsx @@ -108,7 +108,6 @@ import type { OffsetPlane, } from '@src/machines/modelingSharedTypes' import { modelingMachine } from '@src/machines/modelingMachine' -import { modelingMachineDefaultContext } from '@src/machines/modelingSharedContext' import { useFolders } from '@src/machines/systemIO/hooks' import { @@ -126,6 +125,13 @@ import { toPlaneName } from '@src/lib/planes' const OVERLAY_TIMEOUT_MS = 1_000 +// Defined outside of React to prevent rerenders +const systemDeps = { + sceneInfra, + rustContext, + sceneEntitiesManager, +} + export const ModelingMachineContext = createContext( {} as { state: StateFrom @@ -537,7 +543,10 @@ export const ModelingMachineProvider = ({ let result: DefaultPlane | OffsetPlane | ExtrudeFacePlane | null = null - const defaultResult = getDefaultSketchPlaneData(artifactOrPlaneId) + const defaultResult = getDefaultSketchPlaneData( + artifactOrPlaneId, + systemDeps + ) if (!err(defaultResult) && defaultResult) { result = defaultResult } @@ -545,7 +554,10 @@ export const ModelingMachineProvider = ({ // Look up the artifact from the artifact graph for getOffsetSketchPlaneData if (!result) { const artifact = kclManager.artifactGraph.get(artifactOrPlaneId) - const offsetResult = await getOffsetSketchPlaneData(artifact) + const offsetResult = await getOffsetSketchPlaneData( + artifact, + systemDeps + ) if (!err(offsetResult) && offsetResult) { result = offsetResult } @@ -555,7 +567,8 @@ export const ModelingMachineProvider = ({ artifactOrPlaneId, kclManager.artifactGraph, kclManager.astSignal.value, - kclManager.execState + kclManager.execState, + systemDeps ) if (sweepFaceSelected) { result = sweepFaceSelected @@ -652,7 +665,8 @@ export const ModelingMachineProvider = ({ // Get plane/face data from the sketchBlock const planeData = await getPlaneDataFromSketchBlock( artifact, - kclManager.artifactGraph + kclManager.artifactGraph, + systemDeps ) if (!planeData) { console.trace('yo!!') @@ -1421,15 +1435,16 @@ export const ModelingMachineProvider = ({ }), { input: { - ...modelingMachineDefaultContext, + machineManager, + engineCommandManager, + kclManager, + sceneInfra, + rustContext, + sceneEntitiesManager, store: { - ...modelingMachineDefaultContext.store, - cameraProjection, useNewSketchMode, + cameraProjection, }, - machineManager, - sketchSolveToolName: null, - kclManager, }, // devTools: true, } @@ -1667,7 +1682,7 @@ export const ModelingMachineProvider = ({ modelingSend({ type: 'Center camera on selection' }) }) useHotkeys(['mod + alt + x'], () => { - resetCameraPosition().catch(reportRejection) + resetCameraPosition({ sceneInfra }).catch(reportRejection) }) // Toggle Snap to grid @@ -1689,7 +1704,10 @@ export const ModelingMachineProvider = ({ if (!inSketchMode) return e.preventDefault() - const selection = selectAllInCurrentSketch(kclManager.artifactGraph) + const selection = selectAllInCurrentSketch( + kclManager.artifactGraph, + systemDeps + ) modelingSend({ type: 'Set selection', data: { selectionType: 'completeSelection', selection }, diff --git a/src/components/ModelingPageProvider.tsx b/src/components/ModelingPageProvider.tsx index fb10796a908..54c021f2687 100644 --- a/src/components/ModelingPageProvider.tsx +++ b/src/components/ModelingPageProvider.tsx @@ -9,7 +9,11 @@ import { DEFAULT_DEFAULT_LENGTH_UNIT } from '@src/lib/constants' import { kclCommands } from '@src/lib/kclCommands' import { BROWSER_PATH, PATHS } from '@src/lib/paths' import { markOnce } from '@src/lib/performance' -import { engineCommandManager, kclManager } from '@src/lib/singletons' +import { + engineCommandManager, + kclManager, + sceneInfra, +} from '@src/lib/singletons' import { useSettings, useToken } from '@src/lib/singletons' import { commandBarActor } from '@src/lib/singletons' import { type IndexLoaderData } from '@src/lib/types' @@ -112,7 +116,8 @@ export const ModelingPageProvider = ({ settings, navigate, filePath, - engineCommandManager + engineCommandManager, + sceneInfra ) useMenuListener(cb) diff --git a/src/components/RouteProvider.tsx b/src/components/RouteProvider.tsx index 71f664f906c..c1ece8ad2ac 100644 --- a/src/components/RouteProvider.tsx +++ b/src/components/RouteProvider.tsx @@ -15,7 +15,7 @@ import { getAppSettingsFilePath } from '@src/lib/desktop' import { PATHS, getStringAfterLastSeparator } from '@src/lib/paths' import { markOnce } from '@src/lib/performance' import { loadAndValidateSettings } from '@src/lib/settings/settingsUtils' -import { kclManager, settingsActor } from '@src/lib/singletons' +import { kclManager, sceneInfra, settingsActor } from '@src/lib/singletons' import { trap } from '@src/lib/trap' import type { IndexLoaderData } from '@src/lib/types' import { kclEditorActor } from '@src/machines/kclEditorMachine' @@ -105,7 +105,7 @@ export function RouteProvider({ children }: { children: ReactNode }) { if (!isCodeTheSame(code, kclManager.codeSignal.value)) { kclManager.updateCodeStateEditor(code) await kclManager.executeCode() - await resetCameraPosition() + await resetCameraPosition({ sceneInfra }) } } } else if ( diff --git a/src/components/ViewControlMenu.tsx b/src/components/ViewControlMenu.tsx index a6484bd18ff..d470de53c33 100644 --- a/src/components/ViewControlMenu.tsx +++ b/src/components/ViewControlMenu.tsx @@ -15,6 +15,8 @@ import { resetCameraPosition } from '@src/lib/resetCameraPosition' import { getLayout, kclManager, + rustContext, + sceneEntitiesManager, sceneInfra, settingsActor, } from '@src/lib/singletons' @@ -74,7 +76,7 @@ export function useViewControlMenuItems() { , { - resetCameraPosition().catch(reportRejection) + resetCameraPosition({ sceneInfra }).catch(reportRejection) }} disabled={shouldLockView} hotkey="mod+alt+x" @@ -147,9 +149,14 @@ export function useViewControlMenuItems() { }) void selectSketchPlane( - kclManager, planeOrFaceId, - modelingState.context.store.useNewSketchMode?.current + modelingState.context.store.useNewSketchMode?.current, + { + kclManager, + rustContext, + sceneEntitiesManager, + sceneInfra, + } ) } }} diff --git a/src/components/gizmo/CubeGizmo.tsx b/src/components/gizmo/CubeGizmo.tsx index 62e9152572f..ab503ff91e9 100644 --- a/src/components/gizmo/CubeGizmo.tsx +++ b/src/components/gizmo/CubeGizmo.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef, useState } from 'react' import GizmoRenderer from '@src/components/gizmo/GizmoRenderer' -import { useSettings } from '@src/lib/singletons' +import { sceneInfra, useSettings } from '@src/lib/singletons' import { useModelingContext } from '@src/hooks/useModelingContext' import { useResolvedTheme } from '@src/hooks/useResolvedTheme' @@ -29,7 +29,8 @@ export default function CubeGizmo() { renderer.current = new GizmoRenderer( canvasRef.current, initialIsPerspectiveRef.current, - initialResolvedThemeRef.current + initialResolvedThemeRef.current, + sceneInfra ) } return () => { diff --git a/src/components/gizmo/GizmoRenderer.ts b/src/components/gizmo/GizmoRenderer.ts index 03a4ac6d7a5..ce2c7a025d3 100644 --- a/src/components/gizmo/GizmoRenderer.ts +++ b/src/components/gizmo/GizmoRenderer.ts @@ -1,6 +1,6 @@ import { btnName } from '@src/lib/cameraControls' import { DprDetector } from '@src/lib/DprDetector' -import { sceneInfra } from '@src/lib/singletons' +import type { SceneInfra } from '@src/clientSideScene/sceneInfra' import { reportRejection } from '@src/lib/trap' import type { Object3D, Mesh, ColorRepresentation, Texture } from 'three' import { @@ -38,6 +38,7 @@ export default class GizmoRenderer { private readonly renderer: WebGLRenderer private readonly scene: Scene private readonly dprDetector: DprDetector + private readonly sceneInfra: SceneInfra private camera: PerspectiveCamera | OrthographicCamera private clickableObjects: StandardMesh[] = [] private theme: 'light' | 'dark' @@ -73,13 +74,15 @@ export default class GizmoRenderer { constructor( canvas: HTMLCanvasElement, isPerspective: boolean, - theme: 'light' | 'dark' + theme: 'light' | 'dark', + sceneInfra: SceneInfra ) { this.canvas = canvas this.renderer = new WebGLRenderer({ canvas, antialias: true, alpha: true }) this.renderer.setSize(82, 82) // CANVAS_SIZE + border this.renderer.setPixelRatio(window.devicePixelRatio) this.dprDetector = new DprDetector(this.onDprChange) + this.sceneInfra = sceneInfra this.scene = new Scene() const ambient = new AmbientLight(0xffffff, 1.8) @@ -306,7 +309,7 @@ export default class GizmoRenderer { this.canvas.addEventListener('mousedown', this.onMouseDown) this.canvas.addEventListener('contextmenu', this.onContextMenu) this.canvas.addEventListener('click', this.onClick) - sceneInfra.camControls.cameraChange.add(this.onCameraChange) + this.sceneInfra.camControls.cameraChange.add(this.onCameraChange) } public dispose() { @@ -315,7 +318,7 @@ export default class GizmoRenderer { this.canvas.removeEventListener('mousedown', this.onMouseDown) this.canvas.removeEventListener('contextmenu', this.onContextMenu) this.canvas.removeEventListener('click', this.onClick) - sceneInfra.camControls.cameraChange.remove(this.onCameraChange) + this.sceneInfra.camControls.cameraChange.remove(this.onCameraChange) window.removeEventListener('mousemove', this.onWindowMouseMove) window.removeEventListener('mouseup', this.onMouseUp) @@ -329,7 +332,7 @@ export default class GizmoRenderer { } private onCameraChange = () => { - const currentQuaternion = sceneInfra.camControls.camera.quaternion + const currentQuaternion = this.sceneInfra.camControls.camera.quaternion this.camera.position.set(0, 0, 2.2).applyQuaternion(currentQuaternion) this.camera.quaternion.copy(currentQuaternion) @@ -359,7 +362,7 @@ export default class GizmoRenderer { private onWindowMouseMove = (event: MouseEvent) => { // Drag to rotate main camera if (this.isDragging) { - sceneInfra.camControls.wasDragging = true + this.sceneInfra.camControls.wasDragging = true const last = this.dragLast const now = new Vector2(event.clientX, event.clientY) this.dragLast = now @@ -372,10 +375,10 @@ export default class GizmoRenderer { this.updateHoveringMesh(null) } - sceneInfra.camControls.rotateCamera(dx, dy) - sceneInfra.camControls.safeLookAtTarget() + this.sceneInfra.camControls.rotateCamera(dx, dy) + this.sceneInfra.camControls.safeLookAtTarget() - sceneInfra.camControls.onCameraChange(true) + this.sceneInfra.camControls.onCameraChange(true) } } } @@ -391,10 +394,10 @@ export default class GizmoRenderer { } } - private onMouseUp = (e: MouseEvent) => { + private onMouseUp = (_e: MouseEvent) => { this.isDragging = false this.dragLast = null - sceneInfra.camControls.wasDragging = false + this.sceneInfra.camControls.wasDragging = false window.removeEventListener('mousemove', this.onWindowMouseMove) window.removeEventListener('mouseup', this.onMouseUp) @@ -428,7 +431,9 @@ export default class GizmoRenderer { const pickedName = obj?.name || this.hoveringMesh.name const targetQuat = orientationQuaternionForName(pickedName) if (targetQuat) { - animateCameraToQuaternion(targetQuat).catch(reportRejection) + animateCameraToQuaternion(targetQuat, this.sceneInfra).catch( + reportRejection + ) } } @@ -596,7 +601,10 @@ function orientationQuaternionForName(name: string): Quaternion | null { return q.setFromRotationMatrix(m) } -async function animateCameraToQuaternion(targetQuat: Quaternion) { +async function animateCameraToQuaternion( + targetQuat: Quaternion, + sceneInfra: SceneInfra +) { const camControls = sceneInfra.camControls camControls.syncDirection = 'clientToEngine' camControls.enableRotate = false diff --git a/src/components/layout/areas/CodeEditor.tsx b/src/components/layout/areas/CodeEditor.tsx index eb0144301e7..1662321d99c 100644 --- a/src/components/layout/areas/CodeEditor.tsx +++ b/src/components/layout/areas/CodeEditor.tsx @@ -11,7 +11,6 @@ import { } from 'react' import { isArray } from '@src/lib/utils' -import { editorTheme } from '@src/lib/codeEditor' //reference: https://github.com/sachinraja/rodemirror/blob/main/src/use-first-render.ts const useFirstRender = () => { @@ -34,7 +33,6 @@ interface CodeEditorProps { onCreateEditor?: (view: EditorView | null) => void initialDocValue?: EditorStateConfig['doc'] extensions?: Extension - theme: 'light' | 'dark' autoFocus?: boolean selection?: EditorStateConfig['selection'] } @@ -48,7 +46,6 @@ const CodeEditor = forwardRef((props, ref) => { onCreateEditor, extensions = [], initialDocValue, - theme, autoFocus = false, selection, } = props @@ -59,7 +56,6 @@ const CodeEditor = forwardRef((props, ref) => { onCreateEditor, extensions, initialDocValue, - theme, autoFocus, selection, }) @@ -91,7 +87,6 @@ export function useCodeMirror(props: UseCodeMirror) { onCreateEditor, extensions = [], initialDocValue, - theme, autoFocus = false, selection, } = props @@ -104,14 +99,8 @@ export function useCodeMirror(props: UseCodeMirror) { const targetExtensions = useMemo(() => { let exts = isExtensionArray(extensions) ? extensions : [] - if (theme === 'dark') { - exts = [...exts, editorTheme.dark] - } else if (theme === 'light') { - exts = [...exts, editorTheme.light] - } - return exts - }, [extensions, theme]) + }, [extensions]) useEffect(() => { if (container && !state) { diff --git a/src/components/layout/areas/FeatureTreePane.tsx b/src/components/layout/areas/FeatureTreePane.tsx index b929bb8e98a..4bb62c746f0 100644 --- a/src/components/layout/areas/FeatureTreePane.tsx +++ b/src/components/layout/areas/FeatureTreePane.tsx @@ -38,6 +38,7 @@ import { getLayout, kclManager, rustContext, + sceneEntitiesManager, sceneInfra, setLayout, useLayout, @@ -64,6 +65,15 @@ import { FeatureTreeMenu } from '@src/components/layout/areas/FeatureTreeMenu' import Tooltip from '@src/components/Tooltip' import { Disclosure } from '@headlessui/react' +// Defined outside of React to prevent rerenders +// TODO: get all system dependencies into React via global context +const systemDeps = { + kclManager, + sceneInfra, + sceneEntitiesManager, + rustContext, +} + export function FeatureTreePane(props: AreaTypeComponentProps) { return ( { input: { rustContext, kclManager, + sceneEntitiesManager, }, // devTools: true, } @@ -548,7 +559,7 @@ const OperationItem = (props: OperationProps) => { props.item, kclManager.artifactGraph ) - const result = await selectOffsetSketchPlane(artifact) + const result = await selectOffsetSketchPlane(artifact, systemDeps) if (err(result)) { console.error(result) } @@ -669,7 +680,7 @@ const OperationItem = (props: OperationProps) => { data: { forceNewSketch: true }, }) - void selectOffsetSketchPlane(artifact) + void selectOffsetSketchPlane(artifact, systemDeps) } } } @@ -888,9 +899,9 @@ const DefaultPlanes = () => { (planeId: string) => { if (sketchNoFace) { void selectSketchPlane( - kclManager, planeId, - modelingState.context.store.useNewSketchMode?.current + modelingState.context.store.useNewSketchMode?.current, + systemDeps ) } else { const foundDefaultPlane = @@ -924,9 +935,9 @@ const DefaultPlanes = () => { }) void selectSketchPlane( - kclManager, planeId, - modelingState.context.store.useNewSketchMode?.current + modelingState.context.store.useNewSketchMode?.current, + systemDeps ) }, [modelingState.context.store.useNewSketchMode] diff --git a/src/components/layout/areas/KclEditorPane.tsx b/src/components/layout/areas/KclEditorPane.tsx index e12d2ad316c..2efbc45bd00 100644 --- a/src/components/layout/areas/KclEditorPane.tsx +++ b/src/components/layout/areas/KclEditorPane.tsx @@ -3,7 +3,11 @@ import type { PropsWithChildren } from 'react' import { ActionIcon } from '@src/components/ActionIcon' import { useConvertToVariable } from '@src/hooks/useToolbarGuards' import { openExternalBrowserIfDesktop } from '@src/lib/openWindow' -import { commandBarActor, settingsActor } from '@src/lib/singletons' +import { + commandBarActor, + getSettings, + settingsActor, +} from '@src/lib/singletons' import { withSiteBaseURL } from '@src/lib/withBaseURL' import toast from 'react-hot-toast' import styles from './KclEditorMenu.module.css' @@ -51,9 +55,10 @@ import { lineHighlightField } from '@src/editor/highlightextension' import { modelingMachineEvent } from '@src/lang/KclManager' import { kclManager } from '@src/lib/singletons' import { useSettings } from '@src/lib/singletons' -import { Themes, getSystemTheme } from '@src/lib/theme' import { reportRejection, trap } from '@src/lib/trap' import { onMouseDragMakeANewNumber, onMouseDragRegex } from '@src/lib/utils' +import { artifactAnnotationsExtension } from '@src/editor/plugins/artifacts' +import { getArtifactAnnotationsAtCursor } from '@src/lib/getArtifactAnnotationsAtCursor' import { editorIsMountedSelector, kclEditorActor, @@ -61,8 +66,9 @@ import { } from '@src/machines/kclEditorMachine' import type { AreaTypeComponentProps } from '@src/lib/layout' import { LayoutPanel, LayoutPanelHeader } from '@src/components/layout/Panel' -import { kclSyntaxHighlightingExtension } from '@src/lib/codeEditor' +import { editorTheme, themeCompartment } from '@src/lib/codeEditor' import { CustomIcon } from '@src/components/CustomIcon' +import { getResolvedTheme } from '@src/lib/theme' export const editorShortcutMeta = { formatCode: { @@ -97,10 +103,6 @@ export const KclEditorPaneContents = () => { const context = useSettings() const lastSelectionEvent = useSelector(kclEditorActor, selectionEventSelector) const editorIsMounted = useSelector(kclEditorActor, editorIsMountedSelector) - const theme = - context.app.theme.current === Themes.System - ? getSystemTheme() - : context.app.theme.current const { copilotLSP, kclLSP } = useLspContext() // When this component unmounts, we need to tell the machine that the editor @@ -147,10 +149,14 @@ export const KclEditorPaneContents = () => { const editorExtensions = useMemo(() => { const extensions = [ + themeCompartment.of( + editorTheme[getResolvedTheme(getSettings().app.theme.current)] + ), drawSelection({ cursorBlinkRate: cursorBlinking.current ? 1200 : 0, }), lineHighlightField, + artifactAnnotationsExtension(), historyCompartment.of(initialHistory), closeBrackets(), codeFolding(), @@ -188,7 +194,6 @@ export const KclEditorPaneContents = () => { closeBrackets(), highlightActiveLine(), highlightSelectionMatches(), - kclSyntaxHighlightingExtension, rectangularSelection(), dropCursor(), interact({ @@ -209,6 +214,25 @@ export const KclEditorPaneContents = () => { ) if (textWrapping.current) extensions.push(EditorView.lineWrapping) + if (context.app.showDebugPanel.current) { + extensions.push( + keymap.of([ + { + key: 'Mod-Shift-d', + preventDefault: true, + run: () => { + const view = kclManager.getEditorView() + if (!view) return false + const data = getArtifactAnnotationsAtCursor(view.state) + // eslint-disable-next-line no-console + console.log('Artifact annotations at cursor:', data) + return true + }, + }, + ]) + ) + } + return extensions // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: blanket-ignored fix me! }, [kclLSP, copilotLSP, textWrapping.current, cursorBlinking.current]) @@ -226,7 +250,6 @@ export const KclEditorPaneContents = () => { { kclManager.setEditorView(_editorView) diff --git a/src/components/layout/areas/MemoryPane.spec.tsx b/src/components/layout/areas/MemoryPane.spec.tsx index 20b44ba44ba..5f796b46a1e 100644 --- a/src/components/layout/areas/MemoryPane.spec.tsx +++ b/src/components/layout/areas/MemoryPane.spec.tsx @@ -5,7 +5,7 @@ import { buildTheWorldAndConnectToEngine } from '@src/unitTestUtils' import type { ModuleType } from '@src/lib/wasm_lib_wrapper' import type { ConnectionManager } from '@src/network/connectionManager' import type RustContext from '@src/lib/rustContext' -import { beforeAll, afterAll, expect, describe, it } from 'vitest' +import { afterAll, expect, beforeEach, describe, it } from 'vitest' let instanceInThisFile: ModuleType = null! let engineCommandManagerInThisFile: ConnectionManager = null! @@ -17,7 +17,11 @@ let rustContextInThisFile: RustContext = null! * * Reuse the world for this file. This is not the same as global singleton imports! */ -beforeAll(async () => { +beforeEach(async () => { + if (instanceInThisFile) { + return + } + const { instance, engineCommandManager, rustContext } = await buildTheWorldAndConnectToEngine() instanceInThisFile = instance diff --git a/src/components/layout/areas/MlEphantConversationPane2.tsx b/src/components/layout/areas/MlEphantConversationPane2.tsx index 1a0aa364394..49f5da8d0c1 100644 --- a/src/components/layout/areas/MlEphantConversationPane2.tsx +++ b/src/components/layout/areas/MlEphantConversationPane2.tsx @@ -127,10 +127,27 @@ export const MlEphantConversationPane2 = (props: { const needsReconnect = abruptlyClosed + const getConversationId = () => { + const mlEphantConversations = + props.systemIOActor.getSnapshot().context.mlEphantConversations + + // Not ready yet. + if (mlEphantConversations === undefined) { + return undefined + } + if (props.settings.meta.id.current === uuidNIL) { + return undefined + } + + return mlEphantConversations.get(props.settings.meta.id.current) + } + const onReconnect = () => { + const conversationId = getConversationId() props.mlEphantManagerActor.send({ type: MlEphantManagerTransitions2.CacheSetupAndConnect, refParentSend: props.mlEphantManagerActor.send, + conversationId: conversationId !== uuidNIL ? conversationId : undefined, }) } @@ -153,21 +170,7 @@ export const MlEphantConversationPane2 = (props: { } const tryToGetExchanges = () => { - const mlEphantConversations = - props.systemIOActor.getSnapshot().context.mlEphantConversations - - // Not ready yet. - if (mlEphantConversations === undefined) { - return - } - if (props.settings.meta.id.current === uuidNIL) { - return - } - - const conversationId = mlEphantConversations.get( - props.settings.meta.id.current - ) - + const conversationId = getConversationId() if (conversationId === uuidNIL) { return } diff --git a/src/editor/plugins/artifacts/index.ts b/src/editor/plugins/artifacts/index.ts new file mode 100644 index 00000000000..25a2cdb1c60 --- /dev/null +++ b/src/editor/plugins/artifacts/index.ts @@ -0,0 +1,100 @@ +import type { Extension, Range } from '@codemirror/state' +import { StateEffect, StateField, Annotation } from '@codemirror/state' +import { Decoration, EditorView } from '@codemirror/view' + +import type { Artifact, CodeRef } from '@src/lang/std/artifactGraph' +import type { ArtifactGraph } from '@src/lang/wasm' +import { getCodeRefsByArtifactId } from '@src/lang/std/artifactGraph' + +const artifactAnnotationsAnnotation = Annotation.define() +/** Transaction annotation to identify artifact annotation updates */ +export const artifactAnnotationsEvent = artifactAnnotationsAnnotation.of(true) + +/** Effect used to replace the current artifact graph in state */ +export const setArtifactGraphEffect = StateEffect.define() + +/** Public shape stored on each decoration so we can inspect it later */ +export interface ArtifactAnnotationData { + id: string + type: Artifact['type'] + codeRef: CodeRef +} + +/** StateField to hold the current artifact graph reference on the EditorState */ +export const artifactGraphField = StateField.define({ + create() { + return new Map() + }, + update(value, tr) { + for (const e of tr.effects) { + if (e.is(setArtifactGraphEffect)) { + return e.value ?? new Map() + } + } + return value + }, +}) + +/** Decorations field that stores ranges annotated with artifact metadata */ +export const artifactDecorationsField = StateField.define< + ReturnType +>({ + create() { + return Decoration.none + }, + update(decorations, tr) { + // Recompute all decorations when the artifact graph effect is applied + for (const e of tr.effects) { + if (e.is(setArtifactGraphEffect)) { + const graph = e.value ?? new Map() + return buildArtifactDecorations(graph, tr.state) + } + } + // Map existing decorations through document changes + if (tr.docChanged) { + return decorations.map(tr.changes) + } + return decorations + }, + provide: (f) => EditorView.decorations.from(f), +}) + +/** + * Given an ArtifactGraph, apply decorations to the corresponding code ranges with + * each artifact's metadata. + */ +function buildArtifactDecorations( + graph: ArtifactGraph, + state: EditorView['state'] +) { + const widgets: Range[] = [] + const docLen = state.doc.length + + for (const [id, artifact] of graph.entries()) { + const refs = getCodeRefsByArtifactId(id, graph) + if (!refs) continue + for (const codeRef of refs) { + const from = Math.max(0, Math.min(codeRef.range[0], docLen)) + const to = Math.max(0, Math.min(codeRef.range[1], docLen)) + if (to <= from) continue + const data: ArtifactAnnotationData = { id, type: artifact.type, codeRef } + widgets.push( + Decoration.mark({ + class: 'cm-artifact-range', + attributes: { + 'data-artifact-id': id, + 'data-artifact-type': artifact.type, + 'data-artifact-json': JSON.stringify(data), + }, + inclusive: false, + }).range(from, to) + ) + } + } + + return Decoration.set(widgets, true) +} + +export function artifactAnnotationsExtension(): Extension { + return [artifactGraphField, artifactDecorationsField] +} diff --git a/src/editor/plugins/lsp/kcl/index.ts b/src/editor/plugins/lsp/kcl/index.ts index 730f46eaaee..f46fe81b790 100644 --- a/src/editor/plugins/lsp/kcl/index.ts +++ b/src/editor/plugins/lsp/kcl/index.ts @@ -31,6 +31,7 @@ import type { SceneGraphDelta, SourceDelta, } from '@rust/kcl-lib/bindings/FrontendApi' +import type { SceneEntities } from '@src/clientSideScene/sceneEntities' const changesDelay = 600 @@ -38,15 +39,20 @@ const changesDelay = 600 export class KclPlugin implements PluginValue { private viewUpdate: ViewUpdate | null = null private client: LanguageServerClient - private kclManager: KclManager + private readonly kclManager: KclManager + private readonly sceneEntitiesManager: SceneEntities constructor( client: LanguageServerClient, view: EditorView, - kclManager: KclManager + systemDeps: { + kclManager: KclManager + sceneEntitiesManager: SceneEntities + } ) { this.client = client - this.kclManager = kclManager + this.kclManager = systemDeps.kclManager + this.sceneEntitiesManager = systemDeps.sceneEntitiesManager // Gotcha: Code can be written into the CodeMirror editor but not propagated to kclManager.code // because the update function has not run. We need to initialize the kclManager.code when lsp initializes @@ -56,7 +62,7 @@ export class KclPlugin implements PluginValue { return plugin.client.name === 'kcl' }) if (kclLspPlugin) { - kclManager.code = view.state.doc.toString() + systemDeps.kclManager.code = view.state.doc.toString() } } @@ -70,7 +76,11 @@ export class KclPlugin implements PluginValue { return } - this.kclManager.handleOnViewUpdate(this.viewUpdate, processCodeMirrorRanges) + this.kclManager.handleOnViewUpdate( + this.viewUpdate, + processCodeMirrorRanges, + this.sceneEntitiesManager + ) }, 50) update(viewUpdate: ViewUpdate) { @@ -223,12 +233,15 @@ export class KclPlugin implements PluginValue { export function kclPlugin( options: LanguageServerOptions, - kclManager: KclManager + systemDeps: { + kclManager: KclManager + sceneEntitiesManager: SceneEntities + } ): Extension { return [ lspPlugin(options), ViewPlugin.define( - (view) => new KclPlugin(options.client, view, kclManager) + (view) => new KclPlugin(options.client, view, systemDeps) ), ] } diff --git a/src/editor/plugins/lsp/kcl/language.ts b/src/editor/plugins/lsp/kcl/language.ts index 29571318c6b..1cd8555befb 100644 --- a/src/editor/plugins/lsp/kcl/language.ts +++ b/src/editor/plugins/lsp/kcl/language.ts @@ -10,6 +10,7 @@ import type * as LSP from 'vscode-languageserver-protocol' import { kclPlugin } from '@src/editor/plugins/lsp/kcl' import { colorPicker } from '@src/editor/plugins/lsp/kcl/colors' import type { KclManager } from '@src/lang/KclManager' +import type { SceneEntities } from '@src/clientSideScene/sceneEntities' export interface LanguageOptions { workspaceFolders: LSP.WorkspaceFolder[] @@ -21,7 +22,13 @@ export interface LanguageOptions { ) => void } -export function kcl(options: LanguageOptions, kclManager: KclManager) { +export function kcl( + options: LanguageOptions, + systemDeps: { + kclManager: KclManager + sceneEntitiesManager: SceneEntities + } +) { return new LanguageSupport(KclLanguage, [ colorPicker, kclPlugin( @@ -32,7 +39,7 @@ export function kcl(options: LanguageOptions, kclManager: KclManager) { client: options.client, processLspNotification: options.processLspNotification, }, - kclManager + systemDeps ), ]) } diff --git a/src/hooks/network/useOnFileRoute.test.tsx b/src/hooks/network/useOnFileRoute.test.tsx index a2f56fee4b5..5deeb51b5a9 100644 --- a/src/hooks/network/useOnFileRoute.test.tsx +++ b/src/hooks/network/useOnFileRoute.test.tsx @@ -9,6 +9,7 @@ import { resetCameraPosition } from '@src/lib/resetCameraPosition' import { Connection } from '@src/network/connection' import { expect, vi, describe, test } from 'vitest' import type { ModuleType } from '@src/lib/wasm_lib_wrapper' +import { buildTheWorldAndNoEngineConnection } from '@src/unitTestUtils' const tick = () => { return new Promise((resolve, reject) => { @@ -18,27 +19,24 @@ const tick = () => { describe('useOnFileRoute', () => { describe('after mount', () => { - test('should call unmount', () => { + test('should call unmount', async () => { const file: FileEntry = { path: '/application/project-001/main.kcl', name: 'main.kcl', children: null, } - const engineCommandManager = new ConnectionManager() - const initWasmMock = Promise.resolve({} as ModuleType) - const rustContext = new RustContext(engineCommandManager, initWasmMock) - const sceneInfra = new SceneInfra(engineCommandManager) - const kclManager = new KclManager(engineCommandManager, initWasmMock, { - rustContext, - sceneInfra, - }) + const { engineCommandManager, sceneInfra, kclManager } = + await buildTheWorldAndNoEngineConnection(true) const { unmount } = renderHook(() => { useOnFileRoute({ file, isStreamAcceptingInput: false, - engineCommandManager, - kclManager, resetCameraPosition, + systemDeps: { + engineCommandManager, + kclManager, + sceneInfra, + }, }) }) unmount() @@ -72,9 +70,12 @@ describe('useOnFileRoute', () => { useOnFileRoute({ file, isStreamAcceptingInput: true, - engineCommandManager, - kclManager, resetCameraPosition: callback, + systemDeps: { + engineCommandManager, + kclManager, + sceneInfra, + }, }) }) unmount() @@ -121,9 +122,12 @@ describe('useOnFileRoute', () => { useOnFileRoute({ file, isStreamAcceptingInput: true, - engineCommandManager, - kclManager, resetCameraPosition: callback, + systemDeps: { + engineCommandManager, + kclManager, + sceneInfra, + }, }) }, { initialProps: { file } } @@ -175,9 +179,12 @@ describe('useOnFileRoute', () => { useOnFileRoute({ file, isStreamAcceptingInput: true, - engineCommandManager, - kclManager, resetCameraPosition: callback, + systemDeps: { + engineCommandManager, + kclManager, + sceneInfra, + }, }) }, { initialProps: { file } } @@ -231,9 +238,12 @@ describe('useOnFileRoute', () => { useOnFileRoute({ file, isStreamAcceptingInput: false, - engineCommandManager, - kclManager, resetCameraPosition: callback, + systemDeps: { + engineCommandManager, + kclManager, + sceneInfra, + }, }) }, { initialProps: { file } } diff --git a/src/hooks/network/useOnFileRoute.tsx b/src/hooks/network/useOnFileRoute.tsx index a200eb693b8..2082470f61f 100644 --- a/src/hooks/network/useOnFileRoute.tsx +++ b/src/hooks/network/useOnFileRoute.tsx @@ -2,14 +2,18 @@ import { useEffect, useRef } from 'react' import type { FileEntry } from '@src/lib/project' import type { ConnectionManager } from '@src/network/connectionManager' import type { KclManager } from '@src/lang/KclManager' +import type { SceneInfra } from '@src/clientSideScene/sceneInfra' import type { resetCameraPosition } from '@src/lib/resetCameraPosition' export interface IUseOnFileRoute { file: FileEntry | undefined isStreamAcceptingInput: boolean - engineCommandManager: ConnectionManager - kclManager: KclManager resetCameraPosition: typeof resetCameraPosition + systemDeps: { + engineCommandManager: ConnectionManager + kclManager: KclManager + sceneInfra: SceneInfra + } } /** @@ -21,9 +25,8 @@ export interface IUseOnFileRoute { export const useOnFileRoute = ({ file, isStreamAcceptingInput, - engineCommandManager, - kclManager, resetCameraPosition, + systemDeps: { engineCommandManager, kclManager, sceneInfra }, }: IUseOnFileRoute) => { const seenFilePath = useRef('') useEffect(() => { @@ -51,7 +54,7 @@ export const useOnFileRoute = ({ try { console.log('file changed, executing code') await kclManager.executeCode() - await resetCameraPosition() + await resetCameraPosition({ sceneInfra }) } catch (e) { console.warn(e) } @@ -68,6 +71,7 @@ export const useOnFileRoute = ({ isStreamAcceptingInput, engineCommandManager, kclManager, + sceneInfra, resetCameraPosition, ]) } diff --git a/src/hooks/network/useTryConnect.tsx b/src/hooks/network/useTryConnect.tsx index cd03d19cdd1..212de9315d5 100644 --- a/src/hooks/network/useTryConnect.tsx +++ b/src/hooks/network/useTryConnect.tsx @@ -7,13 +7,13 @@ import { engineCommandManager, kclManager, rustContext, - sceneInfra, } from '@src/lib/singletons' import { reportRejection } from '@src/lib/trap' import { getDimensions } from '@src/network/utils' import { useRef } from 'react' import { NUMBER_OF_ENGINE_RETRIES } from '@src/lib/constants' import toast from 'react-hot-toast' +import type { SceneInfra } from '@src/clientSideScene/sceneInfra' /** * Helper function, do not call this directly. Use tryConnecting instead. @@ -49,7 +49,6 @@ const attemptToConnectToEngine = async ({ if (!authToken) { return reject('authToken is missing on connection initialization') } - if (engineCommandManager.started) { return reject('engine is already started. You cannot start again') } @@ -110,7 +109,9 @@ const attemptToConnectToEngine = async ({ return connection } -const setupSceneAndExecuteCodeAfterOpenedEngineConnection = async () => { +const setupSceneAndExecuteCodeAfterOpenedEngineConnection = async ({ + sceneInfra, +}: { sceneInfra: SceneInfra }) => { const settings = await jsAppSettings() EngineDebugger.addLog({ label: 'onEngineConnectionReadyForRequests', @@ -138,7 +139,7 @@ const setupSceneAndExecuteCodeAfterOpenedEngineConnection = async () => { if (sceneInfra.camControls.oldCameraState) { await sceneInfra.camControls.restoreRemoteCameraStateAndTriggerSync() } else { - await resetCameraPosition() + await resetCameraPosition({ sceneInfra }) } // Since you reconnected you are not idle, clear the old camera state @@ -169,6 +170,7 @@ async function tryConnecting({ timeToConnect, settings, setShowManualConnect, + sceneInfra, }: { isConnecting: React.RefObject numberOfConnectionAttempts: React.RefObject @@ -180,6 +182,7 @@ async function tryConnecting({ timeToConnect: number settings: SettingsViaQueryString setShowManualConnect: React.Dispatch> + sceneInfra: SceneInfra }) { const connection = new Promise((resolve, reject) => { void (async () => { @@ -208,7 +211,9 @@ async function tryConnecting({ }) // Do not count the 30 second timer to connect within the kcl execution and scene setup - await setupSceneAndExecuteCodeAfterOpenedEngineConnection() + await setupSceneAndExecuteCodeAfterOpenedEngineConnection({ + sceneInfra, + }) isConnecting.current = false setAppState({ isStreamAcceptingInput: true }) numberOfConnectionAttempts.current = 0 diff --git a/src/hooks/useEngineConnectionSubscriptions.ts b/src/hooks/useEngineConnectionSubscriptions.ts index dfc6bd14578..e36504e9b27 100644 --- a/src/hooks/useEngineConnectionSubscriptions.ts +++ b/src/hooks/useEngineConnectionSubscriptions.ts @@ -9,16 +9,21 @@ import { selectionBodyFace, selectOffsetSketchPlane, } from '@src/lib/selections' -import { - engineCommandManager, - sceneInfra, - rustContext, -} from '@src/lib/singletons' import { err, reportRejection } from '@src/lib/trap' import type { KclManager } from '@src/lang/KclManager' +import type { SceneInfra } from '@src/clientSideScene/sceneInfra' +import type RustContext from '@src/lib/rustContext' +import type { SceneEntities } from '@src/clientSideScene/sceneEntities' -export function useEngineConnectionSubscriptions(kclManager: KclManager) { +export function useEngineConnectionSubscriptions() { const { send, context, state } = useModelingContext() + const { + engineCommandManager, + kclManager, + rustContext, + sceneEntitiesManager, + sceneInfra, + } = context const stateRef = useRef(state) stateRef.current = state @@ -52,10 +57,10 @@ export function useEngineConnectionSubscriptions(kclManager: KclManager) { callback: (engineEvent) => { ;(async () => { if (stateRef.current.matches('Sketch no face')) return - const event = await getEventForSelectWithPoint( - engineEvent, - kclManager.artifactGraph - ) + const event = await getEventForSelectWithPoint(engineEvent, { + rustContext, + artifactGraph: kclManager.artifactGraph, + }) event && send(event) })().catch(reportRejection) }, @@ -64,7 +69,13 @@ export function useEngineConnectionSubscriptions(kclManager: KclManager) { unSubHover() unSubClick() } - }, [context?.sketchEnginePathId, kclManager, send]) + }, [ + context?.sketchEnginePathId, + kclManager, + send, + engineCommandManager, + rustContext, + ]) useEffect(() => { if (!engineCommandManager) return @@ -74,15 +85,28 @@ export function useEngineConnectionSubscriptions(kclManager: KclManager) { callback: state.matches('Sketch no face') ? ({ data }) => { void selectSketchPlane( - kclManager, data.entity_id, - context.store.useNewSketchMode?.current + context.store.useNewSketchMode?.current, + { + kclManager, + rustContext, + sceneEntitiesManager, + sceneInfra, + } ) } : () => {}, }) return unSub - }, [context.store.useNewSketchMode, state, kclManager]) + }, [ + context.store.useNewSketchMode, + state, + kclManager, + sceneInfra, + rustContext, + engineCommandManager, + sceneEntitiesManager, + ]) // Re-apply plane visibility when planes are (re)created on the Rust side useEffect(() => { @@ -93,44 +117,57 @@ export function useEngineConnectionSubscriptions(kclManager: KclManager) { void kclManager.setPlaneVisibilityByKey('yz', vis.yz) }) return unsubscribe - }, [kclManager]) + }, [kclManager, rustContext]) } export async function selectSketchPlane( - kclManager: KclManager, planeOrFaceId: string | undefined, - useNewSketchMode: boolean | undefined + useNewSketchMode: boolean | undefined, + systemDeps?: { + kclManager: KclManager + sceneInfra: SceneInfra + rustContext: RustContext + sceneEntitiesManager: SceneEntities + } ) { try { + if (!systemDeps) return if (!planeOrFaceId) return if (useNewSketchMode) { - sceneInfra.modelingSend({ + systemDeps.sceneInfra.modelingSend({ type: 'Select sketch solve plane', data: planeOrFaceId, }) return } - const defaultSketchPlaneSelected = selectDefaultSketchPlane(planeOrFaceId) + const defaultSketchPlaneSelected = selectDefaultSketchPlane( + planeOrFaceId, + systemDeps + ) if (!err(defaultSketchPlaneSelected) && defaultSketchPlaneSelected) { return } - const artifact = kclManager.artifactGraph.get(planeOrFaceId) - const offsetPlaneSelected = await selectOffsetSketchPlane(artifact) + const artifact = systemDeps.kclManager.artifactGraph.get(planeOrFaceId) + const offsetPlaneSelected = await selectOffsetSketchPlane( + artifact, + systemDeps + ) if (!err(offsetPlaneSelected) && offsetPlaneSelected) { return } const sweepFaceSelected = await selectionBodyFace( planeOrFaceId, - kclManager.artifactGraph, - kclManager.ast, - kclManager.execState + systemDeps.kclManager.artifactGraph, + systemDeps.kclManager.ast, + systemDeps.kclManager.execState, + systemDeps ) if (sweepFaceSelected) { - sceneInfra.modelingSend({ + systemDeps.sceneInfra.modelingSend({ type: 'Select sketch plane', data: sweepFaceSelected, }) diff --git a/src/lang/KclManager.ts b/src/lang/KclManager.ts index 66328c5cfb1..8fe595f756d 100644 --- a/src/lang/KclManager.ts +++ b/src/lang/KclManager.ts @@ -20,6 +20,10 @@ import type { VariableMap, } from '@src/lang/wasm' import { emptyExecState, getKclVersion, parse, recast } from '@src/lang/wasm' +import { + setArtifactGraphEffect, + artifactAnnotationsEvent, +} from '@src/editor/plugins/artifacts' import type { ArtifactIndex } from '@src/lib/artifactIndex' import { buildArtifactIndex } from '@src/lib/artifactIndex' import { @@ -90,6 +94,13 @@ import { bracket } from '@src/lib/exampleKcl' import { isDesktop } from '@src/lib/isDesktop' import toast from 'react-hot-toast' import { signal } from '@preact/signals-core' +import { + editorTheme, + themeCompartment, + appSettingsThemeEffect, + settingsUpdateAnnotation, +} from '@src/lib/codeEditor' +import type { SceneEntities } from '@src/clientSideScene/sceneEntities' interface ExecuteArgs { ast?: Node @@ -191,6 +202,7 @@ export class KclManager extends EventTarget { private _switchedFiles = false private _fileSettings: KclSettingsAnnotation = {} private _kclVersion: string | undefined = undefined + private _sceneEntitiesManager?: SceneEntities private singletons: Singletons private executionTimeoutId: ReturnType | undefined = undefined @@ -342,11 +354,15 @@ export class KclManager extends EventTarget { return this._isExecuting } + set sceneEntitiesManager(s: SceneEntities) { + this._sceneEntitiesManager = s + } + set isExecuting(isExecuting) { this._isExecuting.value = isExecuting // If we have finished executing, but the execute is stale, we should // execute again. - if (!isExecuting && this.executeIsStale) { + if (!isExecuting && this.executeIsStale && this._sceneEntitiesManager) { const args = this.executeIsStale this.executeIsStale = null // eslint-disable-next-line @typescript-eslint/no-floating-promises @@ -477,6 +493,18 @@ export class KclManager extends EventTarget { ) { this.artifactGraph = execStateArtifactGraph this.artifactIndex = buildArtifactIndex(execStateArtifactGraph) + + // Push the artifact graph into the editor state so annotations/decorations update + const editorView = this.getEditorView() + if (editorView) { + editorView.dispatch({ + effects: [setArtifactGraphEffect.of(this.artifactGraph)], + annotations: [ + artifactAnnotationsEvent, + Transaction.addToHistory.of(false), + ], + }) + } if (this.artifactGraph.size) { // TODO: we wanna remove this logic from xstate, it is racey // This defer is bullshit but playwright wants it @@ -598,7 +626,13 @@ export class KclManager extends EventTarget { instance: this.singletons.rustContext.getRustInstance(), }) ) - await setSelectionFilterToDefault(this.engineCommandManager, this) + if (this._sceneEntitiesManager) { + await setSelectionFilterToDefault({ + engineCommandManager: this.engineCommandManager, + kclManager: this, + sceneEntitiesManager: this._sceneEntitiesManager, + }) + } } this.isExecuting = false @@ -912,29 +946,33 @@ export class KclManager extends EventTarget { /** TODO: this function is hiding unawaited asynchronous work */ setSelectionFilterToDefault( + sceneEntitiesManager: SceneEntities, selectionsToRestore?: Selections, handleSelectionBatch?: typeof handleSelectionBatchFn ) { - setSelectionFilterToDefault( - this.engineCommandManager, - this, + setSelectionFilterToDefault({ + engineCommandManager: this.engineCommandManager, + kclManager: this, + sceneEntitiesManager, selectionsToRestore, - handleSelectionBatch - ) + handleSelectionBatchFn: handleSelectionBatch, + }) } /** TODO: this function is hiding unawaited asynchronous work */ setSelectionFilter( filter: EntityType[], + sceneEntitiesManager: SceneEntities, selectionsToRestore?: Selections, handleSelectionBatch?: typeof handleSelectionBatchFn ) { - setSelectionFilter( + setSelectionFilter({ filter, - this.engineCommandManager, - this, + engineCommandManager: this.engineCommandManager, + kclManager: this, + sceneEntitiesManager, selectionsToRestore, - handleSelectionBatch - ) + handleSelectionBatchFn: handleSelectionBatch, + }) } // Determines if there is no KCL code which means it is executing a blank KCL file @@ -1100,6 +1138,20 @@ export class KclManager extends EventTarget { }) } } + setEditorTheme(theme: 'light' | 'dark') { + if (this._editorView) { + this._editorView.dispatch({ + effects: [ + appSettingsThemeEffect.of(theme), + themeCompartment.reconfigure(editorTheme[theme]), + ], + annotations: [ + settingsUpdateAnnotation.of(null), + Transaction.addToHistory.of(false), + ], + }) + } + } /** * Given an array of Diagnostics remove any duplicates by hashing a key * in the format of from + ' ' + to + ' ' + message. @@ -1276,7 +1328,8 @@ export class KclManager extends EventTarget { // doing. (jess) handleOnViewUpdate( viewUpdate: ViewUpdate, - processCodeMirrorRanges: typeof processCodeMirrorRangesFn + processCodeMirrorRanges: typeof processCodeMirrorRangesFn, + sceneEntitiesManager: SceneEntities ): void { if (!this._editorView) { this.setEditorView(viewUpdate.view) @@ -1307,6 +1360,10 @@ export class KclManager extends EventTarget { ast: this.ast, artifactGraph: this.artifactGraph, artifactIndex: this.artifactIndex, + systemDeps: { + engineCommandManager: this.engineCommandManager, + sceneEntitiesManager, + }, }) if (!eventInfo) { return diff --git a/src/lang/modifyAst/deleteSelection.ts b/src/lang/modifyAst/deleteSelection.ts index 8346d8fefc8..05ac2a593f4 100644 --- a/src/lang/modifyAst/deleteSelection.ts +++ b/src/lang/modifyAst/deleteSelection.ts @@ -3,27 +3,33 @@ import { updateModelingState } from '@src/lang/modelingWorkflows' import { deleteFromSelection } from '@src/lang/modifyAst/deleteFromSelection' import { EXECUTION_TYPE_REAL } from '@src/lib/constants' import type { Selection } from '@src/machines/modelingSharedTypes' -import { - kclManager, - rustContext, - sceneEntitiesManager, -} from '@src/lib/singletons' import { err } from '@src/lib/trap' +import type { KclManager } from '@src/lang/KclManager' +import type { SceneEntities } from '@src/clientSideScene/sceneEntities' +import type RustContext from '@src/lib/rustContext' export const deletionErrorMessage = 'Unable to delete selection. Please edit manually in code pane.' -export async function deleteSelectionPromise( +export async function deleteSelectionPromise({ + selection, + systemDeps, +}: { selection: Selection -): Promise { - let ast = kclManager.ast + systemDeps: { + kclManager: KclManager + rustContext: RustContext + sceneEntitiesManager: SceneEntities + } +}): Promise { + let ast = systemDeps.kclManager.ast const modifiedAst = await deleteFromSelection( ast, selection, - kclManager.variables, - kclManager.artifactGraph, - sceneEntitiesManager.getFaceDetails + systemDeps.kclManager.variables, + systemDeps.kclManager.artifactGraph, + systemDeps.sceneEntitiesManager.getFaceDetails ) if (err(modifiedAst)) { return new Error(deletionErrorMessage) @@ -31,7 +37,7 @@ export async function deleteSelectionPromise( const testExecute = await executeAstMock({ ast: modifiedAst, - rustContext: rustContext, + rustContext: systemDeps.rustContext, }) if (testExecute.errors.length) { return new Error(deletionErrorMessage) @@ -40,8 +46,8 @@ export async function deleteSelectionPromise( modifiedAst, EXECUTION_TYPE_REAL, { - kclManager, - rustContext, + kclManager: systemDeps.kclManager, + rustContext: systemDeps.rustContext, }, { isDeleting: true, diff --git a/src/lang/queryAstNodePathUtils.ts b/src/lang/queryAstNodePathUtils.ts index 054579d2b0e..2a7bb98aea3 100644 --- a/src/lang/queryAstNodePathUtils.ts +++ b/src/lang/queryAstNodePathUtils.ts @@ -160,6 +160,10 @@ function moreNodePathFromSourceRange( return path } if (_node.type === 'FunctionExpression' && isInRange) { + if (_node.name && _node.name.start <= start && _node.name.end >= end) { + path.push(['name', 'FunctionExpression']) + return moreNodePathFromSourceRange(_node.name, sourceRange, path) + } for (let i = 0; i < _node.params.length; i++) { const param = _node.params[i] if (param.identifier.start <= start && param.identifier.end >= end) { diff --git a/src/lang/wasm.ts b/src/lang/wasm.ts index 45eaae16f41..2f560fcb518 100644 --- a/src/lang/wasm.ts +++ b/src/lang/wasm.ts @@ -807,6 +807,9 @@ export function pathToNodeFromRustNodePath(nodePath: NodePath): PathToNode { case 'VariableDeclarationInit': pathToNode.push(['init', '']) break + case 'FunctionExpressionName': + pathToNode.push(['name', 'FunctionExpression']) + break case 'FunctionExpressionParam': pathToNode.push(['params', 'FunctionExpression']) pathToNode.push([step.index, 'index']) diff --git a/src/lang/wasmUtilsNode.ts b/src/lang/wasmUtilsNode.ts index aa75acb56ca..17ab95b573d 100644 --- a/src/lang/wasmUtilsNode.ts +++ b/src/lang/wasmUtilsNode.ts @@ -60,7 +60,7 @@ export const loadAndInitialiseWasmInstance = async (path: string) => { const instanceOfWasmLibImport = await import( `@rust/kcl-wasm-lib/pkg/kcl_wasm_lib` ) - // Tell the instance to load the was buffer + // Tell the instance to load the wasm buffer await instanceOfWasmLibImport.default({ module_or_path: wasmBuffer }) return instanceOfWasmLibImport } diff --git a/src/lib/codeEditor.ts b/src/lib/codeEditor.ts index 3fd493cb660..30f6a472920 100644 --- a/src/lib/codeEditor.ts +++ b/src/lib/codeEditor.ts @@ -1,6 +1,13 @@ import { HighlightStyle, syntaxHighlighting } from '@codemirror/language' +import { + Annotation, + Compartment, + type Extension, + StateEffect, +} from '@codemirror/state' import { tags } from '@lezer/highlight' import { EditorView } from 'codemirror' +import { Themes } from '@src/lib/theme' export const normalizeLineEndings = (str: string, normalized = '\n') => { return str.replace(/\r?\n/g, normalized) @@ -90,6 +97,7 @@ const baseKclHighlights = HighlightStyle.define([ const darkKclHighlights = HighlightStyle.define( [ + ...baseKclHighlights.specs, { tag: [tags.keyword, tags.annotation], color: colors.orange.dark, @@ -149,23 +157,21 @@ const darkTheme = EditorView.theme( } ) -/** - * CodeMirror theme extensions for KCL syntax highlighting. - * - * Not included in package because it uses CSS variables local to ZDS. - * TODO: Make application-agnostic maybe, if other clients want this theme. - */ -export const kclSyntaxHighlightingExtension = [ - // Overrides are provided by `darkKclHighlights` and must be first - syntaxHighlighting(darkKclHighlights), - syntaxHighlighting(baseKclHighlights), -] - /** * Nearly-empty themes that just mark themselves as light or dark * so our {@link syntaxHighlightingExtension} can apply its styling. */ export const editorTheme = { - light: lightTheme, - dark: darkTheme, -} + [Themes.Light]: [lightTheme, syntaxHighlighting(baseKclHighlights)], + [Themes.Dark]: [darkTheme, syntaxHighlighting(darkKclHighlights)], +} satisfies Record, Extension> +/** Compartment to allow us to reconfigure CodeMirror's theme dynamically outside of React */ +export const themeCompartment = new Compartment() + +/** Annotation to flag CodeMirror transactions as coming from an app settings update */ +export const settingsUpdateAnnotation = Annotation.define() + +/** StateEffect to dispatch to CodeMirror when the app theme setting changes */ +export const appSettingsThemeEffect = StateEffect.define<'light' | 'dark'>() +/** StateEffect to dispatch to CodeMirror when the app blinkingCursor setting changes */ +export const appSettingsBlinkingCursorEffect = StateEffect.define() diff --git a/src/lib/getArtifactAnnotationsAtCursor.ts b/src/lib/getArtifactAnnotationsAtCursor.ts new file mode 100644 index 00000000000..481b8bfd851 --- /dev/null +++ b/src/lib/getArtifactAnnotationsAtCursor.ts @@ -0,0 +1,30 @@ +import type { EditorState } from '@codemirror/state' +import { + artifactDecorationsField, + type ArtifactAnnotationData, +} from '@src/editor/plugins/artifacts' + +/** + * Returns any artifact annotation data intersecting the current primary cursor. + */ +export function getArtifactAnnotationsAtCursor( + state: EditorState +): ArtifactAnnotationData[] { + const pos = state.selection.main.head + const decos = state.field(artifactDecorationsField, false) + if (!decos) return [] + + const results: ArtifactAnnotationData[] = [] + decos.between(pos, pos, (_from, _to, value) => { + const attrs = (value.spec && value.spec.attributes) || null + const json = attrs?.['data-artifact-json'] + if (json) { + try { + results.push(JSON.parse(json) as ArtifactAnnotationData) + } catch { + // ignore malformed JSON + } + } + }) + return results +} diff --git a/src/lib/kclCommands.ts b/src/lib/kclCommands.ts index a3956cb3c5f..aeeb67229a8 100644 --- a/src/lib/kclCommands.ts +++ b/src/lib/kclCommands.ts @@ -50,6 +50,8 @@ interface KclCommandConfig { } const NO_INPUT_PROVIDED_MESSAGE = 'No input provided' +const EXECUTING_MESSAGE = + 'Cannot run command while code is executing. Please try again later.' export function kclCommands(commandProps: KclCommandConfig): Command[] { return [ @@ -178,6 +180,11 @@ export function kclCommands(commandProps: KclCommandConfig): Command[] { groupId: 'code', hide: 'web', needsReview: true, + reviewValidation: async () => { + if (commandProps.kclManager.isExecuting) { + return new Error(EXECUTING_MESSAGE) + } + }, args: { path: { inputType: 'options', diff --git a/src/lib/resetCameraPosition.ts b/src/lib/resetCameraPosition.ts index dee640d431c..07b22fab99f 100644 --- a/src/lib/resetCameraPosition.ts +++ b/src/lib/resetCameraPosition.ts @@ -1,9 +1,6 @@ +import type { SceneInfra } from '@src/clientSideScene/sceneInfra' import { isPlaywright } from '@src/lib/isPlaywright' -import { - engineCommandManager, - sceneInfra, - settingsActor, -} from '@src/lib/singletons' +import { engineCommandManager, settingsActor } from '@src/lib/singletons' import { engineStreamZoomToFit, engineViewIsometric } from '@src/lib/utils' /** @@ -14,7 +11,9 @@ import { engineStreamZoomToFit, engineViewIsometric } from '@src/lib/utils' * your localhost will do view_isometric. Turn this boolean on to have the same experience when manually * debugging e2e tests */ -export async function resetCameraPosition() { +export async function resetCameraPosition({ + sceneInfra, +}: { sceneInfra: SceneInfra }) { // We need a padding of 0.1 for zoom_to_fit for all E2E tests since they were originally // written with zoom_to_fit with padding 0.1 const padding = 0.1 diff --git a/src/lib/selectionFilterUtils.ts b/src/lib/selectionFilterUtils.ts index 1545ecbf7cb..95b4b2cc4fe 100644 --- a/src/lib/selectionFilterUtils.ts +++ b/src/lib/selectionFilterUtils.ts @@ -9,6 +9,7 @@ import type { Selections } from '@src/machines/modelingSharedTypes' import type { handleSelectionBatch } from '@src/lib/selections' import { uuidv4 } from '@src/lib/utils' import type { KclManager } from '@src/lang/KclManager' +import type { SceneEntities } from '@src/clientSideScene/sceneEntities' export const defaultSelectionFilter: EntityType[] = [ 'face', @@ -19,30 +20,46 @@ export const defaultSelectionFilter: EntityType[] = [ ] /** TODO: This function is not synchronous but is currently treated as such */ -export function setSelectionFilterToDefault( - engineCommandManager: ConnectionManager, - kclManager: KclManager, - selectionsToRestore?: Selections, +export function setSelectionFilterToDefault({ + engineCommandManager, + kclManager, + sceneEntitiesManager, + selectionsToRestore, + handleSelectionBatchFn, +}: { + engineCommandManager: ConnectionManager + kclManager: KclManager + sceneEntitiesManager: SceneEntities + selectionsToRestore?: Selections handleSelectionBatchFn?: typeof handleSelectionBatch -) { +}) { // eslint-disable-next-line @typescript-eslint/no-floating-promises - setSelectionFilter( - defaultSelectionFilter, + setSelectionFilter({ + filter: defaultSelectionFilter, engineCommandManager, kclManager, + sceneEntitiesManager, selectionsToRestore, - handleSelectionBatchFn - ) + handleSelectionBatchFn, + }) } /** TODO: This function is not synchronous but is currently treated as such */ -export function setSelectionFilter( - filter: EntityType[], - engineCommandManager: ConnectionManager, - kclManager: KclManager, - selectionsToRestore?: Selections, +export function setSelectionFilter({ + filter, + engineCommandManager, + kclManager, + sceneEntitiesManager, + selectionsToRestore, + handleSelectionBatchFn, +}: { + filter: EntityType[] + engineCommandManager: ConnectionManager + kclManager: KclManager + sceneEntitiesManager: SceneEntities + selectionsToRestore?: Selections handleSelectionBatchFn?: typeof handleSelectionBatch -) { +}) { const { engineEvents } = selectionsToRestore && handleSelectionBatchFn ? handleSelectionBatchFn({ @@ -50,6 +67,10 @@ export function setSelectionFilter( artifactGraph: kclManager.artifactGraph, code: kclManager.code, ast: kclManager.ast, + systemDeps: { + sceneEntitiesManager, + engineCommandManager, + }, }) : { engineEvents: undefined } diff --git a/src/lib/selections.ts b/src/lib/selections.ts index b5b2072a1a5..193d71e96b5 100644 --- a/src/lib/selections.ts +++ b/src/lib/selections.ts @@ -49,12 +49,10 @@ import type { import type { ArtifactEntry, ArtifactIndex } from '@src/lib/artifactIndex' import type { CommandArgument } from '@src/lib/commandTypes' import type { DefaultPlaneStr } from '@src/lib/planes' -import { - engineCommandManager, - rustContext, - sceneEntitiesManager, - sceneInfra, -} from '@src/lib/singletons' +import type RustContext from '@src/lib/rustContext' +import type { SceneEntities } from '@src/clientSideScene/sceneEntities' +import type { ConnectionManager } from '@src/network/connectionManager' +import type { SceneInfra } from '@src/clientSideScene/sceneInfra' import { err } from '@src/lib/trap' import { getModuleId, @@ -81,7 +79,13 @@ export const Y_AXIS_UUID = '680fd157-266f-4b8a-984f-cdf46b8bdf01' export async function getEventForSelectWithPoint( { data }: Extract, - artifactGraph: ArtifactGraph + { + artifactGraph, + rustContext, + }: { + artifactGraph: ArtifactGraph + rustContext: RustContext + } ): Promise { if (!data?.entity_id) { return { @@ -218,11 +222,16 @@ export function handleSelectionBatch({ artifactGraph, code, ast, + systemDeps, }: { selections: Selections artifactGraph: ArtifactGraph code: string ast: Node + systemDeps: { + sceneEntitiesManager: SceneEntities + engineCommandManager: ConnectionManager + } }): { engineEvents: WebSocketRequest[] codeMirrorSelection: EditorSelection @@ -240,8 +249,10 @@ export function handleSelectionBatch({ defaultSourceRange(), }) }) - const engineEvents: WebSocketRequest[] = - resetAndSetEngineEntitySelectionCmds(selectionToEngine) + const engineEvents: WebSocketRequest[] = resetAndSetEngineEntitySelectionCmds( + selectionToEngine, + systemDeps + ) selections.graphSelections.forEach(({ codeRef }) => { if (codeRef.range?.[1]) { const safeEnd = Math.min(codeRef.range[1], code.length) @@ -256,7 +267,7 @@ export function handleSelectionBatch({ selections.graphSelections.length - 1 ), updateSceneObjectColors: () => - updateSceneObjectColors(selections.graphSelections, ast), + updateSceneObjectColors(selections.graphSelections, ast, systemDeps), } return { @@ -266,7 +277,7 @@ export function handleSelectionBatch({ ), engineEvents, updateSceneObjectColors: () => - updateSceneObjectColors(selections.graphSelections, ast), + updateSceneObjectColors(selections.graphSelections, ast, systemDeps), } } @@ -282,6 +293,7 @@ export function processCodeMirrorRanges({ ast, artifactGraph, artifactIndex, + systemDeps, }: { codeMirrorRanges: readonly SelectionRange[] selectionRanges: Selections @@ -289,6 +301,10 @@ export function processCodeMirrorRanges({ ast: Node artifactGraph: ArtifactGraph artifactIndex: ArtifactIndex + systemDeps: { + sceneEntitiesManager: SceneEntities + engineCommandManager: ConnectionManager + } }): null | { modelingEvent: ModelingMachineEvent engineEvents: WebSocketRequest[] @@ -351,7 +367,7 @@ export function processCodeMirrorRanges({ } if (!selectionRanges) return null - updateSceneObjectColors(codeBasedSelections, ast) + updateSceneObjectColors(codeBasedSelections, ast, systemDeps) return { modelingEvent: { type: 'Set selection', @@ -364,14 +380,20 @@ export function processCodeMirrorRanges({ }, }, engineEvents: resetAndSetEngineEntitySelectionCmds( - idBasedSelections.filter(({ id }) => !!id) + idBasedSelections.filter(({ id }) => !!id), + systemDeps ), } } function updateSceneObjectColors( codeBasedSelections: Selection[], - ast: Node + ast: Node, + { + sceneEntitiesManager, + }: { + sceneEntitiesManager: SceneEntities + } ) { const updated = ast @@ -425,9 +447,14 @@ export function updateExtraSegments( } function resetAndSetEngineEntitySelectionCmds( - selections: SelectionToEngine[] + selections: SelectionToEngine[], + systemDeps: { + engineCommandManager: ConnectionManager + } ): WebSocketRequest[] { - if (engineCommandManager.connection?.pingIntervalId === undefined) { + if ( + systemDeps.engineCommandManager.connection?.pingIntervalId === undefined + ) { return [] } return [ @@ -735,14 +762,17 @@ export function codeToIdSelections( export async function sendSelectEventToEngine( e: React.MouseEvent, - videoRef: HTMLVideoElement + videoRef: HTMLVideoElement, + systemDeps: { + engineCommandManager: ConnectionManager + } ) { const { x, y } = getNormalisedCoordinates( e, videoRef, - engineCommandManager.streamDimensions + systemDeps.engineCommandManager.streamDimensions ) - let res = await engineCommandManager.sendSceneCommand({ + let res = await systemDeps.engineCommandManager.sendSceneCommand({ type: 'modeling_cmd_req', cmd: { type: 'select_with_point', @@ -854,8 +884,13 @@ export function getSemanticSelectionType(selectionType: Artifact['type'][]) { } export function getDefaultSketchPlaneData( - defaultPlaneId: string + defaultPlaneId: string, + systemDeps: { + rustContext: RustContext + sceneInfra: SceneInfra + } ): Error | false | DefaultPlane { + const { sceneInfra, rustContext } = systemDeps const defaultPlanes = rustContext.defaultPlanes if (!defaultPlanes) { return new Error('No default planes defined in rustContext') @@ -927,7 +962,11 @@ export function getDefaultSketchPlaneData( } export async function getPlaneDataFromSketchBlock( sketchBlock: Extract, - artifactGraph: ArtifactGraph + artifactGraph: ArtifactGraph, + systemDeps: { + rustContext: RustContext + sceneInfra: SceneInfra + } ): Promise { // TODO this function is stubbed out for now since sketchBlocks really only work on default planes // and I don't think we have enough info or the sketchBlock.planeId is wrong, so it just default to the @@ -944,9 +983,12 @@ export async function getPlaneDataFromSketchBlock( // If artifact doesn't exist in the graph, fallback to default XY plane // This is a temporary solution while we determine the proper approach for default planes if (!artifact) { - const defaultPlanes = rustContext.defaultPlanes + const defaultPlanes = systemDeps.rustContext.defaultPlanes if (defaultPlanes?.xy) { - const defaultResult = getDefaultSketchPlaneData(defaultPlanes.xy) + const defaultResult = getDefaultSketchPlaneData( + defaultPlanes.xy, + systemDeps + ) if (!err(defaultResult) && defaultResult) { return defaultResult } @@ -958,9 +1000,14 @@ export async function getPlaneDataFromSketchBlock( } export function selectDefaultSketchPlane( - defaultPlaneId: string + defaultPlaneId: string, + systemDeps: { + sceneInfra: SceneInfra + rustContext: RustContext + } ): Error | boolean { - const result = getDefaultSketchPlaneData(defaultPlaneId) + const { sceneInfra } = systemDeps + const result = getDefaultSketchPlaneData(defaultPlaneId, systemDeps) if (err(result) || result === false) return result sceneInfra.modelingSend({ type: 'Select sketch plane', @@ -970,8 +1017,13 @@ export function selectDefaultSketchPlane( } export async function getOffsetSketchPlaneData( - artifact: Artifact | undefined + artifact: Artifact | undefined, + systemDeps: { + sceneInfra: SceneInfra + sceneEntitiesManager: SceneEntities + } ): Promise { + const { sceneInfra } = systemDeps if (artifact?.type !== 'plane') { return new Error( `Invalid artifact type for offset sketch plane selection: ${artifact?.type}` @@ -979,7 +1031,8 @@ export async function getOffsetSketchPlaneData( } const planeId = artifact.id try { - const planeInfo = await sceneEntitiesManager.getFaceDetails(planeId) + const planeInfo = + await systemDeps.sceneEntitiesManager.getFaceDetails(planeId) // Apply camera-based orientation logic similar to default planes let zAxis: [number, number, number] = [ @@ -1040,9 +1093,14 @@ export async function getOffsetSketchPlaneData( } export async function selectOffsetSketchPlane( - artifact: Artifact | undefined + artifact: Artifact | undefined, + systemDeps: { + sceneInfra: SceneInfra + sceneEntitiesManager: SceneEntities + } ): Promise { - const result = await getOffsetSketchPlaneData(artifact) + const { sceneInfra } = systemDeps + const result = await getOffsetSketchPlaneData(artifact, systemDeps) if (err(result) || result === false) return result try { @@ -1061,15 +1119,27 @@ export async function selectionBodyFace( planeOrFaceId: ArtifactId, artifactGraph: ArtifactGraph, ast: Node, - execState: ExecState + execState: ExecState, + systemDeps: { + sceneInfra: SceneInfra + rustContext: RustContext + sceneEntitiesManager: SceneEntities + } ): Promise { - const defaultSketchPlaneSelected = selectDefaultSketchPlane(planeOrFaceId) + const { sceneInfra } = systemDeps + const defaultSketchPlaneSelected = selectDefaultSketchPlane( + planeOrFaceId, + systemDeps + ) if (!err(defaultSketchPlaneSelected) && defaultSketchPlaneSelected) { return } const artifact = artifactGraph.get(planeOrFaceId) - const offsetPlaneSelected = await selectOffsetSketchPlane(artifact) + const offsetPlaneSelected = await selectOffsetSketchPlane( + artifact, + systemDeps + ) if (!err(offsetPlaneSelected) && offsetPlaneSelected) { return } @@ -1117,7 +1187,7 @@ export async function selectionBodyFace( ? getWallCodeRef(artifact, artifactGraph) : artifact.codeRef - const faceInfo = await sceneEntitiesManager.getFaceDetails(faceId) + const faceInfo = await systemDeps.sceneEntitiesManager.getFaceDetails(faceId) if (!faceInfo?.origin || !faceInfo?.z_axis || !faceInfo?.y_axis) return const { z_axis, y_axis, origin } = faceInfo const sketchPathToNode = err(codeRef) ? [] : codeRef.pathToNode @@ -1166,24 +1236,30 @@ export async function selectionBodyFace( } export function selectAllInCurrentSketch( - artifactGraph: ArtifactGraph + artifactGraph: ArtifactGraph, + systemDeps: { + sceneEntitiesManager: SceneEntities + } ): Selections { const graphSelections: Selection[] = [] - Object.keys(sceneEntitiesManager.activeSegments).forEach((pathToNode) => { - const artifact = artifactGraph - .values() - .find( - (g) => - 'codeRef' in g && JSON.stringify(g.codeRef.pathToNode) === pathToNode - ) - if (artifact && ['path', 'segment'].includes(artifact.type)) { - const codeRefs = getCodeRefsByArtifactId(artifact.id, artifactGraph) - if (codeRefs?.length) { - graphSelections.push({ artifact, codeRef: codeRefs[0] }) + Object.keys(systemDeps.sceneEntitiesManager.activeSegments).forEach( + (pathToNode) => { + const artifact = artifactGraph + .values() + .find( + (g) => + 'codeRef' in g && + JSON.stringify(g.codeRef.pathToNode) === pathToNode + ) + if (artifact && ['path', 'segment'].includes(artifact.type)) { + const codeRefs = getCodeRefsByArtifactId(artifact.id, artifactGraph) + if (codeRefs?.length) { + graphSelections.push({ artifact, codeRef: codeRefs[0] }) + } } } - }) + ) return { graphSelections, diff --git a/src/lib/singletons.ts b/src/lib/singletons.ts index 892c5693f0b..a569b916917 100644 --- a/src/lib/singletons.ts +++ b/src/lib/singletons.ts @@ -93,6 +93,8 @@ export const sceneEntitiesManager = new SceneEntities( kclManager, rustContext ) +/** 🚨 Circular dependency alert 🚨 */ +kclManager.sceneEntitiesManager = sceneEntitiesManager if (typeof window !== 'undefined') { ;(window as any).engineCommandManager = engineCommandManager diff --git a/src/machines/featureTreeMachine.ts b/src/machines/featureTreeMachine.ts index d24863672b1..25df677cc4f 100644 --- a/src/machines/featureTreeMachine.ts +++ b/src/machines/featureTreeMachine.ts @@ -17,6 +17,7 @@ import type { KclManager } from '@src/lang/KclManager' import type RustContext from '@src/lib/rustContext' import { commandBarActor } from '@src/lib/singletons' import { err } from '@src/lib/trap' +import type { SceneEntities } from '@src/clientSideScene/sceneEntities' type FeatureTreeEvent = | { @@ -67,6 +68,7 @@ type FeatureTreeContext = { currentOperation?: Operation rustContext: RustContext kclManager: KclManager + sceneEntitiesManager: SceneEntities } export const featureTreeMachine = setup({ @@ -109,7 +111,11 @@ export const featureTreeMachine = setup({ input: { artifact: Artifact | undefined targetSourceRange: SourceRange | undefined - kclManager: KclManager + systemDeps: { + kclManager: KclManager + rustContext: RustContext + sceneEntitiesManager: SceneEntities + } } }) => { return new Promise((resolve, reject) => { @@ -120,7 +126,7 @@ export const featureTreeMachine = setup({ } const pathToNode = getNodePathFromSourceRange( - input.kclManager.ast, + input.systemDeps.kclManager.ast, targetSourceRange ) const selection = { @@ -130,7 +136,7 @@ export const featureTreeMachine = setup({ }, artifact, } - deleteSelectionPromise(selection) + deleteSelectionPromise({ selection, systemDeps: input.systemDeps }) .then((result) => { if (err(result)) { reject(result) @@ -473,7 +479,11 @@ export const featureTreeMachine = setup({ return { artifact, targetSourceRange: context.targetSourceRange, - kclManager: context.kclManager, + systemDeps: { + kclManager: context.kclManager, + rustContext: context.rustContext, + sceneEntitiesManager: context.sceneEntitiesManager, + }, } }, onDone: { diff --git a/src/machines/modelingMachine.spec.ts b/src/machines/modelingMachine.spec.ts index 54b673b7be2..8e36966fae8 100644 --- a/src/machines/modelingMachine.spec.ts +++ b/src/machines/modelingMachine.spec.ts @@ -151,8 +151,14 @@ describe('modelingMachine.test.ts', () => { describe('modelingMachine - XState', () => { describe('when initialized', () => { it('should start in the idle state', async () => { - const contextCopied = - generateModelingMachineDefaultContext(kclManagerInThisFile) + const contextCopied = generateModelingMachineDefaultContext({ + kclManager: kclManagerInThisFile, + sceneInfra: sceneInfraInThisFile, + rustContext: rustContextInThisFile, + wasmInstance: instanceInThisFile, + sceneEntitiesManager: sceneEntitiesManagerInThisFile, + engineCommandManager: engineCommandManagerInThisFile, + }) contextCopied.engineCommandManager = engineCommandManagerInThisFile contextCopied.sceneInfra = sceneInfraInThisFile contextCopied.sceneEntitiesManager = sceneEntitiesManagerInThisFile @@ -935,8 +941,14 @@ p3 = [342.51, 216.38], ) } - const contextCopied = - generateModelingMachineDefaultContext(kclManagerInThisFile) + const contextCopied = generateModelingMachineDefaultContext({ + kclManager: kclManagerInThisFile, + sceneInfra: sceneInfraInThisFile, + rustContext: rustContextInThisFile, + wasmInstance: instanceInThisFile, + sceneEntitiesManager: sceneEntitiesManagerInThisFile, + engineCommandManager: engineCommandManagerInThisFile, + }) const kclEditorActor = createActor(kclEditorMachine).start() contextCopied.engineCommandManager = engineCommandManagerInThisFile @@ -1062,8 +1074,14 @@ p3 = [342.51, 216.38], ) } - const contextCopied = - generateModelingMachineDefaultContext(kclManagerInThisFile) + const contextCopied = generateModelingMachineDefaultContext({ + kclManager: kclManagerInThisFile, + sceneInfra: sceneInfraInThisFile, + rustContext: rustContextInThisFile, + wasmInstance: instanceInThisFile, + sceneEntitiesManager: sceneEntitiesManagerInThisFile, + engineCommandManager: engineCommandManagerInThisFile, + }) const kclEditorActor = createActor(kclEditorMachine).start() contextCopied.engineCommandManager = engineCommandManagerInThisFile @@ -1199,8 +1217,14 @@ p3 = [342.51, 216.38], ) } - const contextCopied = - generateModelingMachineDefaultContext(kclManagerInThisFile) + const contextCopied = generateModelingMachineDefaultContext({ + kclManager: kclManagerInThisFile, + sceneInfra: sceneInfraInThisFile, + rustContext: rustContextInThisFile, + wasmInstance: instanceInThisFile, + sceneEntitiesManager: sceneEntitiesManagerInThisFile, + engineCommandManager: engineCommandManagerInThisFile, + }) const kclEditorActor = createActor(kclEditorMachine).start() contextCopied.engineCommandManager = engineCommandManagerInThisFile @@ -1323,8 +1347,14 @@ p3 = [342.51, 216.38], ) } - const contextCopied = - generateModelingMachineDefaultContext(kclManagerInThisFile) + const contextCopied = generateModelingMachineDefaultContext({ + kclManager: kclManagerInThisFile, + sceneInfra: sceneInfraInThisFile, + rustContext: rustContextInThisFile, + wasmInstance: instanceInThisFile, + sceneEntitiesManager: sceneEntitiesManagerInThisFile, + engineCommandManager: engineCommandManagerInThisFile, + }) const kclEditorActor = createActor(kclEditorMachine).start() contextCopied.engineCommandManager = engineCommandManagerInThisFile diff --git a/src/machines/modelingMachine.ts b/src/machines/modelingMachine.ts index 2430c3148cd..d8811ec0f86 100644 --- a/src/machines/modelingMachine.ts +++ b/src/machines/modelingMachine.ts @@ -14,8 +14,9 @@ import type { SketchTool, PlaneVisibilityMap, ModelingMachineContext, + ModelingMachineInput, } from '@src/machines/modelingSharedTypes' -import { modelingMachineDefaultContext } from '@src/machines/modelingSharedContext' +import { modelingMachineInitialInternalContext } from '@src/machines/modelingSharedContext' import type { Node } from '@rust/kcl-lib/bindings/Node' import type { @@ -140,12 +141,6 @@ import { updateExtraSegments, updateSelections, } from '@src/lib/selections' -import { - engineCommandManager, - rustContext, - sceneEntitiesManager, - sceneInfra, -} from '@src/lib/singletons' import { isSketchBlockSelected } from '@src/machines/sketchSolve/sketchSolveImpl' import { err, reportRejection, trap } from '@src/lib/trap' import { uuidv4 } from '@src/lib/utils' @@ -379,9 +374,10 @@ const NO_INPUT_PROVIDED_MESSAGE = 'No input provided' export const modelingMachine = setup({ types: { + // We store everything in the input on context as well context: {} as ModelingMachineContext, events: {} as ModelingMachineEvent, - input: {} as ModelingMachineContext, + input: {} as ModelingMachineInput, }, guards: { 'should use new sketch mode': ({ context }) => { @@ -630,7 +626,7 @@ export const modelingMachine = setup({ toast.error(event.error.message) } }, - toastErrorAndExitSketch: ({ event, context }) => { + toastErrorAndExitSketch: ({ event, context: { sceneEntitiesManager } }) => { if ('output' in event && event.output instanceof Error) { console.error(event.output) toast.error(event.output.message) @@ -642,13 +638,10 @@ export const modelingMachine = setup({ toast.error(event.error.message) } - const theSceneEntitiesManager = context.sceneEntitiesManager - ? context.sceneEntitiesManager - : sceneEntitiesManager // Clean up the THREE.js sketch scene - theSceneEntitiesManager.tearDownSketch({ removeAxis: false }) - theSceneEntitiesManager.removeSketchGrid() - theSceneEntitiesManager.resetOverlays() + sceneEntitiesManager.tearDownSketch({ removeAxis: false }) + sceneEntitiesManager.removeSketchGrid() + sceneEntitiesManager.resetOverlays() }, 'assign tool in context': assign({ currentTool: ({ event }) => @@ -682,12 +675,9 @@ export const modelingMachine = setup({ sketchEnginePathId: '', sketchPlaneId: '', }), - 'reset camera position': (context) => { - const theEngineCommandManager = context.context.engineCommandManager - ? context.context.engineCommandManager - : engineCommandManager + 'reset camera position': ({ context: { engineCommandManager } }) => { // eslint-disable-next-line @typescript-eslint/no-floating-promises - theEngineCommandManager.sendSceneCommand({ + engineCommandManager.sendSceneCommand({ type: 'modeling_cmd_req', cmd_id: uuidv4(), cmd: { @@ -712,7 +702,7 @@ export const modelingMachine = setup({ ({ context: { sketchDetails, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneEntitiesManager, kclManager, wasmInstance, }, @@ -720,12 +710,9 @@ export const modelingMachine = setup({ }) => { if (!sketchDetails) return {} if (event.type !== 'Add start point') return {} - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager // eslint-disable-next-line @typescript-eslint/no-floating-promises - theSceneEntitiesManager + sceneEntitiesManager .setupDraftSegment( event.data.sketchEntryNodePath || sketchDetails.sketchEntryNodePath, event.data.sketchNodePaths || sketchDetails.sketchNodePaths, @@ -755,7 +742,7 @@ export const modelingMachine = setup({ ({ context: { sketchDetails, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneEntitiesManager, kclManager, wasmInstance, }, @@ -763,12 +750,9 @@ export const modelingMachine = setup({ }) => { if (!sketchDetails) return {} if (event.type !== 'Continue existing profile') return {} - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager // eslint-disable-next-line @typescript-eslint/no-floating-promises - theSceneEntitiesManager + sceneEntitiesManager .setupDraftSegment( event.data.sketchEntryNodePath || sketchDetails.sketchEntryNodePath, event.data.sketchNodePaths || sketchDetails.sketchNodePaths, @@ -795,11 +779,7 @@ export const modelingMachine = setup({ } ), 'listen for rectangle origin': ({ - context: { - sketchDetails, - sceneEntitiesManager: providedSceneEntitiesManager, - sceneInfra: providedSceneInfra, - }, + context: { sketchDetails, sceneEntitiesManager, sceneInfra }, }) => { if (!sketchDetails) return const quaternion = quaternionFromUpNForward( @@ -807,32 +787,27 @@ export const modelingMachine = setup({ new Vector3(...sketchDetails.zAxis) ) - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const theSceneInfra = providedSceneInfra ? providedSceneInfra : sceneInfra // Position the click raycast plane - - theSceneEntitiesManager.intersectionPlane.setRotationFromQuaternion( + sceneEntitiesManager.intersectionPlane.setRotationFromQuaternion( quaternion ) - theSceneEntitiesManager.intersectionPlane.position.copy( + sceneEntitiesManager.intersectionPlane.position.copy( new Vector3(...(sketchDetails?.origin || [0, 0, 0])) ) - theSceneInfra.setCallbacks({ + sceneInfra.setCallbacks({ onMove: (args) => { - listenForOriginMove(args, sketchDetails, theSceneEntitiesManager) + listenForOriginMove(args, sketchDetails, sceneEntitiesManager) }, onClick: (args) => { - theSceneEntitiesManager.removeDraftPoint() + sceneEntitiesManager.removeDraftPoint() if (!args) return if (args.mouseEvent.which !== 1) return const twoD = args.intersectionPoint?.twoD if (twoD) { - theSceneInfra.modelingSend({ + sceneInfra.modelingSend({ type: 'click in scene', - data: theSceneEntitiesManager.getSnappedDragPoint( + data: sceneEntitiesManager.getSnappedDragPoint( twoD, args.intersects, args.mouseEvent @@ -846,43 +821,34 @@ export const modelingMachine = setup({ }, 'listen for center rectangle origin': ({ - context: { - sketchDetails, - sceneEntitiesManager: providedSceneEntitiesManager, - sceneInfra: providedSceneInfra, - }, + context: { sketchDetails, sceneEntitiesManager, sceneInfra }, }) => { if (!sketchDetails) return const quaternion = quaternionFromUpNForward( new Vector3(...sketchDetails.yAxis), new Vector3(...sketchDetails.zAxis) ) - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const theSceneInfra = providedSceneInfra ? providedSceneInfra : sceneInfra // Position the click raycast plane - - theSceneEntitiesManager.intersectionPlane.setRotationFromQuaternion( + sceneEntitiesManager.intersectionPlane.setRotationFromQuaternion( quaternion ) - theSceneEntitiesManager.intersectionPlane.position.copy( + sceneEntitiesManager.intersectionPlane.position.copy( new Vector3(...(sketchDetails?.origin || [0, 0, 0])) ) - theSceneInfra.setCallbacks({ + sceneInfra.setCallbacks({ onMove: (args) => { - listenForOriginMove(args, sketchDetails, theSceneEntitiesManager) + listenForOriginMove(args, sketchDetails, sceneEntitiesManager) }, onClick: (args) => { - theSceneEntitiesManager.removeDraftPoint() + sceneEntitiesManager.removeDraftPoint() if (!args) return if (args.mouseEvent.which !== 1) return const twoD = args.intersectionPoint?.twoD if (twoD) { - theSceneInfra.modelingSend({ + sceneInfra.modelingSend({ type: 'Add center rectangle origin', - data: theSceneEntitiesManager.getSnappedDragPoint( + data: sceneEntitiesManager.getSnappedDragPoint( twoD, args.intersects, args.mouseEvent @@ -896,33 +862,25 @@ export const modelingMachine = setup({ }, 'listen for circle origin': ({ - context: { - sketchDetails, - sceneEntitiesManager: providedSceneEntitiesManager, - sceneInfra: providedSceneInfra, - }, + context: { sketchDetails, sceneEntitiesManager, sceneInfra }, }) => { if (!sketchDetails) return const quaternion = quaternionFromUpNForward( new Vector3(...sketchDetails.yAxis), new Vector3(...sketchDetails.zAxis) ) - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const theSceneInfra = providedSceneInfra ? providedSceneInfra : sceneInfra - // Position the click raycast plane - theSceneEntitiesManager.intersectionPlane.setRotationFromQuaternion( + // Position the click raycast plane + sceneEntitiesManager.intersectionPlane.setRotationFromQuaternion( quaternion ) - theSceneEntitiesManager.intersectionPlane.position.copy( + sceneEntitiesManager.intersectionPlane.position.copy( new Vector3(...(sketchDetails?.origin || [0, 0, 0])) ) - theSceneInfra.setCallbacks({ + sceneInfra.setCallbacks({ onMove: (args) => { - listenForOriginMove(args, sketchDetails, theSceneEntitiesManager) + listenForOriginMove(args, sketchDetails, sceneEntitiesManager) }, onClick: (args) => { if (!args) return @@ -931,9 +889,9 @@ export const modelingMachine = setup({ if (!intersectionPoint?.twoD) return const twoD = args.intersectionPoint?.twoD if (twoD) { - theSceneInfra.modelingSend({ + sceneInfra.modelingSend({ type: 'Add circle origin', - data: theSceneEntitiesManager.getSnappedDragPoint( + data: sceneEntitiesManager.getSnappedDragPoint( twoD, args.intersects, args.mouseEvent @@ -946,33 +904,25 @@ export const modelingMachine = setup({ }) }, 'listen for circle first point': ({ - context: { - sketchDetails, - sceneEntitiesManager: providedSceneEntitiesManager, - sceneInfra: providedSceneInfra, - }, + context: { sketchDetails, sceneEntitiesManager, sceneInfra }, }) => { if (!sketchDetails) return const quaternion = quaternionFromUpNForward( new Vector3(...sketchDetails.yAxis), new Vector3(...sketchDetails.zAxis) ) - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const theSceneInfra = providedSceneInfra ? providedSceneInfra : sceneInfra // Position the click raycast plane - theSceneEntitiesManager.intersectionPlane.setRotationFromQuaternion( + sceneEntitiesManager.intersectionPlane.setRotationFromQuaternion( quaternion ) - theSceneEntitiesManager.intersectionPlane.position.copy( + sceneEntitiesManager.intersectionPlane.position.copy( new Vector3(...(sketchDetails?.origin || [0, 0, 0])) ) - theSceneInfra.setCallbacks({ + sceneInfra.setCallbacks({ onMove: (args) => { - listenForOriginMove(args, sketchDetails, theSceneEntitiesManager) + listenForOriginMove(args, sketchDetails, sceneEntitiesManager) }, onClick: (args) => { if (!args) return @@ -981,9 +931,9 @@ export const modelingMachine = setup({ if (!intersectionPoint?.twoD) return const twoD = args.intersectionPoint?.twoD if (twoD) { - theSceneInfra.modelingSend({ + sceneInfra.modelingSend({ type: 'Add first point', - data: theSceneEntitiesManager.getSnappedDragPoint( + data: sceneEntitiesManager.getSnappedDragPoint( twoD, args.intersects, args.mouseEvent @@ -996,11 +946,7 @@ export const modelingMachine = setup({ }) }, 'listen for circle second point': ({ - context: { - sketchDetails, - sceneEntitiesManager: providedSceneEntitiesManager, - sceneInfra: providedSceneInfra, - }, + context: { sketchDetails, sceneEntitiesManager, sceneInfra }, event, }) => { if (!sketchDetails) return @@ -1009,36 +955,32 @@ export const modelingMachine = setup({ new Vector3(...sketchDetails.yAxis), new Vector3(...sketchDetails.zAxis) ) - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const theSceneInfra = providedSceneInfra ? providedSceneInfra : sceneInfra - // Position the click raycast plane - theSceneEntitiesManager.intersectionPlane.setRotationFromQuaternion( + // Position the click raycast plane + sceneEntitiesManager.intersectionPlane.setRotationFromQuaternion( quaternion ) - theSceneEntitiesManager.intersectionPlane.position.copy( + sceneEntitiesManager.intersectionPlane.position.copy( new Vector3(...(sketchDetails?.origin || [0, 0, 0])) ) const dummy = new Mesh() dummy.position.set(0, 0, 0) - const scale = theSceneInfra.getClientSceneScaleFactor(dummy) + const scale = sceneInfra.getClientSceneScaleFactor(dummy) const position = new Vector3(event.data[0], event.data[1], 0) position.applyQuaternion(quaternion) const draftPoint = createProfileStartHandle({ isDraft: true, from: event.data, scale, - theme: theSceneInfra.theme, + theme: sceneInfra.theme, }) draftPoint.position.copy(position) - theSceneInfra.scene.add(draftPoint) + sceneInfra.scene.add(draftPoint) - theSceneInfra.setCallbacks({ + sceneInfra.setCallbacks({ onMove: (args) => { - listenForOriginMove(args, sketchDetails, theSceneEntitiesManager) + listenForOriginMove(args, sketchDetails, sceneEntitiesManager) }, onClick: (args) => { if (!args) return @@ -1047,11 +989,11 @@ export const modelingMachine = setup({ if (!intersectionPoint?.twoD) return const twoD = args.intersectionPoint?.twoD if (twoD) { - theSceneInfra.modelingSend({ + sceneInfra.modelingSend({ type: 'Add second point', data: { p1: event.data, - p2: theSceneEntitiesManager.getSnappedDragPoint( + p2: sceneEntitiesManager.getSnappedDragPoint( twoD, args.intersects, args.mouseEvent @@ -1133,23 +1075,14 @@ export const modelingMachine = setup({ return { defaultPlaneVisibility: { xy: true, xz: true, yz: true } } }), 'setup noPoints onClick listener': ({ - context: { - sketchDetails, - currentTool, - sceneEntitiesManager: providedSceneEntitiesManager, - sceneInfra: providedSceneInfra, - }, + context: { sketchDetails, currentTool, sceneEntitiesManager, sceneInfra }, }) => { if (!sketchDetails) return - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const theSceneInfra = providedSceneInfra ? providedSceneInfra : sceneInfra - theSceneEntitiesManager.setupNoPointsListener({ + sceneEntitiesManager.setupNoPointsListener({ sketchDetails, currentTool, afterClick: (_, data) => - theSceneInfra.modelingSend( + sceneInfra.modelingSend( currentTool === 'tangentialArc' ? { type: 'Continue existing profile', data } : { type: 'Add start point', data } @@ -1159,18 +1092,15 @@ export const modelingMachine = setup({ 'add axis n grid': ({ context: { sketchDetails, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneEntitiesManager, kclManager, wasmInstance, }, }) => { if (!sketchDetails) return if (localStorage.getItem('disableAxis')) return - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager // eslint-disable-next-line @typescript-eslint/no-floating-promises - theSceneEntitiesManager.createSketchAxis( + sceneEntitiesManager.createSketchAxis( sketchDetails.zAxis, sketchDetails.yAxis, sketchDetails.origin @@ -1186,41 +1116,37 @@ export const modelingMachine = setup({ 'reset client scene mouse handlers': ({ context }) => { // when not in sketch mode we don't need any mouse listeners // (note the orbit controls are always active though) - const theSceneInfra = context.sceneInfra ? context.sceneInfra : sceneInfra - theSceneInfra.resetMouseListeners() + context.sceneInfra.resetMouseListeners() }, 'clientToEngine cam sync direction': ({ context }) => { - const theSceneInfra = context.sceneInfra ? context.sceneInfra : sceneInfra - theSceneInfra.camControls.syncDirection = 'clientToEngine' + context.sceneInfra.camControls.syncDirection = 'clientToEngine' }, /** TODO: this action is hiding unawaited asynchronous code */ 'set selection filter to faces only': ({ context }) => { - context.kclManager.setSelectionFilter(['face', 'object']) + context.kclManager.setSelectionFilter( + ['face', 'object'], + context.sceneEntitiesManager + ) }, /** TODO: this action is hiding unawaited asynchronous code */ 'set selection filter to defaults': ({ context }) => { - context.kclManager.setSelectionFilterToDefault() + context.kclManager.setSelectionFilterToDefault( + context.sceneEntitiesManager + ) }, 'Delete segments': ({ context: { sketchDetails, kclManager, wasmInstance, - rustContext: providedRustContext, - sceneEntitiesManager: providedSceneEntitiesManager, - sceneInfra: providedSceneInfra, + rustContext, + sceneEntitiesManager, + sceneInfra, }, event, }) => { if (event.type !== 'Delete segments') return if (!sketchDetails || !event.data) return - const theRustContext = providedRustContext - ? providedRustContext - : rustContext - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const theSceneInfra = providedSceneInfra ? providedSceneInfra : sceneInfra // eslint-disable-next-line @typescript-eslint/no-floating-promises deleteSegmentsOrProfiles({ pathToNodes: event.data, @@ -1228,9 +1154,9 @@ export const modelingMachine = setup({ dependencies: { kclManager, wasmInstance, - rustContext: theRustContext, - sceneEntitiesManager: theSceneEntitiesManager, - sceneInfra: theSceneInfra, + rustContext, + sceneEntitiesManager, + sceneInfra, }, }) .then(() => { @@ -1244,15 +1170,14 @@ export const modelingMachine = setup({ console.warn('error', e) }) }, - 'remove draft entities': ({ context }) => { - const theSceneInfra = context.sceneInfra ? context.sceneInfra : sceneInfra - const draftPoint = theSceneInfra.scene.getObjectByName(DRAFT_POINT) + 'remove draft entities': ({ context: { sceneInfra } }) => { + const draftPoint = sceneInfra.scene.getObjectByName(DRAFT_POINT) if (draftPoint) { - theSceneInfra.scene.remove(draftPoint) + sceneInfra.scene.remove(draftPoint) } - const draftLine = theSceneInfra.scene.getObjectByName(DRAFT_DASHED_LINE) + const draftLine = sceneInfra.scene.getObjectByName(DRAFT_DASHED_LINE) if (draftLine) { - theSceneInfra.scene.remove(draftLine) + sceneInfra.scene.remove(draftLine) } }, 'add draft line': ({ event, context }) => { @@ -1262,10 +1187,8 @@ export const modelingMachine = setup({ ) return - const theSceneEntitiesManager = context.sceneEntitiesManager - ? context.sceneEntitiesManager - : sceneEntitiesManager - const theSceneInfra = context.sceneInfra ? context.sceneInfra : sceneInfra + const sceneEntitiesManager = context.sceneEntitiesManager + const sceneInfra = context.sceneInfra let sketchEntryNodePath: PathToNode | undefined if (event.type === 'Add start point') { @@ -1292,32 +1215,32 @@ export const modelingMachine = setup({ const lastSegment = sg.paths[sg.paths.length - 1] || sg.start const to = lastSegment.to - const { group, updater } = theSceneEntitiesManager.drawDashedLine({ + const { group, updater } = sceneEntitiesManager.drawDashedLine({ from: to, to: [to[0] + 0.001, to[1] + 0.001], }) - theSceneInfra.scene.add(group) - const orthoFactor = orthoScale(theSceneInfra.camControls.camera) - theSceneInfra.setCallbacks({ + sceneInfra.scene.add(group) + const orthoFactor = orthoScale(sceneInfra.camControls.camera) + sceneInfra.setCallbacks({ onMove: (args) => { const { intersectionPoint } = args if (!intersectionPoint?.twoD) return if (!context.sketchDetails) return const { snappedPoint, isSnapped } = - theSceneEntitiesManager.getSnappedDragPoint( + sceneEntitiesManager.getSnappedDragPoint( intersectionPoint.twoD, args.intersects, args.mouseEvent ) if (isSnapped) { - theSceneEntitiesManager.positionDraftPoint({ + sceneEntitiesManager.positionDraftPoint({ snappedPoint: new Vector2(...snappedPoint), origin: context.sketchDetails.origin, yAxis: context.sketchDetails.yAxis, zAxis: context.sketchDetails.zAxis, }) } else { - theSceneEntitiesManager.removeDraftPoint() + sceneEntitiesManager.removeDraftPoint() } updater(group, snappedPoint, orthoFactor) }, @@ -1339,7 +1262,8 @@ export const modelingMachine = setup({ context: { selectionRanges, sketchDetails, - engineCommandManager: providedEngineCommandManager, + engineCommandManager, + sceneEntitiesManager, kclManager, kclEditorMachine: providedKclEditorMachine, }, @@ -1463,6 +1387,10 @@ export const modelingMachine = setup({ artifactGraph: kclManager.artifactGraph, code: kclManager.code, ast: kclManager.ast, + systemDeps: { + engineCommandManager, + sceneEntitiesManager, + }, }) if (codeMirrorSelection) { theKclEditorMachine.send({ @@ -1477,12 +1405,9 @@ export const modelingMachine = setup({ // If there are engine commands that need sent off, send them // TODO: This should be handled outside of an action as its own // actor, so that the system state is more controlled. - const theEngineCommandManager = providedEngineCommandManager - ? providedEngineCommandManager - : engineCommandManager engineEvents && engineEvents.forEach((event) => { - theEngineCommandManager + engineCommandManager .sendSceneCommand(event) .catch(reportRejection) }) @@ -1530,6 +1455,10 @@ export const modelingMachine = setup({ artifactGraph: kclManager.artifactGraph, code: kclManager.code, ast: kclManager.ast, + systemDeps: { + engineCommandManager, + sceneEntitiesManager, + }, }) updateSceneObjectColors() @@ -1642,43 +1571,39 @@ export const modelingMachine = setup({ sketchExit: fromPromise( async (args: { input: { context: ModelingMachineContext } }) => { const context = args.input.context - const store = context.store - - const theEngineCommandManager = context.engineCommandManager - ? context.engineCommandManager - : engineCommandManager - const theSceneInfra = context.sceneInfra - ? context.sceneInfra - : sceneInfra - const theSceneEntitiesManager = context.sceneEntitiesManager - ? context.sceneEntitiesManager - : sceneEntitiesManager + const { + store, + engineCommandManager, + sceneInfra, + kclManager, + sceneEntitiesManager, + } = context // When cancelling the sketch mode we should disable sketch mode within the engine. - await theEngineCommandManager.sendSceneCommand({ + await engineCommandManager.sendSceneCommand({ type: 'modeling_cmd_req', cmd_id: uuidv4(), cmd: { type: 'sketch_mode_disable' }, }) - theSceneInfra.camControls.syncDirection = 'clientToEngine' + sceneInfra.camControls.syncDirection = 'clientToEngine' if (store.cameraProjection?.current === 'perspective') { - await theSceneInfra.camControls.snapToPerspectiveBeforeHandingBackControlToEngine() + await sceneInfra.camControls.snapToPerspectiveBeforeHandingBackControlToEngine() } - theSceneInfra.camControls.syncDirection = 'engineToClient' + sceneInfra.camControls.syncDirection = 'engineToClient' // TODO: Re-evaluate if this pause/play logic is needed. // TODO: Do I need this video element? store.videoElement?.pause() - await context.kclManager + await kclManager .executeCode() .then(() => { if ( - !theEngineCommandManager.started && - theEngineCommandManager.connection?.websocket?.readyState === + !engineCommandManager.started && + engineCommandManager.connection?.websocket?.readyState === WebSocket.CLOSED ) return @@ -1688,11 +1613,11 @@ export const modelingMachine = setup({ }) }) .catch(reportRejection) - theSceneEntitiesManager.tearDownSketch({ removeAxis: false }) - theSceneEntitiesManager.removeSketchGrid() - theSceneInfra.camControls.syncDirection = 'engineToClient' - theSceneEntitiesManager.resetOverlays() - theSceneInfra.stop() + sceneEntitiesManager.tearDownSketch({ removeAxis: false }) + sceneEntitiesManager.removeSketchGrid() + sceneInfra.camControls.syncDirection = 'engineToClient' + sceneEntitiesManager.resetOverlays() + sceneInfra.stop() } ), /* Below are all the do-constrain sketch actors, @@ -1703,7 +1628,7 @@ export const modelingMachine = setup({ selectionRanges, sketchDetails, data, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneEntitiesManager, kclManager, wasmInstance, }, @@ -1726,10 +1651,7 @@ export const modelingMachine = setup({ if (trap(constraint)) return const { pathToNodeMap } = constraint if (!sketchDetails) return - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - let updatedAst = await theSceneEntitiesManager.updateAstAndRejigSketch( + let updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch( pathToNodeMap[0], sketchDetails.sketchNodePaths, sketchDetails.planeNodePath, @@ -1767,7 +1689,7 @@ export const modelingMachine = setup({ selectionRanges, sketchDetails, kclManager, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneEntitiesManager, wasmInstance, }, }: { @@ -1789,22 +1711,18 @@ export const modelingMachine = setup({ if (trap(constraint)) return false const { modifiedAst, pathToNodeMap } = constraint if (!sketchDetails) return - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const updatedAst = - await theSceneEntitiesManager.updateAstAndRejigSketch( - sketchDetails.sketchEntryNodePath, - sketchDetails.sketchNodePaths, - sketchDetails.planeNodePath, - modifiedAst, - sketchDetails.zAxis, - sketchDetails.yAxis, - sketchDetails.origin, - getEventForSegmentSelection, - updateExtraSegments, - wasmInstance - ) + const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch( + sketchDetails.sketchEntryNodePath, + sketchDetails.sketchNodePaths, + sketchDetails.planeNodePath, + modifiedAst, + sketchDetails.zAxis, + sketchDetails.yAxis, + sketchDetails.origin, + getEventForSegmentSelection, + updateExtraSegments, + wasmInstance + ) if (trap(updatedAst, { suppress: true })) return if (!updatedAst) return await kclManager.updateEditorWithAstAndWriteToFile( @@ -1829,7 +1747,7 @@ export const modelingMachine = setup({ selectionRanges, sketchDetails, kclManager, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneEntitiesManager, wasmInstance, }, }: { @@ -1851,22 +1769,18 @@ export const modelingMachine = setup({ if (trap(constraint)) return false const { modifiedAst, pathToNodeMap } = constraint if (!sketchDetails) return - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const updatedAst = - await theSceneEntitiesManager.updateAstAndRejigSketch( - sketchDetails.sketchEntryNodePath || [], - sketchDetails.sketchNodePaths, - sketchDetails.planeNodePath, - modifiedAst, - sketchDetails.zAxis, - sketchDetails.yAxis, - sketchDetails.origin, - getEventForSegmentSelection, - updateExtraSegments, - wasmInstance - ) + const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch( + sketchDetails.sketchEntryNodePath || [], + sketchDetails.sketchNodePaths, + sketchDetails.planeNodePath, + modifiedAst, + sketchDetails.zAxis, + sketchDetails.yAxis, + sketchDetails.origin, + getEventForSegmentSelection, + updateExtraSegments, + wasmInstance + ) if (trap(updatedAst, { suppress: true })) return if (!updatedAst) return await kclManager.updateEditorWithAstAndWriteToFile( @@ -1891,7 +1805,7 @@ export const modelingMachine = setup({ selectionRanges, sketchDetails, kclManager, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneEntitiesManager, wasmInstance, }, }: { @@ -1911,22 +1825,18 @@ export const modelingMachine = setup({ if (trap(constraint)) return const { modifiedAst, pathToNodeMap } = constraint if (!sketchDetails) return - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const updatedAst = - await theSceneEntitiesManager.updateAstAndRejigSketch( - sketchDetails?.sketchEntryNodePath || [], - sketchDetails.sketchNodePaths, - sketchDetails.planeNodePath, - modifiedAst, - sketchDetails.zAxis, - sketchDetails.yAxis, - sketchDetails.origin, - getEventForSegmentSelection, - updateExtraSegments, - wasmInstance - ) + const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch( + sketchDetails?.sketchEntryNodePath || [], + sketchDetails.sketchNodePaths, + sketchDetails.planeNodePath, + modifiedAst, + sketchDetails.zAxis, + sketchDetails.yAxis, + sketchDetails.origin, + getEventForSegmentSelection, + updateExtraSegments, + wasmInstance + ) if (trap(updatedAst, { suppress: true })) return if (!updatedAst) return await kclManager.updateEditorWithAstAndWriteToFile( @@ -1952,7 +1862,7 @@ export const modelingMachine = setup({ selectionRanges, sketchDetails, kclManager, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneEntitiesManager, wasmInstance, }, }: { @@ -1972,22 +1882,18 @@ export const modelingMachine = setup({ if (trap(constraint)) return const { modifiedAst, pathToNodeMap } = constraint if (!sketchDetails) return - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const updatedAst = - await theSceneEntitiesManager.updateAstAndRejigSketch( - sketchDetails?.sketchEntryNodePath || [], - sketchDetails.sketchNodePaths, - sketchDetails.planeNodePath, - modifiedAst, - sketchDetails.zAxis, - sketchDetails.yAxis, - sketchDetails.origin, - getEventForSegmentSelection, - updateExtraSegments, - wasmInstance - ) + const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch( + sketchDetails?.sketchEntryNodePath || [], + sketchDetails.sketchNodePaths, + sketchDetails.planeNodePath, + modifiedAst, + sketchDetails.zAxis, + sketchDetails.yAxis, + sketchDetails.origin, + getEventForSegmentSelection, + updateExtraSegments, + wasmInstance + ) if (trap(updatedAst, { suppress: true })) return if (!updatedAst) return await kclManager.updateEditorWithAstAndWriteToFile( @@ -2013,7 +1919,7 @@ export const modelingMachine = setup({ selectionRanges, sketchDetails, kclManager, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneEntitiesManager, wasmInstance, }, }: { @@ -2033,22 +1939,18 @@ export const modelingMachine = setup({ if (err(constraint)) return false const { modifiedAst, pathToNodeMap } = constraint if (!sketchDetails) return - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const updatedAst = - await theSceneEntitiesManager.updateAstAndRejigSketch( - sketchDetails?.sketchEntryNodePath || [], - sketchDetails.sketchNodePaths, - sketchDetails.planeNodePath, - modifiedAst, - sketchDetails.zAxis, - sketchDetails.yAxis, - sketchDetails.origin, - getEventForSegmentSelection, - updateExtraSegments, - wasmInstance - ) + const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch( + sketchDetails?.sketchEntryNodePath || [], + sketchDetails.sketchNodePaths, + sketchDetails.planeNodePath, + modifiedAst, + sketchDetails.zAxis, + sketchDetails.yAxis, + sketchDetails.origin, + getEventForSegmentSelection, + updateExtraSegments, + wasmInstance + ) if (trap(updatedAst, { suppress: true })) return if (!updatedAst) return await kclManager.updateEditorWithAstAndWriteToFile( @@ -2074,7 +1976,7 @@ export const modelingMachine = setup({ selectionRanges, sketchDetails, kclManager, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneEntitiesManager, wasmInstance, }, }: { @@ -2094,22 +1996,18 @@ export const modelingMachine = setup({ if (trap(constraint)) return false const { modifiedAst, pathToNodeMap } = constraint if (!sketchDetails) return - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const updatedAst = - await theSceneEntitiesManager.updateAstAndRejigSketch( - sketchDetails?.sketchEntryNodePath || [], - sketchDetails.sketchNodePaths, - sketchDetails.planeNodePath, - modifiedAst, - sketchDetails.zAxis, - sketchDetails.yAxis, - sketchDetails.origin, - getEventForSegmentSelection, - updateExtraSegments, - wasmInstance - ) + const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch( + sketchDetails?.sketchEntryNodePath || [], + sketchDetails.sketchNodePaths, + sketchDetails.planeNodePath, + modifiedAst, + sketchDetails.zAxis, + sketchDetails.yAxis, + sketchDetails.origin, + getEventForSegmentSelection, + updateExtraSegments, + wasmInstance + ) if (trap(updatedAst, { suppress: true })) return if (!updatedAst) return await kclManager.updateEditorWithAstAndWriteToFile( @@ -2136,7 +2034,7 @@ export const modelingMachine = setup({ sketchDetails, kclManager, wasmInstance, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneEntitiesManager, }, }: { input: Pick< @@ -2158,25 +2056,21 @@ export const modelingMachine = setup({ trap(new Error('No sketch details')) return } - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager const recastAst = parse(recast(modifiedAst, wasmInstance), wasmInstance) if (err(recastAst) || !resultIsOk(recastAst)) return - const updatedAst = - await theSceneEntitiesManager.updateAstAndRejigSketch( - sketchDetails?.sketchEntryNodePath || [], - sketchDetails.sketchNodePaths, - sketchDetails.planeNodePath, - recastAst.program, - sketchDetails.zAxis, - sketchDetails.yAxis, - sketchDetails.origin, - getEventForSegmentSelection, - updateExtraSegments, - wasmInstance - ) + const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch( + sketchDetails?.sketchEntryNodePath || [], + sketchDetails.sketchNodePaths, + sketchDetails.planeNodePath, + recastAst.program, + sketchDetails.zAxis, + sketchDetails.yAxis, + sketchDetails.origin, + getEventForSegmentSelection, + updateExtraSegments, + wasmInstance + ) if (trap(updatedAst, { suppress: true })) return if (!updatedAst) return await kclManager.updateEditorWithAstAndWriteToFile( @@ -2203,7 +2097,7 @@ export const modelingMachine = setup({ selectionRanges, sketchDetails, kclManager, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneEntitiesManager, wasmInstance, }, }: { @@ -2222,22 +2116,18 @@ export const modelingMachine = setup({ if (trap(constraint)) return false const { modifiedAst, pathToNodeMap } = constraint if (!sketchDetails) return - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager - const updatedAst = - await theSceneEntitiesManager.updateAstAndRejigSketch( - sketchDetails?.sketchEntryNodePath || [], - sketchDetails.sketchNodePaths, - sketchDetails.planeNodePath, - modifiedAst, - sketchDetails.zAxis, - sketchDetails.yAxis, - sketchDetails.origin, - getEventForSegmentSelection, - updateExtraSegments, - wasmInstance - ) + const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch( + sketchDetails?.sketchEntryNodePath || [], + sketchDetails.sketchNodePaths, + sketchDetails.planeNodePath, + modifiedAst, + sketchDetails.zAxis, + sketchDetails.yAxis, + sketchDetails.origin, + getEventForSegmentSelection, + updateExtraSegments, + wasmInstance + ) if (trap(updatedAst, { suppress: true })) return if (!updatedAst) return await kclManager.updateEditorWithAstAndWriteToFile( @@ -2350,8 +2240,8 @@ export const modelingMachine = setup({ input: { sketchDetails, selectionRanges, - sceneInfra: providedSceneInfra, - sceneEntitiesManager: providedSceneEntitiesManager, + sceneInfra, + sceneEntitiesManager, kclManager: providedKclManager, wasmInstance, }, @@ -2359,8 +2249,8 @@ export const modelingMachine = setup({ input: { sketchDetails: SketchDetails | null selectionRanges: Selections - sceneInfra?: SceneInfra - sceneEntitiesManager?: SceneEntities + sceneInfra: SceneInfra + sceneEntitiesManager: SceneEntities kclManager: KclManager wasmInstance?: ModuleType } @@ -2368,21 +2258,15 @@ export const modelingMachine = setup({ if (!sketchDetails) { return } - const theSceneInfra = providedSceneInfra - ? providedSceneInfra - : sceneInfra - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager if (!sketchDetails.sketchEntryNodePath?.length) { // When unequipping eg. the three-point arc tool during placement of the 3rd point, sketchEntryNodePath is // empty if its the first profile in a sketch, but we still need to tear down and cancel the current tool properly. - theSceneInfra.resetMouseListeners() - theSceneEntitiesManager.tearDownSketch({ removeAxis: false }) + sceneInfra.resetMouseListeners() + sceneEntitiesManager.tearDownSketch({ removeAxis: false }) return } sceneInfra.resetMouseListeners() - await theSceneEntitiesManager.setupSketch({ + await sceneEntitiesManager.setupSketch({ sketchEntryNodePath: sketchDetails.sketchEntryNodePath, sketchNodePaths: sketchDetails.sketchNodePaths, forward: sketchDetails.zAxis, @@ -2392,9 +2276,9 @@ export const modelingMachine = setup({ selectionRanges, wasmInstance, }) - theSceneInfra.resetMouseListeners() + sceneInfra.resetMouseListeners() - theSceneEntitiesManager.setupSketchIdleCallbacks({ + sceneEntitiesManager.setupSketchIdleCallbacks({ sketchEntryNodePath: sketchDetails.sketchEntryNodePath, forward: sketchDetails.zAxis, up: sketchDetails.yAxis, @@ -2416,29 +2300,22 @@ export const modelingMachine = setup({ async ({ input: { selectionRanges, - kclManager: providedKclManager, - engineCommandManager: providedEngineCommandManager, - sceneEntitiesManager: providedSceneEntitiesManager, + kclManager, + engineCommandManager, + sceneEntitiesManager, + sceneInfra, }, }: { input: { selectionRanges: Selections kclManager: KclManager - engineCommandManager?: ConnectionManager - sceneEntitiesManager?: SceneEntities + engineCommandManager: ConnectionManager + sceneEntitiesManager: SceneEntities + sceneInfra: SceneInfra } }): Promise => { - const theEngineCommandManager = providedEngineCommandManager - ? providedEngineCommandManager - : engineCommandManager - const theSceneEntitiesManager = providedSceneEntitiesManager - ? providedSceneEntitiesManager - : sceneEntitiesManager const artifact = selectionRanges.graphSelections[0].artifact - const plane = getPlaneFromArtifact( - artifact, - providedKclManager.artifactGraph - ) + const plane = getPlaneFromArtifact(artifact, kclManager.artifactGraph) if (err(plane)) return Promise.reject(plane) // if the user selected a segment, make sure we enter the right sketch as there can be multiple on a plane // but still works if the user selected a plane/face by defaulting to the first path @@ -2449,9 +2326,7 @@ export const modelingMachine = setup({ let sketch: KclValue | null = null let planeVar: Plane | null = null - for (const variable of Object.values( - providedKclManager.execState.variables - )) { + for (const variable of Object.values(kclManager.execState.variables)) { // find programMemory that matches path artifact if ( variable?.type === 'Sketch' && @@ -2488,11 +2363,11 @@ export const modelingMachine = setup({ point.z, ] const planPath = getNodePathFromSourceRange( - providedKclManager.ast, + kclManager.ast, planeCodeRef.range ) await letEngineAnimateAndSyncCamAfter( - theEngineCommandManager, + engineCommandManager, artifact.id ) const normal = crossProduct(planeVar.xAxis, planeVar.yAxis) @@ -2507,30 +2382,30 @@ export const modelingMachine = setup({ } return Promise.reject(new Error('No sketch')) } - const info = await theSceneEntitiesManager.getSketchOrientationDetails( + const info = await sceneEntitiesManager.getSketchOrientationDetails( sketch.value ) await letEngineAnimateAndSyncCamAfter( - theEngineCommandManager, + engineCommandManager, info?.sketchDetails?.faceId || '' ) - const sketchArtifact = providedKclManager.artifactGraph.get(mainPath) + const sketchArtifact = kclManager.artifactGraph.get(mainPath) if (sketchArtifact?.type !== 'path') { return Promise.reject(new Error('No sketch artifact')) } const sketchPaths = getPathsFromArtifact({ - artifact: providedKclManager.artifactGraph.get(plane.id), + artifact: kclManager.artifactGraph.get(plane.id), sketchPathToNode: sketchArtifact?.codeRef?.pathToNode, - artifactGraph: providedKclManager.artifactGraph, - ast: providedKclManager.ast, + artifactGraph: kclManager.artifactGraph, + ast: kclManager.ast, }) if (err(sketchPaths)) return Promise.reject(sketchPaths) let codeRef = getFaceCodeRef(plane) if (!codeRef) return Promise.reject(new Error('No plane codeRef')) // codeRef.pathToNode is not always populated correctly const planeNodePath = getNodePathFromSourceRange( - providedKclManager.ast, + kclManager.ast, codeRef.range ) return { @@ -2568,9 +2443,6 @@ export const modelingMachine = setup({ if (!data) { return Promise.reject(new Error('No data from command flow')) } - const theSceneEntitiesManager = input.sceneEntitiesManager - ? input.sceneEntitiesManager - : sceneEntitiesManager let pResult = parse( recast(input.kclManager.ast, input.wasmInstance), input.wasmInstance @@ -2666,7 +2538,7 @@ export const modelingMachine = setup({ }) const updatedAst = - await theSceneEntitiesManager.updateAstAndRejigSketch( + await input.sceneEntitiesManager.updateAstAndRejigSketch( updatedSketchEntryNodePath, updatedSketchNodePaths, updatedPlaneNodePath, @@ -2777,7 +2649,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Extrude'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -2796,15 +2668,12 @@ export const modelingMachine = setup({ } const { modifiedAst, pathToNode } = astResult - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [pathToNode], @@ -2820,7 +2689,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Sweep'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -2838,15 +2707,12 @@ export const modelingMachine = setup({ } const { modifiedAst, pathToNode } = astResult - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [pathToNode], @@ -2862,7 +2728,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Loft'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -2876,15 +2742,12 @@ export const modelingMachine = setup({ } const { modifiedAst, pathToNode } = astResult - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [pathToNode], @@ -2900,7 +2763,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Revolve'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -2918,15 +2781,12 @@ export const modelingMachine = setup({ } const { modifiedAst, pathToNode } = astResult - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [pathToNode], @@ -2942,7 +2802,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Offset plane'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -2962,15 +2822,12 @@ export const modelingMachine = setup({ } const { modifiedAst, pathToNode } = astResult - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [pathToNode], @@ -2986,7 +2843,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Helix'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3005,15 +2862,12 @@ export const modelingMachine = setup({ } const { modifiedAst, pathToNode } = astResult - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [pathToNode], @@ -3029,7 +2883,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Shell'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3048,15 +2902,12 @@ export const modelingMachine = setup({ } const { modifiedAst, pathToNode } = astResult - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [pathToNode], @@ -3072,7 +2923,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Hole'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3105,15 +2956,12 @@ export const modelingMachine = setup({ } const { modifiedAst, pathToNode } = astResult - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [pathToNode], @@ -3129,8 +2977,8 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Fillet'] | undefined kclManager: KclManager - rustContext?: RustContext - engineCommandManager?: ConnectionManager + rustContext: RustContext + engineCommandManager: ConnectionManager } | undefined }) => { @@ -3149,16 +2997,13 @@ export const modelingMachine = setup({ } const { modifiedAst, pathToNode } = astResult - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: pathToNode, @@ -3174,8 +3019,8 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Chamfer'] | undefined kclManager: KclManager - rustContext?: RustContext - engineCommandManager?: ConnectionManager + rustContext: RustContext + engineCommandManager: ConnectionManager } | undefined }) => { @@ -3194,16 +3039,13 @@ export const modelingMachine = setup({ } const { modifiedAst, pathToNode } = astResult - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: pathToNode, @@ -3213,9 +3055,16 @@ export const modelingMachine = setup({ ), deleteSelectionAstMod: fromPromise( ({ - input: { selectionRanges }, + input: { selectionRanges, systemDeps }, }: { - input: { selectionRanges: Selections } + input: { + selectionRanges: Selections + systemDeps: { + kclManager: KclManager + rustContext: RustContext + sceneEntitiesManager: SceneEntities + } + } }) => { return new Promise((resolve, reject) => { if (!selectionRanges) { @@ -3227,7 +3076,7 @@ export const modelingMachine = setup({ reject(new Error(deletionErrorMessage)) } - deleteSelectionPromise(selection) + deleteSelectionPromise({ selection, systemDeps }) .then((result) => { if (err(result)) { reject(result) @@ -3247,7 +3096,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Appearance'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3264,15 +3113,12 @@ export const modelingMachine = setup({ if (err(result)) { return Promise.reject(result) } - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( result.modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [result.pathToNode], @@ -3288,7 +3134,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Translate'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3306,15 +3152,12 @@ export const modelingMachine = setup({ if (err(result)) { return Promise.reject(result) } - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( result.modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [result.pathToNode], @@ -3330,16 +3173,13 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Rotate'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { if (!input || !input.data) { return Promise.reject(new Error(NO_INPUT_PROVIDED_MESSAGE)) } - const theRustContext = input.rustContext - ? input.rustContext - : rustContext const ast = input.kclManager.ast const artifactGraph = input.kclManager.artifactGraph const result = addRotate({ @@ -3356,7 +3196,7 @@ export const modelingMachine = setup({ EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [result.pathToNode], @@ -3372,7 +3212,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Scale'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3391,15 +3231,12 @@ export const modelingMachine = setup({ return Promise.reject(result) } - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( result.modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [result.pathToNode], @@ -3415,7 +3252,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Clone'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3432,15 +3269,12 @@ export const modelingMachine = setup({ if (err(result)) { return Promise.reject(result) } - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( result.modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [result.pathToNode], @@ -3456,7 +3290,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['GDT Flatness'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3464,10 +3298,6 @@ export const modelingMachine = setup({ return Promise.reject(new Error(NO_INPUT_PROVIDED_MESSAGE)) } - const theRustContext = input.rustContext - ? input.rustContext - : rustContext - // Remove once this command isn't experimental anymore let astWithNewSetting: Node | undefined if ( @@ -3497,7 +3327,7 @@ export const modelingMachine = setup({ EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [result.pathToNode], @@ -3513,7 +3343,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['GDT Datum'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3521,10 +3351,6 @@ export const modelingMachine = setup({ return Promise.reject(new Error(NO_INPUT_PROVIDED_MESSAGE)) } - const theRustContext = input.rustContext - ? input.rustContext - : rustContext - // Remove once this command isn't experimental anymore let astWithNewSetting: Node | undefined if ( @@ -3554,7 +3380,7 @@ export const modelingMachine = setup({ EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [result.pathToNode], @@ -3584,7 +3410,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Boolean Subtract'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3601,15 +3427,12 @@ export const modelingMachine = setup({ if (err(result)) { return Promise.reject(result) } - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( result.modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [result.pathToNode], @@ -3625,7 +3448,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Boolean Union'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3642,15 +3465,12 @@ export const modelingMachine = setup({ if (err(result)) { return Promise.reject(result) } - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( result.modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [result.pathToNode], @@ -3666,7 +3486,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Boolean Intersect'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3684,15 +3504,12 @@ export const modelingMachine = setup({ if (err(result)) { return Promise.reject(new Error(NO_INPUT_PROVIDED_MESSAGE)) } - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( result.modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [result.pathToNode], @@ -3709,7 +3526,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Pattern Circular 3D'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3726,15 +3543,12 @@ export const modelingMachine = setup({ if (err(result)) { return Promise.reject(result) } - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( result.modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [result.pathToNode], @@ -3751,7 +3565,7 @@ export const modelingMachine = setup({ | { data: ModelingCommandSchema['Pattern Linear 3D'] | undefined kclManager: KclManager - rustContext?: RustContext + rustContext: RustContext } | undefined }) => { @@ -3769,15 +3583,12 @@ export const modelingMachine = setup({ if (err(result)) { return Promise.reject(result) } - const theRustContext = input.rustContext - ? input.rustContext - : rustContext await updateModelingState( result.modifiedAst, EXECUTION_TYPE_REAL, { kclManager: input.kclManager, - rustContext: theRustContext, + rustContext: input.rustContext, }, { focusPath: [result.pathToNode], @@ -3875,8 +3686,12 @@ export const modelingMachine = setup({ id: 'Modeling', context: ({ input }) => ({ - ...modelingMachineDefaultContext, + ...modelingMachineInitialInternalContext, ...input, + store: { + ...modelingMachineInitialInternalContext.store, + ...input.store, + }, }), states: { @@ -3886,8 +3701,8 @@ export const modelingMachine = setup({ { target: 'animating to existing sketch solve', actions: [ - () => { - sceneInfra.animate() + ({ context }) => { + context.sceneInfra.animate() }, ], guard: 'Selection is sketchBlock', @@ -3895,8 +3710,8 @@ export const modelingMachine = setup({ { target: 'animating to existing sketch', actions: [ - () => { - sceneInfra.animate() + ({ context }) => { + context.sceneInfra.animate() }, ], guard: 'Selection is on face', @@ -3904,8 +3719,8 @@ export const modelingMachine = setup({ { target: 'Sketch no face', actions: [ - () => { - sceneInfra.animate() + ({ context }) => { + context.sceneInfra.animate() }, ], }, @@ -5413,6 +5228,7 @@ export const modelingMachine = setup({ kclManager: context.kclManager, engineCommandManager: context.engineCommandManager, sceneEntitiesManager: context.sceneEntitiesManager, + sceneInfra: context.sceneInfra, }), onDone: { @@ -5442,10 +5258,9 @@ export const modelingMachine = setup({ sketchId: context.sketchSolveId || 0, initialSceneGraphDelta: context.initialSceneGraphDelta, // Use context values if available, otherwise fall back to singletons - sceneInfra: context.sceneInfra ?? sceneInfra, - sceneEntitiesManager: - context.sceneEntitiesManager ?? sceneEntitiesManager, - rustContext: context.rustContext ?? rustContext, + sceneInfra: context.sceneInfra, + sceneEntitiesManager: context.sceneEntitiesManager, + rustContext: context.rustContext, kclManager: context.kclManager, }), onDone: { @@ -5527,6 +5342,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5546,6 +5362,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5565,6 +5382,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5584,6 +5402,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5603,6 +5422,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5622,6 +5442,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5641,6 +5462,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5660,6 +5482,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5680,6 +5503,7 @@ export const modelingMachine = setup({ data: event.data, kclManager: context.kclManager, engineCommandManager: context.engineCommandManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5700,6 +5524,7 @@ export const modelingMachine = setup({ data: event.data, kclManager: context.kclManager, engineCommandManager: context.engineCommandManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5736,7 +5561,14 @@ export const modelingMachine = setup({ id: 'deleteSelectionAstMod', input: ({ context }) => { - return { selectionRanges: context.selectionRanges } + return { + selectionRanges: context.selectionRanges, + systemDeps: { + kclManager: context.kclManager, + rustContext: context.rustContext, + sceneEntitiesManager: context.sceneEntitiesManager, + }, + } }, onDone: 'idle', @@ -5761,6 +5593,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5780,6 +5613,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5799,6 +5633,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5818,6 +5653,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5837,6 +5673,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: ['idle'], @@ -5925,6 +5762,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: 'idle', @@ -5944,6 +5782,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: 'idle', @@ -5963,6 +5802,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: 'idle', @@ -5982,6 +5822,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: 'idle', @@ -6001,6 +5842,7 @@ export const modelingMachine = setup({ return { data: event.data, kclManager: context.kclManager, + rustContext: context.rustContext, } }, onDone: 'idle', @@ -6077,8 +5919,8 @@ export const modelingMachine = setup({ 'reset sketch metadata', 'enable copilot', 'enter modeling mode', - () => { - sceneInfra.stop() + ({ context }) => { + context.sceneInfra.stop() }, ], }, diff --git a/src/machines/modelingSharedContext.ts b/src/machines/modelingSharedContext.ts index bff2b7b5e5b..7e4cc522254 100644 --- a/src/machines/modelingSharedContext.ts +++ b/src/machines/modelingSharedContext.ts @@ -1,50 +1,55 @@ +import type { SceneEntities } from '@src/clientSideScene/sceneEntities' +import type { SceneInfra } from '@src/clientSideScene/sceneInfra' import type { KclManager } from '@src/lang/KclManager' -import type { ModelingMachineContext } from '@src/machines/modelingSharedTypes' - -export const modelingMachineDefaultContext: Omit< +import type RustContext from '@src/lib/rustContext' +import type { ConnectionManager } from '@src/network/connectionManager' +import type { ModuleType } from '@src/lib/wasm_lib_wrapper' +import type { ModelingMachineContext, - 'kclManager' -> = { - currentMode: 'modeling', - currentTool: 'none', - toastId: null, - machineManager: { - machines: [], - machineApiIp: null, - currentMachine: null, - setCurrentMachine: () => {}, - noMachinesReason: () => undefined, - }, - selection: [], - selectionRanges: { - graphSelections: [], - otherSelections: [], - }, - sketchDetails: null, - sketchSolveInit: null, - sketchPlaneId: '', - sketchEnginePathId: '', - moveDescs: [], - mouseState: { type: 'idle' }, - segmentOverlays: {}, - segmentHoverMap: {}, - store: {}, - defaultPlaneVisibility: { - xy: true, - xz: true, - yz: true, - }, - savedDefaultPlaneVisibility: { - xy: true, - xz: true, - yz: true, - }, - planesInitialized: false, - sketchSolveToolName: null, - sketchSolveTool: null, -} + ModelingMachineInternalContext, +} from '@src/machines/modelingSharedTypes' + +export const modelingMachineInitialInternalContext: ModelingMachineInternalContext = + { + currentMode: 'modeling', + currentTool: 'none', + toastId: null, + selection: [], + selectionRanges: { + graphSelections: [], + otherSelections: [], + }, + sketchDetails: null, + sketchPlaneId: '', + sketchEnginePathId: '', + moveDescs: [], + mouseState: { type: 'idle' }, + segmentOverlays: {}, + segmentHoverMap: {}, + store: {}, + defaultPlaneVisibility: { + xy: true, + xz: true, + yz: true, + }, + savedDefaultPlaneVisibility: { + xy: true, + xz: true, + yz: true, + }, + planesInitialized: false, + sketchSolveToolName: null, + sketchSolveTool: null, + } -export function generateModelingMachineDefaultContext(kclManager: KclManager) { +export function generateModelingMachineDefaultContext(systemDeps: { + kclManager: KclManager + sceneInfra: SceneInfra + rustContext: RustContext + wasmInstance: ModuleType + sceneEntitiesManager: SceneEntities + engineCommandManager: ConnectionManager +}) { const context: ModelingMachineContext = { currentMode: 'modeling', currentTool: 'none', @@ -83,7 +88,7 @@ export function generateModelingMachineDefaultContext(kclManager: KclManager) { planesInitialized: false, sketchSolveTool: null, sketchSolveToolName: null, - kclManager, + ...systemDeps, } return context } diff --git a/src/machines/modelingSharedTypes.ts b/src/machines/modelingSharedTypes.ts index 23306c5841b..2d96ff3f068 100644 --- a/src/machines/modelingSharedTypes.ts +++ b/src/machines/modelingSharedTypes.ts @@ -198,11 +198,21 @@ export type SketchTool = export type MoveDesc = { line: number; snippet: string } -export interface ModelingMachineContext { +/** Input into the Modeling machine consists of its external dependencies */ +export type ModelingMachineInput = { + kclManager: KclManager + engineCommandManager: ConnectionManager + sceneInfra: SceneInfra + sceneEntitiesManager: SceneEntities + rustContext: RustContext + machineManager: MachineManager + wasmInstance?: ModuleType + store?: Store +} +export type ModelingMachineInternalContext = { currentMode: ToolbarModeName currentTool: SketchTool toastId: string | null - machineManager: MachineManager selection: string[] selectionRanges: Selections sketchDetails: SketchDetails | null @@ -217,13 +227,7 @@ export interface ModelingMachineContext { defaultPlaneVisibility: PlaneVisibilityMap savedDefaultPlaneVisibility: PlaneVisibilityMap planesInitialized: boolean - kclManager: KclManager - engineCommandManager?: ConnectionManager - sceneInfra?: SceneInfra - sceneEntitiesManager?: SceneEntities - wasmInstance?: ModuleType kclEditorMachine?: ActorRefFrom - rustContext?: RustContext // sketch solve context sketchSolveInit?: DefaultPlane | OffsetPlane | ExtrudeFacePlane | null sketchSolveId?: number @@ -232,6 +236,8 @@ export interface ModelingMachineContext { sketchSolveTool: EquipTool | null sketchSolveToolName: EquipTool | null } +export type ModelingMachineContext = ModelingMachineInput & + ModelingMachineInternalContext export type PlaneVisibilityMap = { xy: boolean diff --git a/src/machines/settingsMachine.ts b/src/machines/settingsMachine.ts index ac35c7bc8d3..aac242ae5aa 100644 --- a/src/machines/settingsMachine.ts +++ b/src/machines/settingsMachine.ts @@ -39,6 +39,7 @@ import { Themes, darkModeMatcher, getOppositeTheme, + getResolvedTheme, getSystemTheme, setThemeClass, } from '@src/lib/theme' @@ -208,13 +209,16 @@ export const settingsMachine = setup({ const rootContext = self.system.get('root')?.getSnapshot().context const sceneInfra = rootContext?.sceneInfra const sceneEntitiesManager = rootContext?.sceneEntitiesManager + const kclManager = rootContext?.kclManager - if (!sceneInfra || !sceneEntitiesManager) { + if (!sceneInfra || !sceneEntitiesManager || !kclManager) { return } + const resolvedTheme = getResolvedTheme(context.app.theme.current) const opposingTheme = getOppositeTheme(context.app.theme.current) sceneInfra.theme = opposingTheme sceneEntitiesManager.updateSegmentBaseColor(opposingTheme) + kclManager.setEditorTheme(resolvedTheme) }, setAllowOrbitInSketchMode: ({ context, self }) => { const rootContext = self.system.get('root')?.getSnapshot().context diff --git a/src/menu/register.ts b/src/menu/register.ts index 62c99ef2267..e783dd31dfb 100644 --- a/src/menu/register.ts +++ b/src/menu/register.ts @@ -1,7 +1,7 @@ import { AxisNames } from '@src/lib/constants' import { PATHS } from '@src/lib/paths' import type { SettingsType } from '@src/lib/settings/initialSettings' -import { sceneInfra } from '@src/lib/singletons' +import type { SceneInfra } from '@src/clientSideScene/sceneInfra' import type { ConnectionManager } from '@src/network/connectionManager' import { authActor, @@ -18,7 +18,8 @@ export function modelingMenuCallbackMostActions( settings: SettingsType, navigate: NavigateFunction, filePath: string, - engineCommandManager: ConnectionManager + engineCommandManager: ConnectionManager, + sceneInfra: SceneInfra ) { // Menu listeners const cb = (data: WebContentSendPayload) => { diff --git a/src/unitTestUtils.ts b/src/unitTestUtils.ts index a1bf7bd4d2f..3a310af1124 100644 --- a/src/unitTestUtils.ts +++ b/src/unitTestUtils.ts @@ -20,6 +20,7 @@ import env from '@src/env' import { SceneEntities } from '@src/clientSideScene/sceneEntities' import { commandBarMachine } from '@src/machines/commandBarMachine' import { createActor } from 'xstate' +import type { ModuleType } from '@src/lib/wasm_lib_wrapper' /** * Throw x if it's an Error. Only use this in tests. @@ -81,6 +82,7 @@ export async function buildTheWorldAndConnectToEngine() { await instancePromise ) sceneEntitiesManager.commandBarActor = commandBarActor + kclManager.sceneEntitiesManager = sceneEntitiesManager await new Promise((resolve) => { engineCommandManager @@ -110,12 +112,19 @@ export async function buildTheWorldAndConnectToEngine() { } // Initialize all the singletons and the WASM blob but do not connect to the engine -export async function buildTheWorldAndNoEngineConnection() { - const WASM_PATH = join(process.cwd(), 'public/kcl_wasm_lib_bg.wasm') - const instancePromise = loadAndInitialiseWasmInstance(WASM_PATH) +export async function buildTheWorldAndNoEngineConnection(mockWasm = false) { + async function loadWasm() { + const WASM_PATH = join(process.cwd(), 'public/kcl_wasm_lib_bg.wasm') + const instancePromise = loadAndInitialiseWasmInstance(WASM_PATH) + return instancePromise + } + const instancePromise = mockWasm + ? Promise.resolve({} as ModuleType) + : loadWasm() const engineCommandManager = new ConnectionManager() const rustContext = new RustContext(engineCommandManager, instancePromise) const sceneInfra = new SceneInfra(engineCommandManager) + const kclManager = new KclManager(engineCommandManager, instancePromise, { rustContext, sceneInfra, @@ -123,11 +132,19 @@ export async function buildTheWorldAndNoEngineConnection() { engineCommandManager.kclManager = kclManager engineCommandManager.sceneInfra = sceneInfra engineCommandManager.rustContext = rustContext + const sceneEntitiesManager = new SceneEntities( + engineCommandManager, + sceneInfra, + kclManager, + rustContext + ) + kclManager.sceneEntitiesManager = sceneEntitiesManager return { instance: await instancePromise, engineCommandManager, rustContext, sceneInfra, kclManager, + sceneEntitiesManager, } } diff --git a/vitest.config.ts b/vitest.config.ts index 157227684d1..7e2ae6ae345 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -37,6 +37,7 @@ export default defineConfig({ name: 'integration', include: ['src/**/*.spec.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], hookTimeout: 60_000, + retry: 2, }, }, ],