Compare commits
6 Commits
remove-the
...
lf94/fix-b
Author | SHA1 | Date | |
---|---|---|---|
826e9d8f4a | |||
7097aae0c6 | |||
f165de6b1c | |||
deeec5f2bc | |||
0a665816d9 | |||
0c1bf86222 |
4
.github/workflows/cargo-bench.yml
vendored
@ -38,7 +38,5 @@ jobs:
|
||||
- name: Benchmark kcl library
|
||||
shell: bash
|
||||
run: |-
|
||||
cd src/wasm-lib/kcl; cargo bench --all-features -- iai
|
||||
env:
|
||||
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}
|
||||
cd src/wasm-lib/kcl; cargo bench -- iai
|
||||
|
||||
|
14
.github/workflows/ci.yml
vendored
@ -107,7 +107,7 @@ jobs:
|
||||
'.plugins.updater.endpoints[]=$url' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
|
||||
echo "$(jq --arg id 'dev.zoo.modeling-app-nightly' \
|
||||
'.identifier=$id' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
|
||||
echo "$(jq --arg name 'Zoo Modeling App (Nightly)' \
|
||||
echo "$(jq --arg name 'zoo-modeling-app-nightly' \
|
||||
'.productName=$name' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
@ -286,9 +286,9 @@ jobs:
|
||||
|
||||
yarn tauri build --target "${target}" --verbose --config src-tauri/tauri.app-store.conf.json
|
||||
|
||||
app_path="src-tauri/target/${target}/release/bundle/macos/Zoo Modeling App.app"
|
||||
build_name="src-tauri/target/${target}/release/bundle/macos/Zoo Modeling App.pkg"
|
||||
cp_dir="src-tauri/target/${target}/release/bundle/macos/Zoo Modeling App.app/Contents/embedded.provisionprofile"
|
||||
app_path="src-tauri/target/${target}/release/bundle/macos/zoo-modeling-app.app"
|
||||
build_name="src-tauri/target/${target}/release/bundle/macos/zoo-modeling-app.pkg"
|
||||
cp_dir="src-tauri/target/${target}/release/bundle/macos/zoo-modeling-app.app/Contents/embedded.provisionprofile"
|
||||
entitlements="src-tauri/entitlements/app-store.entitlements"
|
||||
|
||||
cp "${profile}" "${cp_dir}"
|
||||
@ -312,7 +312,7 @@ jobs:
|
||||
uses: apple-actions/upload-testflight-build@v1
|
||||
if: ${{ github.event_name == 'schedule' && matrix.os == 'macos-14' }}
|
||||
with:
|
||||
app-path: 'src-tauri/target/universal-apple-darwin/release/bundle/macos/Zoo Modeling App.pkg'
|
||||
app-path: 'src-tauri/target/universal-apple-darwin/release/bundle/macos/zoo-modeling-app.pkg'
|
||||
issuer-id: ${{ secrets.APPLE_STORE_ISSUER_ID }}
|
||||
api-key-id: ${{ secrets.APPLE_STORE_API_KEY_ID }}
|
||||
api-private-key: ${{ secrets.APPLE_STORE_API_PRIVATE_KEY }}
|
||||
@ -367,7 +367,7 @@ jobs:
|
||||
export VITE_KC_API_BASE_URL
|
||||
xvfb-run yarn test:e2e:tauri
|
||||
env:
|
||||
E2E_APPLICATION: "./src-tauri/target/${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}/app"
|
||||
E2E_APPLICATION: "./src-tauri/target/${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}/zoo-modeling-app"
|
||||
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
|
||||
- name: Run e2e tests (windows only)
|
||||
@ -376,7 +376,7 @@ jobs:
|
||||
cargo install tauri-driver --force
|
||||
yarn wdio run wdio.conf.ts
|
||||
env:
|
||||
E2E_APPLICATION: ".\\src-tauri\\target\\${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}\\app.exe"
|
||||
E2E_APPLICATION: ".\\src-tauri\\target\\${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}\\zoo-modeling-app.exe"
|
||||
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
VITE_KC_API_BASE_URL: ${{ env.BUILD_RELEASE == 'true' && 'https://api.zoo.dev' || 'https://api.dev.zoo.dev' }}
|
||||
E2E_TAURI_ENABLED: true
|
||||
|
52
.github/workflows/playwright.yml
vendored
@ -38,8 +38,6 @@ jobs:
|
||||
runs-on: ubuntu-latest-8-cores
|
||||
needs: check-rust-changes
|
||||
steps:
|
||||
- name: Tune GitHub-hosted runner network
|
||||
uses: smorimoto/tune-github-hosted-runner-network@v1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
@ -92,17 +90,11 @@ jobs:
|
||||
- name: build web
|
||||
run: yarn build:local
|
||||
- name: Run ubuntu/chrome snapshots
|
||||
continue-on-error: true
|
||||
run: |
|
||||
yarn playwright test --project="Google Chrome" --update-snapshots e2e/playwright/snapshot-tests.spec.ts
|
||||
run: yarn playwright test --project="Google Chrome" --update-snapshots e2e/playwright/snapshot-tests.spec.ts
|
||||
env:
|
||||
CI: true
|
||||
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
|
||||
- name: Clean up test-results
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
run: rm -r test-results
|
||||
- name: check for changes
|
||||
id: git-check
|
||||
run: |
|
||||
@ -129,7 +121,7 @@ jobs:
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: steps.git-check.outputs.modified == 'true'
|
||||
with:
|
||||
name: playwright-report-ubuntu-${{ github.sha }}
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 30
|
||||
# if have previous run results, use them
|
||||
@ -137,18 +129,16 @@ jobs:
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
with:
|
||||
name: test-results-ubuntu-${{ github.sha }}
|
||||
name: test-results
|
||||
path: test-results/
|
||||
- name: Run ubuntu/chrome flow retry failures
|
||||
id: retry
|
||||
if: always()
|
||||
run: |
|
||||
if [[ -d "test-results" ]];
|
||||
then if [[ $(ls -1 "test-results" | wc -l) != "0" ]];
|
||||
then echo "retried=true" >> $GITHUB_OUTPUT;
|
||||
else echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
|
||||
fi;
|
||||
else echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
|
||||
ls -1 "test-results"
|
||||
if [[ $(ls -1 "test-results" | wc -l) == "0" ]];
|
||||
then echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
|
||||
else echo "retried=true" >> $GITHUB_OUTPUT;
|
||||
fi;
|
||||
yarn playwright test --project="Google Chrome" --last-failed e2e/playwright/flow-tests.spec.ts
|
||||
env:
|
||||
@ -163,25 +153,23 @@ jobs:
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: test-results-ubuntu-${{ github.sha }}
|
||||
name: test-results
|
||||
path: test-results/
|
||||
retention-days: 30
|
||||
overwrite: true
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report-ubuntu-${{ github.sha }}
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 30
|
||||
overwrite: true
|
||||
|
||||
playwright-macos:
|
||||
timeout-minutes: 60
|
||||
runs-on: macos-14-large
|
||||
runs-on: macos-14
|
||||
needs: check-rust-changes
|
||||
steps:
|
||||
- name: Tune GitHub-hosted runner network
|
||||
uses: smorimoto/tune-github-hosted-runner-network@v1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
@ -239,25 +227,23 @@ jobs:
|
||||
if: ${{ always() }}
|
||||
continue-on-error: true
|
||||
with:
|
||||
name: test-results-macos-${{ github.sha }}
|
||||
name: test-results
|
||||
path: test-results/
|
||||
- name: Run macos/safari flow retry failures
|
||||
id: retry
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
if: ${{ success() }}
|
||||
run: |
|
||||
if [[ -d "test-results" ]];
|
||||
then if [[ $(ls -1 "test-results" | wc -l) != "0" ]];
|
||||
then echo "retried=true" >> $GITHUB_OUTPUT;
|
||||
else echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
|
||||
fi;
|
||||
else echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
|
||||
if [ -d "test-results" ];
|
||||
then echo "retried=true" >> $GITHUB_OUTPUT;
|
||||
else echo "retried=false" >> $GITHUB_OUTPUT;
|
||||
fi;
|
||||
yarn playwright test --project="webkit" --last-failed e2e/playwright/flow-tests.spec.ts
|
||||
env:
|
||||
CI: true
|
||||
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
- name: Run macos/safari flow
|
||||
if: steps.retry.outputs.retried == 'false'
|
||||
if: ${{ steps.retry.outputs.retried != 'true' }}
|
||||
# webkit doesn't work on Ubuntu because of the same reason tauri doesn't (webRTC issues)
|
||||
# TODO remove this and the matrix and run all tests on ubuntu when this is fixed
|
||||
run: yarn playwright test --project="webkit" e2e/playwright/flow-tests.spec.ts
|
||||
@ -267,14 +253,14 @@ jobs:
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: test-results-macos-${{ github.sha }}
|
||||
name: test-results
|
||||
path: test-results/
|
||||
retention-days: 30
|
||||
overwrite: true
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: playwright-report-macos-${{ github.sha }}
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 30
|
||||
overwrite: true
|
||||
|
@ -17,8 +17,11 @@ angleToMatchLengthX(segment_name: TagIdentifier, to: number, sketch_group: Sketc
|
||||
```js
|
||||
const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([2, 5], %, $seg01)
|
||||
|> angledLineToX([-angleToMatchLengthX(seg01, 7, %), 10], %)
|
||||
|> line([2, 5], %, 'seg01')
|
||||
|> angledLineToX([
|
||||
-angleToMatchLengthX('seg01', 7, %),
|
||||
10
|
||||
], %)
|
||||
|> close(%)
|
||||
|
||||
const extrusion = extrude(5, sketch001)
|
||||
|
@ -17,9 +17,9 @@ angleToMatchLengthY(segment_name: TagIdentifier, to: number, sketch_group: Sketc
|
||||
```js
|
||||
const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([1, 2], %, $seg01)
|
||||
|> line([1, 2], %, 'seg01')
|
||||
|> angledLine({
|
||||
angle: angleToMatchLengthY(seg01, 15, %),
|
||||
angle: angleToMatchLengthY('seg01', 15, %),
|
||||
length: 5
|
||||
}, %)
|
||||
|> yLineTo(0, %)
|
||||
|
@ -17,10 +17,10 @@ angledLineOfXLength(data: AngledLineData, sketch_group: SketchGroup, tag?: TagDe
|
||||
```js
|
||||
const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> angledLineOfXLength({ angle: 45, length: 10 }, %, $edge1)
|
||||
|> angledLineOfXLength({ angle: -15, length: 20 }, %, $edge2)
|
||||
|> angledLineOfXLength({ angle: 45, length: 10 }, %, "edge1")
|
||||
|> angledLineOfXLength({ angle: -15, length: 20 }, %, "edge2")
|
||||
|> line([0, -5], %)
|
||||
|> close(%, $edge3)
|
||||
|> close(%, "edge3")
|
||||
|
||||
const extrusion = extrude(10, sketch001)
|
||||
```
|
||||
|
@ -18,7 +18,7 @@ angledLineThatIntersects(data: AngledLineThatIntersectsData, sketch_group: Sketc
|
||||
const exampleSketch = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> lineTo([5, 10], %)
|
||||
|> lineTo([-10, 10], %, $lineToIntersect)
|
||||
|> lineTo([-10, 10], %, "lineToIntersect")
|
||||
|> lineTo([0, 20], %)
|
||||
|> angledLineThatIntersects({
|
||||
angle: 80,
|
||||
|
@ -22,19 +22,19 @@ const chamferLength = 2
|
||||
|
||||
const mountingPlateSketch = startSketchOn("XY")
|
||||
|> startProfileAt([-width / 2, -length / 2], %)
|
||||
|> lineTo([width / 2, -length / 2], %, $edge1)
|
||||
|> lineTo([width / 2, length / 2], %, $edge2)
|
||||
|> lineTo([-width / 2, length / 2], %, $edge3)
|
||||
|> close(%, $edge4)
|
||||
|> lineTo([width / 2, -length / 2], %, 'edge1')
|
||||
|> lineTo([width / 2, length / 2], %, 'edge2')
|
||||
|> lineTo([-width / 2, length / 2], %, 'edge3')
|
||||
|> close(%, 'edge4')
|
||||
|
||||
const mountingPlate = extrude(thickness, mountingPlateSketch)
|
||||
|> chamfer({
|
||||
length: chamferLength,
|
||||
tags: [
|
||||
getNextAdjacentEdge(edge1, %),
|
||||
getNextAdjacentEdge(edge2, %),
|
||||
getNextAdjacentEdge(edge3, %),
|
||||
getNextAdjacentEdge(edge4, %)
|
||||
getNextAdjacentEdge('edge1', %),
|
||||
getNextAdjacentEdge('edge2', %),
|
||||
getNextAdjacentEdge('edge3', %),
|
||||
getNextAdjacentEdge('edge4', %)
|
||||
]
|
||||
}, %)
|
||||
```
|
||||
|
@ -9,7 +9,7 @@ Sketch a circle.
|
||||
|
||||
|
||||
```js
|
||||
circle(center: [number], radius: number, sketch_surface_or_group: SketchSurfaceOrGroup, tag?: TagDeclarator) -> SketchGroup
|
||||
circle(center: [number], radius: number, tag?: TagDeclarator, sketch_surface_or_group: SketchSurfaceOrGroup) -> SketchGroup
|
||||
```
|
||||
|
||||
### Examples
|
||||
@ -41,6 +41,14 @@ const example = extrude(5, exampleSketch)
|
||||
|
||||
* `center`: `[number]` (REQUIRED)
|
||||
* `radius`: `number` (REQUIRED)
|
||||
* `tag`: `TagDeclarator` (OPTIONAL)
|
||||
```js
|
||||
{
|
||||
end: number,
|
||||
start: number,
|
||||
value: string,
|
||||
}
|
||||
```
|
||||
* `sketch_surface_or_group`: `SketchSurfaceOrGroup` - A sketch surface or a sketch group. (REQUIRED)
|
||||
```js
|
||||
{
|
||||
@ -502,14 +510,6 @@ const example = extrude(5, exampleSketch)
|
||||
}],
|
||||
}
|
||||
```
|
||||
* `tag`: `TagDeclarator` (OPTIONAL)
|
||||
```js
|
||||
{
|
||||
end: number,
|
||||
start: number,
|
||||
value: string,
|
||||
}
|
||||
```
|
||||
|
||||
### Returns
|
||||
|
||||
|
@ -22,19 +22,19 @@ const filletRadius = 2
|
||||
|
||||
const mountingPlateSketch = startSketchOn("XY")
|
||||
|> startProfileAt([-width / 2, -length / 2], %)
|
||||
|> lineTo([width / 2, -length / 2], %, $edge1)
|
||||
|> lineTo([width / 2, length / 2], %, $edge2)
|
||||
|> lineTo([-width / 2, length / 2], %, $edge3)
|
||||
|> close(%, $edge4)
|
||||
|> lineTo([width / 2, -length / 2], %, 'edge1')
|
||||
|> lineTo([width / 2, length / 2], %, 'edge2')
|
||||
|> lineTo([-width / 2, length / 2], %, 'edge3')
|
||||
|> close(%, 'edge4')
|
||||
|
||||
const mountingPlate = extrude(thickness, mountingPlateSketch)
|
||||
|> fillet({
|
||||
radius: filletRadius,
|
||||
tags: [
|
||||
getNextAdjacentEdge(edge1, %),
|
||||
getNextAdjacentEdge(edge2, %),
|
||||
getNextAdjacentEdge(edge3, %),
|
||||
getNextAdjacentEdge(edge4, %)
|
||||
getNextAdjacentEdge('edge1', %),
|
||||
getNextAdjacentEdge('edge2', %),
|
||||
getNextAdjacentEdge('edge3', %),
|
||||
getNextAdjacentEdge('edge4', %)
|
||||
]
|
||||
}, %)
|
||||
```
|
||||
|
@ -17,7 +17,7 @@ getEdge(tag: TagIdentifier, extrude_group: ExtrudeGroup) -> Uuid
|
||||
```js
|
||||
const box = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([0, 10], %, $revolveAxis)
|
||||
|> line([0, 10], %, 'revolveAxis')
|
||||
|> line([10, 0], %)
|
||||
|> line([0, -10], %)
|
||||
|> close(%)
|
||||
@ -30,7 +30,7 @@ const revolution = startSketchOn(box, "revolveAxis")
|
||||
|> line([0, -10], %)
|
||||
|> close(%)
|
||||
|> revolve({
|
||||
axis: getEdge(revolveAxis, box),
|
||||
axis: getEdge('revolveAxis', box),
|
||||
angle: 90
|
||||
}, %)
|
||||
```
|
||||
|
@ -21,13 +21,15 @@ const exampleSketch = startSketchOn('XZ')
|
||||
|> angledLine({ angle: 60, length: 10 }, %)
|
||||
|> angledLine({ angle: 120, length: 10 }, %)
|
||||
|> line([-10, 0], %)
|
||||
|> angledLine({ angle: 240, length: 10 }, %, $referenceEdge)
|
||||
|> angledLine({ angle: 240, length: 10 }, %, 'referenceEdge')
|
||||
|> close(%)
|
||||
|
||||
const example = extrude(5, exampleSketch)
|
||||
|> fillet({
|
||||
radius: 3,
|
||||
tags: [getNextAdjacentEdge(referenceEdge, %)]
|
||||
tags: [
|
||||
getNextAdjacentEdge("referenceEdge", %)
|
||||
]
|
||||
}, %)
|
||||
```
|
||||
|
||||
|
@ -21,13 +21,13 @@ const exampleSketch = startSketchOn('XZ')
|
||||
|> angledLine({ angle: 60, length: 10 }, %)
|
||||
|> angledLine({ angle: 120, length: 10 }, %)
|
||||
|> line([-10, 0], %)
|
||||
|> angledLine({ angle: 240, length: 10 }, %, $referenceEdge)
|
||||
|> angledLine({ angle: 240, length: 10 }, %, 'referenceEdge')
|
||||
|> close(%)
|
||||
|
||||
const example = extrude(5, exampleSketch)
|
||||
|> fillet({
|
||||
radius: 3,
|
||||
tags: [getOppositeEdge(referenceEdge, %)]
|
||||
tags: [getOppositeEdge("referenceEdge", %)]
|
||||
}, %)
|
||||
```
|
||||
|
||||
|
@ -21,14 +21,14 @@ const exampleSketch = startSketchOn('XZ')
|
||||
|> angledLine({ angle: 60, length: 10 }, %)
|
||||
|> angledLine({ angle: 120, length: 10 }, %)
|
||||
|> line([-10, 0], %)
|
||||
|> angledLine({ angle: 240, length: 10 }, %, $referenceEdge)
|
||||
|> angledLine({ angle: 240, length: 10 }, %, 'referenceEdge')
|
||||
|> close(%)
|
||||
|
||||
const example = extrude(5, exampleSketch)
|
||||
|> fillet({
|
||||
radius: 3,
|
||||
tags: [
|
||||
getPreviousAdjacentEdge(referenceEdge, %)
|
||||
getPreviousAdjacentEdge("referenceEdge", %)
|
||||
]
|
||||
}, %)
|
||||
```
|
||||
|
@ -55,7 +55,6 @@ layout: manual
|
||||
* [`patternCircular3d`](kcl/patternCircular3d)
|
||||
* [`patternLinear2d`](kcl/patternLinear2d)
|
||||
* [`patternLinear3d`](kcl/patternLinear3d)
|
||||
* [`patternTransform`](kcl/patternTransform)
|
||||
* [`pi`](kcl/pi)
|
||||
* [`pow`](kcl/pow)
|
||||
* [`profileStart`](kcl/profileStart)
|
||||
|
@ -17,9 +17,9 @@ profileStart(sketch_group: SketchGroup) -> [number]
|
||||
```js
|
||||
const sketch001 = startSketchOn('XY')
|
||||
|> startProfileAt([5, 2], %)
|
||||
|> angledLine({ angle: 120, length: 50 }, %, $seg01)
|
||||
|> angledLine({ angle: 120, length: 50 }, %, 'seg01')
|
||||
|> angledLine({
|
||||
angle: segAng(seg01, %) + 120,
|
||||
angle: segAng('seg01', %) + 120,
|
||||
length: 50
|
||||
}, %)
|
||||
|> lineTo(profileStart(%), %)
|
||||
|
@ -99,7 +99,7 @@ const box = startSketchOn('XY')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([0, 20], %)
|
||||
|> line([20, 0], %)
|
||||
|> line([0, -20], %, $revolveAxis)
|
||||
|> line([0, -20], %, 'revolveAxis')
|
||||
|> close(%)
|
||||
|> extrude(20, %)
|
||||
|
||||
@ -107,7 +107,7 @@ const sketch001 = startSketchOn(box, "END")
|
||||
|> circle([10, 10], 4, %)
|
||||
|> revolve({
|
||||
angle: 90,
|
||||
axis: getOppositeEdge(revolveAxis, box)
|
||||
axis: getOppositeEdge('revolveAxis', box)
|
||||
}, %)
|
||||
```
|
||||
|
||||
|
@ -18,11 +18,11 @@ segAng(segment_name: TagIdentifier, sketch_group: SketchGroup) -> number
|
||||
const exampleSketch = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([10, 0], %)
|
||||
|> line([5, 10], %, $seg01)
|
||||
|> line([5, 10], %, 'seg01')
|
||||
|> line([-10, 0], %)
|
||||
|> angledLine([segAng(seg01, %), 10], %)
|
||||
|> angledLine([segAng('seg01', %), 10], %)
|
||||
|> line([-10, 0], %)
|
||||
|> angledLine([segAng(seg01, %), -15], %)
|
||||
|> angledLine([segAng('seg01', %), -15], %)
|
||||
|> close(%)
|
||||
|
||||
const example = extrude(4, exampleSketch)
|
||||
|
@ -17,9 +17,9 @@ segEndX(segment_name: TagIdentifier, sketch_group: SketchGroup) -> number
|
||||
```js
|
||||
const exampleSketch = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([20, 0], %, $thing)
|
||||
|> line([20, 0], %, "thing")
|
||||
|> line([0, 5], %)
|
||||
|> line([segEndX(thing, %), 0], %)
|
||||
|> line([segEndX("thing", %), 0], %)
|
||||
|> line([-20, 10], %)
|
||||
|> close(%)
|
||||
|
||||
|
@ -18,9 +18,9 @@ segEndY(segment_name: TagIdentifier, sketch_group: SketchGroup) -> number
|
||||
const exampleSketch = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([20, 0], %)
|
||||
|> line([0, 3], %, $thing)
|
||||
|> line([0, 3], %, "thing")
|
||||
|> line([-10, 0], %)
|
||||
|> line([0, segEndY(thing, %)], %)
|
||||
|> line([0, segEndY("thing", %)], %)
|
||||
|> line([-10, 0], %)
|
||||
|> close(%)
|
||||
|
||||
|
@ -17,9 +17,12 @@ segLen(segment_name: TagIdentifier, sketch_group: SketchGroup) -> number
|
||||
```js
|
||||
const exampleSketch = startSketchOn("XZ")
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> angledLine({ angle: 60, length: 10 }, %, $thing)
|
||||
|> angledLine({ angle: 60, length: 10 }, %, "thing")
|
||||
|> tangentialArc({ offset: -120, radius: 5 }, %)
|
||||
|> angledLine({ angle: -60, length: segLen(thing, %) }, %)
|
||||
|> angledLine({
|
||||
angle: -60,
|
||||
length: segLen("thing", %)
|
||||
}, %)
|
||||
|> close(%)
|
||||
|
||||
const example = extrude(5, exampleSketch)
|
||||
|
@ -49,7 +49,7 @@ const example003 = extrude(5, exampleSketch003)
|
||||
const exampleSketch = startSketchOn("XY")
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([10, 0], %)
|
||||
|> line([0, 10], %, $sketchingFace)
|
||||
|> line([0, 10], %, 'sketchingFace')
|
||||
|> line([-10, 0], %)
|
||||
|> close(%)
|
||||
|
||||
@ -60,7 +60,7 @@ const exampleSketch002 = startSketchOn(example, 'sketchingFace')
|
||||
|> line([8, 0], %)
|
||||
|> line([0, 8], %)
|
||||
|> line([-8, 0], %)
|
||||
|> close(%, $sketchingFace002)
|
||||
|> close(%, 'sketchingFace002')
|
||||
|
||||
const example002 = extrude(10, exampleSketch002)
|
||||
|
||||
|
4322
docs/kcl/std.json
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 43 KiB |
@ -45,8 +45,8 @@ async function clearCommandLogs(page: Page) {
|
||||
await page.getByTestId('clear-commands').click()
|
||||
}
|
||||
|
||||
async function expectCmdLog(page: Page, locatorStr: string, timeout = 5000) {
|
||||
await expect(page.locator(locatorStr).last()).toBeVisible({ timeout })
|
||||
async function expectCmdLog(page: Page, locatorStr: string) {
|
||||
await expect(page.locator(locatorStr).last()).toBeVisible()
|
||||
}
|
||||
|
||||
async function waitForDefaultPlanesToBeVisible(page: Page) {
|
||||
@ -228,8 +228,7 @@ export async function getUtils(page: Page) {
|
||||
await fillInput('z', xyz[2])
|
||||
},
|
||||
clearCommandLogs: () => clearCommandLogs(page),
|
||||
expectCmdLog: (locatorStr: string, timeout = 5000) =>
|
||||
expectCmdLog(page, locatorStr, timeout),
|
||||
expectCmdLog: (locatorStr: string) => expectCmdLog(page, locatorStr),
|
||||
openKclCodePanel: () => openKclCodePanel(page),
|
||||
closeKclCodePanel: () => closeKclCodePanel(page),
|
||||
openDebugPanel: () => openDebugPanel(page),
|
||||
@ -301,19 +300,11 @@ export async function getUtils(page: Page) {
|
||||
(screenshot.width * coords.y * pixMultiplier +
|
||||
coords.x * pixMultiplier) *
|
||||
4 // rbga is 4 channels
|
||||
const maxDiff = Math.max(
|
||||
return Math.max(
|
||||
Math.abs(screenshot.data[index] - expected[0]),
|
||||
Math.abs(screenshot.data[index + 1] - expected[1]),
|
||||
Math.abs(screenshot.data[index + 2] - expected[2])
|
||||
)
|
||||
if (maxDiff > 4) {
|
||||
console.log(
|
||||
`Expected: ${expected} Actual: [${screenshot.data[index]}, ${
|
||||
screenshot.data[index + 1]
|
||||
}, ${screenshot.data[index + 2]}]`
|
||||
)
|
||||
}
|
||||
return maxDiff
|
||||
},
|
||||
doAndWaitForImageDiff: (fn: () => Promise<any>, diffCount = 200) =>
|
||||
new Promise(async (resolve) => {
|
||||
|
@ -89,7 +89,7 @@
|
||||
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e",
|
||||
"fetch:wasm": "./get-latest-wasm-bundle.sh",
|
||||
"build:wasm-dev": "(cd src/wasm-lib && wasm-pack build --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt",
|
||||
"build:wasm": "(cd src/wasm-lib && wasm-pack build --release --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt",
|
||||
"build:wasm": "(cd src/wasm-lib && wasm-pack build --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt",
|
||||
"build:wasm-clean": "yarn wasm-prep && yarn build:wasm",
|
||||
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\" || echo \"sed for both mac and linux\"",
|
||||
"wasm-prep": "rm -rf src/wasm-lib/pkg && mkdir src/wasm-lib/pkg && rm -rf src/wasm-lib/kcl/bindings",
|
||||
|
@ -12,13 +12,13 @@ import { defineConfig, devices } from '@playwright/test'
|
||||
export default defineConfig({
|
||||
testDir: './e2e/playwright',
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
fullyParallel: false,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 3 : 0,
|
||||
/* Different amount of parallelism on CI and local. */
|
||||
workers: process.env.CI ? 4 : 4,
|
||||
workers: process.env.CI ? 1 : 4,
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: 'html',
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
|
BIN
public/cat.jpg
Before Width: | Height: | Size: 193 KiB |
35
src-tauri/Cargo.lock
generated
@ -405,6 +405,12 @@ dependencies = [
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba"
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
@ -1140,20 +1146,6 @@ dependencies = [
|
||||
"parking_lot_core 0.9.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "6.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "804c8821570c3f8b70230c2ba75ffa5c0f9a4189b9a432b6656c536712acae28"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"hashbrown 0.14.3",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core 0.9.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.5.0"
|
||||
@ -2576,7 +2568,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.1.67"
|
||||
version = "0.1.65"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx",
|
||||
@ -2586,7 +2578,7 @@ dependencies = [
|
||||
"bson",
|
||||
"chrono",
|
||||
"clap",
|
||||
"dashmap 6.0.1",
|
||||
"dashmap",
|
||||
"databake",
|
||||
"derive-docs",
|
||||
"form_urlencoded",
|
||||
@ -4546,9 +4538,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.118"
|
||||
version = "1.0.116"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
|
||||
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
|
||||
dependencies = [
|
||||
"indexmap 2.2.6",
|
||||
"itoa 1.0.11",
|
||||
@ -5874,7 +5866,7 @@ dependencies = [
|
||||
"async-trait",
|
||||
"auto_impl",
|
||||
"bytes",
|
||||
"dashmap 5.5.3",
|
||||
"dashmap",
|
||||
"futures",
|
||||
"httparse",
|
||||
"lsp-types",
|
||||
@ -6224,10 +6216,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.9.1"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439"
|
||||
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
|
||||
dependencies = [
|
||||
"atomic",
|
||||
"getrandom 0.2.14",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
|
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "app"
|
||||
name = "zoo-modeling-app"
|
||||
version = "0.1.0"
|
||||
description = "The Zoo Modeling App"
|
||||
authors = ["Zoo Engineers <eng@zoo.dev>"]
|
||||
|
@ -73,6 +73,6 @@
|
||||
"open": true
|
||||
}
|
||||
},
|
||||
"productName": "Zoo Modeling App",
|
||||
"productName": "zoo-modeling-app",
|
||||
"version": "0.22.6"
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import { LowerRightControls } from 'components/LowerRightControls'
|
||||
import ModalContainer from 'react-modal-promise'
|
||||
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
||||
import Gizmo from 'components/Gizmo'
|
||||
import { CoreDumpManager } from 'lib/coredump'
|
||||
|
||||
export function App() {
|
||||
useRefreshSettings(paths.FILE + 'SETTINGS')
|
||||
@ -56,11 +55,7 @@ export function App() {
|
||||
setHtmlRef(ref)
|
||||
}, [ref])
|
||||
|
||||
const { auth, settings } = useSettingsAuthContext()
|
||||
const token = auth?.context?.token
|
||||
|
||||
const coreDumpManager = new CoreDumpManager(engineCommandManager, ref, token)
|
||||
|
||||
const { settings } = useSettingsAuthContext()
|
||||
const {
|
||||
app: { onboardingStatus },
|
||||
} = settings.context
|
||||
@ -134,7 +129,7 @@ export function App() {
|
||||
<ModelingSidebar paneOpacity={paneOpacity} />
|
||||
<Stream />
|
||||
{/* <CamToggle /> */}
|
||||
<LowerRightControls coreDumpManager={coreDumpManager}>
|
||||
<LowerRightControls>
|
||||
<Gizmo />
|
||||
</LowerRightControls>
|
||||
</div>
|
||||
|
@ -534,7 +534,7 @@ export class SceneEntities {
|
||||
segmentName: 'line' | 'tangentialArcTo' = 'line',
|
||||
shouldTearDown = true
|
||||
) => {
|
||||
const _ast = kclManager.ast
|
||||
const _ast = JSON.parse(JSON.stringify(kclManager.ast))
|
||||
|
||||
const _node1 = getNodeFromPath<VariableDeclaration>(
|
||||
_ast,
|
||||
@ -692,7 +692,7 @@ export class SceneEntities {
|
||||
sketchOrigin: [number, number, number],
|
||||
rectangleOrigin: [x: number, y: number]
|
||||
) => {
|
||||
let _ast = kclManager.ast
|
||||
let _ast = JSON.parse(JSON.stringify(kclManager.ast))
|
||||
|
||||
const _node1 = getNodeFromPath<VariableDeclaration>(
|
||||
_ast,
|
||||
@ -723,9 +723,7 @@ export class SceneEntities {
|
||||
...getRectangleCallExpressions(rectangleOrigin, tags),
|
||||
])
|
||||
|
||||
let result = parse(recast(_ast))
|
||||
if (trap(result)) return Promise.reject(result)
|
||||
_ast = result
|
||||
_ast = parse(recast(_ast))
|
||||
|
||||
const { programMemoryOverride, truncatedAst } = await this.setupSketch({
|
||||
sketchPathToNode,
|
||||
@ -739,7 +737,7 @@ export class SceneEntities {
|
||||
sceneInfra.setCallbacks({
|
||||
onMove: async (args) => {
|
||||
// Update the width and height of the draft rectangle
|
||||
const pathToNodeTwo = sketchPathToNode
|
||||
const pathToNodeTwo = JSON.parse(JSON.stringify(sketchPathToNode))
|
||||
pathToNodeTwo[1][0] = 0
|
||||
|
||||
const _node = getNodeFromPath<VariableDeclaration>(
|
||||
@ -801,9 +799,7 @@ export class SceneEntities {
|
||||
if (sketchInit.type === 'PipeExpression') {
|
||||
updateRectangleSketch(sketchInit, x, y, tags[0])
|
||||
|
||||
let result = parse(recast(_ast))
|
||||
if (trap(result)) return Promise.reject(result)
|
||||
_ast = result
|
||||
_ast = parse(recast(_ast))
|
||||
|
||||
// Update the primary AST and unequip the rectangle tool
|
||||
await kclManager.executeAstMock(_ast)
|
||||
@ -1007,8 +1003,10 @@ export class SceneEntities {
|
||||
PROFILE_START,
|
||||
])
|
||||
if (!group) return
|
||||
const pathToNode: PathToNode = group.userData.pathToNode
|
||||
const varDecIndex: number = pathToNode[1][0] as number
|
||||
const pathToNode: PathToNode = JSON.parse(
|
||||
JSON.stringify(group.userData.pathToNode)
|
||||
)
|
||||
const varDecIndex = JSON.parse(JSON.stringify(pathToNode[1][0]))
|
||||
if (draftInfo) {
|
||||
pathToNode[1][0] = 0
|
||||
}
|
||||
@ -1721,7 +1719,7 @@ function prepareTruncatedMemoryAndAst(
|
||||
}
|
||||
| Error {
|
||||
const bodyIndex = Number(sketchPathToNode?.[1]?.[0]) || 0
|
||||
const _ast = ast
|
||||
const _ast = JSON.parse(JSON.stringify(ast))
|
||||
|
||||
const _node = getNodeFromPath<VariableDeclaration>(
|
||||
_ast,
|
||||
@ -1780,36 +1778,11 @@ function prepareTruncatedMemoryAndAst(
|
||||
}
|
||||
const truncatedAst: Program = {
|
||||
..._ast,
|
||||
body: [_ast.body[bodyIndex]],
|
||||
body: [JSON.parse(JSON.stringify(_ast.body[bodyIndex]))],
|
||||
}
|
||||
const programMemoryOverride = programMemoryInit()
|
||||
if (err(programMemoryOverride)) return programMemoryOverride
|
||||
|
||||
// Grab all the TagDeclarators and TagIdentifiers from memory.
|
||||
let start = _node.node.start
|
||||
for (const key in programMemory.root) {
|
||||
const value = programMemory.root[key]
|
||||
if (!('__meta' in value)) {
|
||||
continue
|
||||
}
|
||||
if (
|
||||
value.__meta === undefined ||
|
||||
value.__meta.length === 0 ||
|
||||
value.__meta[0].sourceRange === undefined
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (value.__meta[0].sourceRange[0] >= start) {
|
||||
// We only want things before our start point.
|
||||
continue
|
||||
}
|
||||
|
||||
if (value.type === 'TagIdentifier') {
|
||||
programMemoryOverride.root[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < bodyIndex; i++) {
|
||||
const node = _ast.body[i]
|
||||
if (node.type !== 'VariableDeclaration') {
|
||||
@ -1821,7 +1794,7 @@ function prepareTruncatedMemoryAndAst(
|
||||
if (!memoryItem) {
|
||||
continue
|
||||
}
|
||||
programMemoryOverride.root[name] = memoryItem
|
||||
programMemoryOverride.root[name] = JSON.parse(JSON.stringify(memoryItem))
|
||||
}
|
||||
return {
|
||||
truncatedAst,
|
||||
@ -1969,9 +1942,9 @@ export async function getSketchOrientationDetails(
|
||||
* @param entityId - The ID of the entity for which orientation details are being fetched.
|
||||
* @returns A promise that resolves with the orientation details of the face.
|
||||
*/
|
||||
export async function getFaceDetails(
|
||||
async function getFaceDetails(
|
||||
entityId: string
|
||||
): Promise<Models['GetSketchModePlane_type']> {
|
||||
): Promise<Models['FaceIsPlanar_type']> {
|
||||
// TODO mode engine connection to allow batching returns and batch the following
|
||||
await engineCommandManager.sendSceneCommand({
|
||||
type: 'modeling_cmd_req',
|
||||
@ -1984,7 +1957,8 @@ export async function getFaceDetails(
|
||||
entity_id: entityId,
|
||||
},
|
||||
})
|
||||
const faceInfo: Models['GetSketchModePlane_type'] = (
|
||||
// TODO change typing to get_sketch_mode_plane once lib is updated
|
||||
const faceInfo: Models['FaceIsPlanar_type'] = (
|
||||
await engineCommandManager.sendSceneCommand({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
|
@ -151,7 +151,9 @@ export function useCalc({
|
||||
ast,
|
||||
engineCommandManager,
|
||||
useFakeExecutor: true,
|
||||
programMemoryOverride: kclManager.programMemory,
|
||||
programMemoryOverride: JSON.parse(
|
||||
JSON.stringify(kclManager.programMemory)
|
||||
),
|
||||
}).then(({ programMemory }) => {
|
||||
const resultDeclaration = ast.body.find(
|
||||
(a) =>
|
||||
|
@ -6,18 +6,8 @@ import { NetworkHealthIndicator } from 'components/NetworkHealthIndicator'
|
||||
import { HelpMenu } from './HelpMenu'
|
||||
import { Link, useLocation } from 'react-router-dom'
|
||||
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
|
||||
import { coreDump } from 'lang/wasm'
|
||||
import toast from 'react-hot-toast'
|
||||
import { CoreDumpManager } from 'lib/coredump'
|
||||
import openWindow from 'lib/openWindow'
|
||||
|
||||
export function LowerRightControls({
|
||||
children,
|
||||
coreDumpManager,
|
||||
}: {
|
||||
children?: React.ReactNode
|
||||
coreDumpManager?: CoreDumpManager
|
||||
}) {
|
||||
export function LowerRightControls(props: React.PropsWithChildren) {
|
||||
const location = useLocation()
|
||||
const filePath = useAbsoluteFilePath()
|
||||
const linkOverrideClassName =
|
||||
@ -25,42 +15,9 @@ export function LowerRightControls({
|
||||
|
||||
const isPlayWright = window?.localStorage.getItem('playwright') === 'true'
|
||||
|
||||
async function reportbug(event: { preventDefault: () => void }) {
|
||||
event?.preventDefault()
|
||||
|
||||
if (!coreDumpManager) {
|
||||
// open default reporting option
|
||||
openWindow('https://github.com/KittyCAD/modeling-app/issues/new/choose')
|
||||
} else {
|
||||
toast
|
||||
.promise(
|
||||
coreDump(coreDumpManager, true),
|
||||
{
|
||||
loading: 'Preparing bug report...',
|
||||
success: 'Bug report opened in new window',
|
||||
error: 'Unable to export a core dump. Using default reporting.',
|
||||
},
|
||||
{
|
||||
success: {
|
||||
// Note: this extended duration is especially important for Playwright e2e testing
|
||||
// default duration is 2000 - https://react-hot-toast.com/docs/toast#default-durations
|
||||
duration: 6000,
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err: Error) => {
|
||||
if (err) {
|
||||
openWindow(
|
||||
'https://github.com/KittyCAD/modeling-app/issues/new/choose'
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="fixed bottom-2 right-2 flex flex-col items-end gap-3 pointer-events-none">
|
||||
{children}
|
||||
{props.children}
|
||||
<menu className="flex items-center justify-end gap-3 pointer-events-auto">
|
||||
<a
|
||||
href={`https://github.com/KittyCAD/modeling-app/releases/tag/v${APP_VERSION}`}
|
||||
@ -71,7 +28,6 @@ export function LowerRightControls({
|
||||
v{isPlayWright ? '11.22.33' : APP_VERSION}
|
||||
</a>
|
||||
<a
|
||||
onClick={reportbug}
|
||||
href="https://github.com/KittyCAD/modeling-app/issues/new/choose"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
|
@ -30,7 +30,7 @@ import { wasmUrl } from 'lang/wasm'
|
||||
import { PROJECT_ENTRYPOINT } from 'lib/constants'
|
||||
import { useNetworkContext } from 'hooks/useNetworkContext'
|
||||
import { NetworkHealthState } from 'hooks/useNetworkStatus'
|
||||
import { err } from 'lib/trap'
|
||||
import { err, trap } from 'lib/trap'
|
||||
|
||||
function getWorkspaceFolders(): LSP.WorkspaceFolder[] {
|
||||
return []
|
||||
|
@ -23,7 +23,6 @@ import {
|
||||
editorManager,
|
||||
sceneEntitiesManager,
|
||||
} from 'lib/singletons'
|
||||
import { useHotkeys } from 'react-hotkeys-hook'
|
||||
import { applyConstraintHorzVertDistance } from './Toolbar/SetHorzVertDistance'
|
||||
import {
|
||||
angleBetweenInfo,
|
||||
@ -79,7 +78,6 @@ import { getVarNameModal } from 'hooks/useToolbarGuards'
|
||||
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
||||
import { uuidv4 } from 'lib/utils'
|
||||
import { err, trap } from 'lib/trap'
|
||||
import { useCommandsContext } from 'hooks/useCommandsContext'
|
||||
|
||||
type MachineContext<T extends AnyStateMachine> = {
|
||||
state: StateFrom<T>
|
||||
@ -126,6 +124,7 @@ export const ModelingMachineProvider = ({
|
||||
token
|
||||
)
|
||||
useHotkeyWrapper(['meta + shift + .'], () => {
|
||||
console.warn('CoreDump: Initializing core dump')
|
||||
toast.promise(
|
||||
coreDump(coreDumpManager, true),
|
||||
{
|
||||
@ -142,7 +141,6 @@ export const ModelingMachineProvider = ({
|
||||
}
|
||||
)
|
||||
})
|
||||
const { commandBarState } = useCommandsContext()
|
||||
|
||||
// Settings machine setup
|
||||
// const retrievedSettings = useRef(
|
||||
@ -328,11 +326,6 @@ export const ModelingMachineProvider = ({
|
||||
)
|
||||
updateSceneObjectColors()
|
||||
|
||||
// side effect to stop code mirror from updating the same selections again
|
||||
editorManager.lastSelection = selections.codeBasedSelections
|
||||
.map(({ range }) => `${range[1]}->${range[1]}`)
|
||||
.join('&')
|
||||
|
||||
return {
|
||||
selectionRanges: selections,
|
||||
}
|
||||
@ -467,11 +460,6 @@ export const ModelingMachineProvider = ({
|
||||
|
||||
return canExtrudeSelection(selectionRanges)
|
||||
},
|
||||
'has valid selection for deletion': ({ selectionRanges }) => {
|
||||
if (!commandBarState.matches('Closed')) return false
|
||||
if (selectionRanges.codeBasedSelections.length <= 0) return false
|
||||
return true
|
||||
},
|
||||
'Sketch is empty': ({ sketchDetails }) => {
|
||||
const node = getNodeFromPath<VariableDeclaration>(
|
||||
kclManager.ast,
|
||||
@ -513,7 +501,7 @@ export const ModelingMachineProvider = ({
|
||||
services: {
|
||||
'AST-undo-startSketchOn': async ({ sketchDetails }) => {
|
||||
if (!sketchDetails) return
|
||||
const newAst: Program = kclManager.ast
|
||||
const newAst: Program = JSON.parse(JSON.stringify(kclManager.ast))
|
||||
const varDecIndex = sketchDetails.sketchPathToNode[1][0]
|
||||
// remove body item at varDecIndex
|
||||
newAst.body = newAst.body.filter((_, i) => i !== varDecIndex)
|
||||
@ -935,11 +923,6 @@ export const ModelingMachineProvider = ({
|
||||
}
|
||||
}, [modelingSend])
|
||||
|
||||
// Allow using the delete key to delete solids
|
||||
useHotkeys(['backspace', 'delete', 'del'], () => {
|
||||
modelingSend({ type: 'Delete selection' })
|
||||
})
|
||||
|
||||
useStateMachineCommands({
|
||||
machineId: 'modeling',
|
||||
state: modelingState,
|
||||
|
@ -1,25 +1,7 @@
|
||||
import { coreDump } from 'lang/wasm'
|
||||
import { CoreDumpManager } from 'lib/coredump'
|
||||
import { CustomIcon } from './CustomIcon'
|
||||
import { engineCommandManager } from 'lib/singletons'
|
||||
import React from 'react'
|
||||
import toast from 'react-hot-toast'
|
||||
import Tooltip from './Tooltip'
|
||||
import { useStore } from 'useStore'
|
||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||
|
||||
export const RefreshButton = ({ children }: React.PropsWithChildren) => {
|
||||
const { auth } = useSettingsAuthContext()
|
||||
const token = auth?.context?.token
|
||||
const { htmlRef } = useStore((s) => ({
|
||||
htmlRef: s.htmlRef,
|
||||
}))
|
||||
const coreDumpManager = new CoreDumpManager(
|
||||
engineCommandManager,
|
||||
htmlRef,
|
||||
token
|
||||
)
|
||||
|
||||
export function RefreshButton() {
|
||||
async function refresh() {
|
||||
if (window && 'plausible' in window) {
|
||||
const p = window.plausible as (
|
||||
@ -35,26 +17,8 @@ export const RefreshButton = ({ children }: React.PropsWithChildren) => {
|
||||
})
|
||||
}
|
||||
|
||||
toast
|
||||
.promise(
|
||||
coreDump(coreDumpManager, true),
|
||||
{
|
||||
loading: 'Starting core dump...',
|
||||
success: 'Core dump completed successfully',
|
||||
error: 'Error while exporting core dump',
|
||||
},
|
||||
{
|
||||
success: {
|
||||
// Note: this extended duration is especially important for Playwright e2e testing
|
||||
// default duration is 2000 - https://react-hot-toast.com/docs/toast#default-durations
|
||||
duration: 6000,
|
||||
},
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
// Window may not be available in some environments
|
||||
window?.location.reload()
|
||||
})
|
||||
// Window may not be available in some environments
|
||||
window?.location.reload()
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -83,7 +83,6 @@ export const Stream = ({ className = '' }: { className?: string }) => {
|
||||
if (!videoRef.current) return
|
||||
if (state.matches('Sketch')) return
|
||||
if (state.matches('Sketch no face')) return
|
||||
|
||||
const { x, y } = getNormalisedCoordinates({
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY,
|
||||
@ -128,7 +127,6 @@ export const Stream = ({ className = '' }: { className?: string }) => {
|
||||
return (
|
||||
<div
|
||||
className="absolute inset-0 z-0"
|
||||
id="stream"
|
||||
data-testid="stream"
|
||||
onMouseUp={handleMouseUp}
|
||||
onMouseDown={handleMouseDown}
|
||||
|
@ -145,7 +145,7 @@ export async function applyConstraintIntersect({
|
||||
const { transforms, forcedSelectionRanges } = info
|
||||
|
||||
const transform1 = transformSecondarySketchLinesTagFirst({
|
||||
ast: kclManager.ast,
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges: forcedSelectionRanges,
|
||||
transformInfos: transforms,
|
||||
programMemory: kclManager.programMemory,
|
||||
|
@ -106,7 +106,7 @@ export async function applyConstraintAbsDistance({
|
||||
const transformInfos = info.transforms
|
||||
|
||||
const transform1 = transformAstSketchLines({
|
||||
ast: kclManager.ast,
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges: selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
@ -128,7 +128,7 @@ export async function applyConstraintAbsDistance({
|
||||
)
|
||||
|
||||
const transform2 = transformAstSketchLines({
|
||||
ast: kclManager.ast,
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges: selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
@ -176,7 +176,7 @@ export function applyConstraintAxisAlign({
|
||||
let finalValue = createIdentifier('ZERO')
|
||||
|
||||
return transformAstSketchLines({
|
||||
ast: kclManager.ast,
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges: selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
|
@ -100,7 +100,7 @@ export async function applyConstraintAngleBetween({
|
||||
const transformInfos = info.transforms
|
||||
|
||||
const transformed1 = transformSecondarySketchLinesTagFirst({
|
||||
ast: kclManager.ast,
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
|
@ -108,7 +108,7 @@ export async function applyConstraintHorzVertDistance({
|
||||
if (err(info)) return Promise.reject(info)
|
||||
const transformInfos = info.transforms
|
||||
const transformed = transformSecondarySketchLinesTagFirst({
|
||||
ast: kclManager.ast,
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
|
@ -84,7 +84,7 @@ export async function applyConstraintAngleLength({
|
||||
|
||||
const { transforms } = angleLength
|
||||
const sketched = transformAstSketchLines({
|
||||
ast: kclManager.ast,
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges,
|
||||
transformInfos: transforms,
|
||||
programMemory: kclManager.programMemory,
|
||||
@ -139,7 +139,7 @@ export async function applyConstraintAngleLength({
|
||||
}
|
||||
|
||||
const retval = transformAstSketchLines({
|
||||
ast: kclManager.ast,
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges,
|
||||
transformInfos: transforms,
|
||||
programMemory: kclManager.programMemory,
|
||||
|
@ -20,12 +20,6 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
|
||||
const navigate = useNavigate()
|
||||
const send = useSettingsAuthContext()?.auth?.send
|
||||
|
||||
// This image host goes down sometimes. We will instead rewrite the
|
||||
// resource to be a local one.
|
||||
if (user?.image === 'https://placekitten.com/200/200') {
|
||||
user.image = '/cat.jpg'
|
||||
}
|
||||
|
||||
// Fallback logic for displaying user's "name":
|
||||
// 1. user.name
|
||||
// 2. user.first_name + ' ' + user.last_name
|
||||
|
@ -23,7 +23,7 @@ export default class EditorManager {
|
||||
}
|
||||
|
||||
private _lastSelectionEvent: number | null = null
|
||||
lastSelection: string = ''
|
||||
private _lastSelection: string = ''
|
||||
private _lastEvent: { event: string; time: number } | null = null
|
||||
|
||||
private _modelingSend: (eventInfo: ModelingMachineEvent) => void = () => {}
|
||||
@ -199,14 +199,12 @@ export default class EditorManager {
|
||||
viewUpdate?.state?.selection?.ranges || []
|
||||
)
|
||||
|
||||
if (selString === this.lastSelection) {
|
||||
if (selString === this._lastSelection) {
|
||||
// onUpdate is noisy and is fired a lot by extensions
|
||||
// since we're only interested in selections changes we can ignore most of these.
|
||||
return
|
||||
}
|
||||
// note this is also set from the "Set selection" action to stop code mirror from updating selections right after
|
||||
// selections are made from the scene
|
||||
this.lastSelection = selString
|
||||
this._lastSelection = selString
|
||||
|
||||
if (
|
||||
this._lastSelectionEvent &&
|
||||
|
@ -42,8 +42,9 @@ function registerServerCapability(
|
||||
serverCapabilities: ServerCapabilities,
|
||||
registration: Registration
|
||||
): ServerCapabilities | Error {
|
||||
const serverCapabilitiesCopy =
|
||||
serverCapabilities as IFlexibleServerCapabilities
|
||||
const serverCapabilitiesCopy = JSON.parse(
|
||||
JSON.stringify(serverCapabilities)
|
||||
) as IFlexibleServerCapabilities
|
||||
const { method, registerOptions } = registration
|
||||
const providerName = ServerCapabilitiesProviders[method]
|
||||
|
||||
@ -51,7 +52,10 @@ function registerServerCapability(
|
||||
if (!registerOptions) {
|
||||
serverCapabilitiesCopy[providerName] = true
|
||||
} else {
|
||||
serverCapabilitiesCopy[providerName] = Object.assign({}, registerOptions)
|
||||
serverCapabilitiesCopy[providerName] = Object.assign(
|
||||
{},
|
||||
JSON.parse(JSON.stringify(registerOptions))
|
||||
)
|
||||
}
|
||||
} else {
|
||||
return new Error('Could not register server capability.')
|
||||
@ -64,8 +68,9 @@ function unregisterServerCapability(
|
||||
serverCapabilities: ServerCapabilities,
|
||||
unregistration: Unregistration
|
||||
): ServerCapabilities {
|
||||
const serverCapabilitiesCopy =
|
||||
serverCapabilities as IFlexibleServerCapabilities
|
||||
const serverCapabilitiesCopy = JSON.parse(
|
||||
JSON.stringify(serverCapabilities)
|
||||
) as IFlexibleServerCapabilities
|
||||
const { method } = unregistration
|
||||
const providerName = ServerCapabilitiesProviders[method]
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { executeAst, lintAst } from 'useStore'
|
||||
import { executeAst } from 'useStore'
|
||||
import { Selections } from 'lib/selections'
|
||||
import { KCLError, kclErrorsToDiagnostics } from './errors'
|
||||
import { uuidv4 } from 'lib/utils'
|
||||
@ -211,9 +211,6 @@ export class KclManager {
|
||||
ast,
|
||||
engineCommandManager: this.engineCommandManager,
|
||||
})
|
||||
|
||||
editorManager.addDiagnostics(await lintAst({ ast: ast }))
|
||||
|
||||
sceneInfra.modelingSend({ type: 'code edit during sketch' })
|
||||
defaultSelectionFilter(programMemory, this.engineCommandManager)
|
||||
|
||||
@ -264,10 +261,7 @@ export class KclManager {
|
||||
return
|
||||
}
|
||||
const newAst = this.safeParse(newCode)
|
||||
if (!newAst) {
|
||||
this.clearAst()
|
||||
return
|
||||
}
|
||||
if (!newAst) return
|
||||
codeManager.updateCodeEditor(newCode)
|
||||
// Write the file to disk.
|
||||
await codeManager.writeToFile()
|
||||
@ -284,9 +278,6 @@ export class KclManager {
|
||||
engineCommandManager: this.engineCommandManager,
|
||||
useFakeExecutor: true,
|
||||
})
|
||||
|
||||
editorManager.addDiagnostics(await lintAst({ ast: ast }))
|
||||
|
||||
this._logs = logs
|
||||
this._kclErrors = errors
|
||||
this._programMemory = programMemory
|
||||
|
@ -502,10 +502,11 @@ describe('testing pipe operator special', () => {
|
||||
},
|
||||
{ type: 'PipeSubstitution', start: 82, end: 83 },
|
||||
{
|
||||
type: 'TagDeclarator',
|
||||
type: 'Literal',
|
||||
start: 85,
|
||||
end: 93,
|
||||
value: 'myPath',
|
||||
raw: '"myPath"',
|
||||
},
|
||||
],
|
||||
optional: false,
|
||||
@ -1656,10 +1657,11 @@ describe('should recognise callExpresions in binaryExpressions', () => {
|
||||
callee: { type: 'Identifier', start: 8, end: 15, name: 'segEndX' },
|
||||
arguments: [
|
||||
{
|
||||
type: 'Identifier',
|
||||
type: 'Literal',
|
||||
start: 16,
|
||||
end: 23,
|
||||
name: 'seg02',
|
||||
value: 'seg02',
|
||||
raw: "'seg02'",
|
||||
},
|
||||
{ type: 'PipeSubstitution', start: 25, end: 26 },
|
||||
],
|
||||
|
@ -128,7 +128,7 @@ const mySketch001 = startSketchOn('XY')
|
||||
const sk1 = startSketchOn('XY')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> lineTo([-2.5, 0], %)
|
||||
|> lineTo([0, 10], %, $p)
|
||||
|> lineTo([0, 10], %, "p")
|
||||
|> lineTo([2.5, 0], %)
|
||||
// |> rx(45, %)
|
||||
// |> translate([1,0,1], %)
|
||||
@ -138,7 +138,7 @@ const theExtrude = extrude(2, sk1)
|
||||
const sk2 = startSketchOn('XY')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> lineTo([-2.5, 0], %)
|
||||
|> lineTo([0, 3], %, $o)
|
||||
|> lineTo([0, 3], %, "p")
|
||||
|> lineTo([2.5, 0], %)
|
||||
// |> transform(theTransf, %)
|
||||
|> extrude(2, %)
|
||||
@ -163,20 +163,20 @@ const sk2 = startSketchOn('XY')
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: {
|
||||
end: 116,
|
||||
end: 117,
|
||||
start: 114,
|
||||
type: 'TagDeclarator',
|
||||
value: 'p',
|
||||
},
|
||||
id: expect.any(String),
|
||||
sourceRange: [95, 117],
|
||||
sourceRange: [95, 118],
|
||||
},
|
||||
{
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
id: expect.any(String),
|
||||
sourceRange: [123, 142],
|
||||
sourceRange: [124, 143],
|
||||
},
|
||||
],
|
||||
sketchGroup: {
|
||||
@ -201,14 +201,14 @@ const sk2 = startSketchOn('XY')
|
||||
from: [-2.5, 0],
|
||||
to: [0, 10],
|
||||
tag: {
|
||||
end: 116,
|
||||
end: 117,
|
||||
start: 114,
|
||||
type: 'TagDeclarator',
|
||||
value: 'p',
|
||||
},
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [95, 117],
|
||||
sourceRange: [95, 118],
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -218,7 +218,7 @@ const sk2 = startSketchOn('XY')
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [123, 142],
|
||||
sourceRange: [124, 143],
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -237,26 +237,26 @@ const sk2 = startSketchOn('XY')
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
id: expect.any(String),
|
||||
sourceRange: [373, 393],
|
||||
sourceRange: [374, 394],
|
||||
},
|
||||
{
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: {
|
||||
end: 419,
|
||||
start: 417,
|
||||
end: 421,
|
||||
start: 418,
|
||||
type: 'TagDeclarator',
|
||||
value: 'o',
|
||||
value: 'p',
|
||||
},
|
||||
id: expect.any(String),
|
||||
sourceRange: [399, 420],
|
||||
sourceRange: [400, 422],
|
||||
},
|
||||
{
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
id: expect.any(String),
|
||||
sourceRange: [426, 445],
|
||||
sourceRange: [428, 447],
|
||||
},
|
||||
],
|
||||
sketchGroup: {
|
||||
@ -273,7 +273,7 @@ const sk2 = startSketchOn('XY')
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [373, 393],
|
||||
sourceRange: [374, 394],
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -281,14 +281,14 @@ const sk2 = startSketchOn('XY')
|
||||
from: [-2.5, 0],
|
||||
to: [0, 3],
|
||||
tag: {
|
||||
end: 419,
|
||||
start: 417,
|
||||
end: 421,
|
||||
start: 418,
|
||||
type: 'TagDeclarator',
|
||||
value: 'o',
|
||||
value: 'p',
|
||||
},
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [399, 420],
|
||||
sourceRange: [400, 422],
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -298,7 +298,7 @@ const sk2 = startSketchOn('XY')
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [426, 445],
|
||||
sourceRange: [428, 447],
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -306,7 +306,7 @@ const sk2 = startSketchOn('XY')
|
||||
height: 2,
|
||||
startCapId: expect.any(String),
|
||||
endCapId: expect.any(String),
|
||||
__meta: [{ sourceRange: [342, 367] }],
|
||||
__meta: [{ sourceRange: [343, 368] }],
|
||||
},
|
||||
])
|
||||
})
|
||||
|
@ -15,7 +15,6 @@ import {
|
||||
sketchOnExtrudedFace,
|
||||
deleteSegmentFromPipeExpression,
|
||||
removeSingleConstraintInfo,
|
||||
deleteFromSelection,
|
||||
} from './modifyAst'
|
||||
import { enginelessExecutor } from '../lib/testHelpers'
|
||||
import { findUsesOfTagInPipe, getNodePathFromSourceRange } from './queryAst'
|
||||
@ -164,25 +163,25 @@ describe('Testing giveSketchFnCallTag', () => {
|
||||
code,
|
||||
'line([0, 0.83], %)'
|
||||
)
|
||||
expect(newCode).toContain('line([0, 0.83], %, $seg01)')
|
||||
expect(newCode).toContain("line([0, 0.83], %, 'seg01')")
|
||||
expect(tag).toBe('seg01')
|
||||
expect(isTagExisting).toBe(false)
|
||||
})
|
||||
it('Should create a unique tag if seg01 already exists', () => {
|
||||
let _code = code.replace(
|
||||
'line([-2.57, -0.13], %)',
|
||||
'line([-2.57, -0.13], %, $seg01)'
|
||||
"line([-2.57, -0.13], %, 'seg01')"
|
||||
)
|
||||
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
|
||||
_code,
|
||||
'line([0, 0.83], %)'
|
||||
)
|
||||
expect(newCode).toContain('line([0, 0.83], %, $seg02)')
|
||||
expect(newCode).toContain("line([0, 0.83], %, 'seg02')")
|
||||
expect(tag).toBe('seg02')
|
||||
expect(isTagExisting).toBe(false)
|
||||
})
|
||||
it('Should return existing tag if it already exists', () => {
|
||||
const lineButWithTag = 'line([-2.57, -0.13], %, $butts)'
|
||||
const lineButWithTag = "line([-2.57, -0.13], %, 'butts')"
|
||||
let _code = code.replace('line([-2.57, -0.13], %)', lineButWithTag)
|
||||
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
|
||||
_code,
|
||||
@ -329,11 +328,11 @@ describe('testing sketchOnExtrudedFace', () => {
|
||||
const newCode = recast(modifiedAst)
|
||||
expect(newCode).toContain(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([3.58, 2.06], %)
|
||||
|> line([9.7, 9.19], %, $seg01)
|
||||
|> line([9.7, 9.19], %, 'seg01')
|
||||
|> line([8.62, -9.57], %)
|
||||
|> close(%)
|
||||
|> extrude(5 + 7, %)
|
||||
const sketch001 = startSketchOn(part001, seg01)`)
|
||||
const sketch001 = startSketchOn(part001, 'seg01')`)
|
||||
})
|
||||
test('it should be able to extrude on close segments', async () => {
|
||||
const code = `const part001 = startSketchOn('-XZ')
|
||||
@ -372,9 +371,9 @@ const sketch001 = startSketchOn(part001, seg01)`)
|
||||
|> startProfileAt([3.58, 2.06], %)
|
||||
|> line([9.7, 9.19], %)
|
||||
|> line([8.62, -9.57], %)
|
||||
|> close(%, $seg01)
|
||||
|> close(%, 'seg01')
|
||||
|> extrude(5 + 7, %)
|
||||
const sketch001 = startSketchOn(part001, seg01)`)
|
||||
const sketch001 = startSketchOn(part001, 'seg01')`)
|
||||
})
|
||||
test('it should be able to extrude on start-end caps', async () => {
|
||||
const code = `const part001 = startSketchOn('-XZ')
|
||||
@ -458,7 +457,7 @@ const sketch001 = startSketchOn(part001, 'END')`)
|
||||
if (err(updatedAst)) throw updatedAst
|
||||
const newCode = recast(updatedAst.modifiedAst)
|
||||
expect(newCode).toContain(`const part001 = extrude(5 + 7, sketch001)
|
||||
const sketch002 = startSketchOn(part001, seg01)`)
|
||||
const sketch002 = startSketchOn(part001, 'seg01')`)
|
||||
})
|
||||
})
|
||||
|
||||
@ -500,49 +499,49 @@ describe('Testing deleteSegmentFromPipeExpression', () => {
|
||||
replace2 = ''
|
||||
) => `const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([54.78, -95.91], %)
|
||||
|> line([306.21, 198.82], %, $b)
|
||||
|> line([306.21, 198.82], %, 'b')
|
||||
${!replace1 ? ` |> ${line}\n` : ''} |> angledLine([-65, ${
|
||||
!replace1 ? 'segLen(a, %)' : replace1
|
||||
!replace1 ? "segLen('a', %)" : replace1
|
||||
}], %)
|
||||
|> line([306.21, 198.87], %)
|
||||
|> angledLine([65, ${!replace2 ? 'segAng(a, %)' : replace2}], %)
|
||||
|> angledLine([65, ${!replace2 ? "segAng('a', %)" : replace2}], %)
|
||||
|> line([-963.39, -154.67], %)
|
||||
`
|
||||
test.each([
|
||||
['line', 'line([306.21, 198.85], %, $a)', ['365.11', '33']],
|
||||
['lineTo', 'lineTo([306.21, 198.85], %, $a)', ['110.48', '119.73']],
|
||||
['yLine', 'yLine(198.85, %, $a)', ['198.85', '90']],
|
||||
['xLine', 'xLine(198.85, %, $a)', ['198.85', '0']],
|
||||
['yLineTo', 'yLineTo(198.85, %, $a)', ['95.94', '90']],
|
||||
['xLineTo', 'xLineTo(198.85, %, $a)', ['162.14', '180']],
|
||||
['line', "line([306.21, 198.85], %, 'a')", ['365.11', '33']],
|
||||
['lineTo', "lineTo([306.21, 198.85], %, 'a')", ['110.48', '119.73']],
|
||||
['yLine', "yLine(198.85, %, 'a')", ['198.85', '90']],
|
||||
['xLine', "xLine(198.85, %, 'a')", ['198.85', '0']],
|
||||
['yLineTo', "yLineTo(198.85, %, 'a')", ['95.94', '90']],
|
||||
['xLineTo', "xLineTo(198.85, %, 'a')", ['162.14', '180']],
|
||||
[
|
||||
'angledLine',
|
||||
'angledLine({ angle: 45.5, length: 198.85 }, %, $a)',
|
||||
"angledLine({ angle: 45.5, length: 198.85 }, %, 'a')",
|
||||
['198.85', '45.5'],
|
||||
],
|
||||
[
|
||||
'angledLineOfXLength',
|
||||
'angledLineOfXLength({ angle: 45.5, length: 198.85 }, %, $a)',
|
||||
"angledLineOfXLength({ angle: 45.5, length: 198.85 }, %, 'a')",
|
||||
['283.7', '45.5'],
|
||||
],
|
||||
[
|
||||
'angledLineOfYLength',
|
||||
'angledLineOfYLength({ angle: 45.5, length: 198.85 }, %, $a)',
|
||||
"angledLineOfYLength({ angle: 45.5, length: 198.85 }, %, 'a')",
|
||||
['278.79', '45.5'],
|
||||
],
|
||||
[
|
||||
'angledLineToX',
|
||||
'angledLineToX({ angle: 45.5, to: 198.85 }, %, $a)',
|
||||
"angledLineToX({ angle: 45.5, to: 198.85 }, %, 'a')",
|
||||
['231.33', '134.5'],
|
||||
],
|
||||
[
|
||||
'angledLineToY',
|
||||
'angledLineToY({ angle: 45.5, to: 198.85 }, %, $a)',
|
||||
"angledLineToY({ angle: 45.5, to: 198.85 }, %, 'a')",
|
||||
['134.51', '45.5'],
|
||||
],
|
||||
[
|
||||
'angledLineThatIntersects',
|
||||
`angledLineThatIntersects({ angle: 45.5, intersectTag: b, offset: 198.85 }, %, $a)`,
|
||||
`angledLineThatIntersects({ angle: 45.5, intersectTag: 'b', offset: 198.85 }, %, 'a')`,
|
||||
['918.4', '45.5'],
|
||||
],
|
||||
])(`%s`, async (_, line, [replace1, replace2]) => {
|
||||
@ -580,7 +579,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
||||
|> lineTo([6.14 + 0, 3.14 + 0], %)
|
||||
|> xLineTo(8 + 0, %)
|
||||
|> yLineTo(5 + 0, %)
|
||||
|> yLine(3.14 + 0, %, $a)
|
||||
|> yLine(3.14 + 0, %, 'a')
|
||||
|> xLine(3.14 + 0, %)
|
||||
|> angledLineOfXLength({ angle: 3 + 0, length: 3.14 + 0 }, %)
|
||||
|> angledLineOfYLength({ angle: 30 + 0, length: 3 + 0 }, %)
|
||||
@ -588,7 +587,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
||||
|> angledLineToY({ angle: 30 + 0, to: 10.14 + 0 }, %)
|
||||
|> angledLineThatIntersects({
|
||||
angle: 3.14 + 0,
|
||||
intersectTag: a,
|
||||
intersectTag: 'a',
|
||||
offset: 0 + 0
|
||||
}, %)
|
||||
|> tangentialArcTo([3.14 + 0, 13.14 + 0], %)`
|
||||
@ -602,7 +601,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
||||
['lineTo([6.14, 3.14 + 0], %)', 'arrayIndex', 0],
|
||||
['xLineTo(8, %)', '', ''],
|
||||
['yLineTo(5, %)', '', ''],
|
||||
['yLine(3.14, %, $a)', '', ''],
|
||||
["yLine(3.14, %, 'a')", '', ''],
|
||||
['xLine(3.14, %)', '', ''],
|
||||
[
|
||||
'angledLineOfXLength({ angle: 3, length: 3.14 + 0 }, %)',
|
||||
@ -628,7 +627,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
||||
`angledLineThatIntersects({
|
||||
angle: 3.14 + 0,
|
||||
offset: 0,
|
||||
intersectTag: a
|
||||
intersectTag: 'a'
|
||||
}, %)`,
|
||||
'objectProperty',
|
||||
'offset',
|
||||
@ -697,196 +696,3 @@ describe('Testing removeSingleConstraintInfo', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Testing deleteFromSelection', () => {
|
||||
const cases = [
|
||||
[
|
||||
'basicCase',
|
||||
{
|
||||
codeBefore: `const myVar = 5
|
||||
const sketch003 = startSketchOn('XZ')
|
||||
|> startProfileAt([3.82, 13.6], %)
|
||||
|> line([-2.94, 2.7], %)
|
||||
|> line([7.7, 0.16], %)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)`,
|
||||
codeAfter: `const myVar = 5\n`,
|
||||
lineOfInterest: 'line([-2.94, 2.7], %)',
|
||||
type: 'default',
|
||||
},
|
||||
],
|
||||
[
|
||||
'delete extrude',
|
||||
{
|
||||
codeBefore: `const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([3.29, 7.86], %)
|
||||
|> line([2.48, 2.44], %)
|
||||
|> line([2.66, 1.17], %)
|
||||
|> line([3.75, 0.46], %)
|
||||
|> line([4.99, -0.46], %, $seg01)
|
||||
|> line([-3.86, -2.73], %)
|
||||
|> line([-17.67, 0.85], %)
|
||||
|> close(%)
|
||||
const extrude001 = extrude(10, sketch001)`,
|
||||
codeAfter: `const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([3.29, 7.86], %)
|
||||
|> line([2.48, 2.44], %)
|
||||
|> line([2.66, 1.17], %)
|
||||
|> line([3.75, 0.46], %)
|
||||
|> line([4.99, -0.46], %, $seg01)
|
||||
|> line([-3.86, -2.73], %)
|
||||
|> line([-17.67, 0.85], %)
|
||||
|> close(%)\n`,
|
||||
lineOfInterest: 'line([2.66, 1.17], %)',
|
||||
type: 'extrude-wall',
|
||||
},
|
||||
],
|
||||
[
|
||||
'delete extrude with sketch on it',
|
||||
{
|
||||
codeBefore: `const myVar = 5
|
||||
const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([4.46, 5.12], %, $tag)
|
||||
|> line([0.08, myVar], %)
|
||||
|> line([13.03, 2.02], %, $seg01)
|
||||
|> line([3.9, -7.6], %)
|
||||
|> line([-11.18, -2.15], %)
|
||||
|> line([5.41, -9.61], %)
|
||||
|> line([-8.54, -2.51], %)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)
|
||||
const extrude001 = extrude(5, sketch001)
|
||||
const sketch002 = startSketchOn(extrude001, seg01)
|
||||
|> startProfileAt([-12.55, 2.89], %)
|
||||
|> line([3.02, 1.9], %)
|
||||
|> line([1.82, -1.49], %, $seg02)
|
||||
|> angledLine([-86, segLen(seg02, %)], %)
|
||||
|> line([-3.97, -0.53], %)
|
||||
|> line([0.3, 0.84], %)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)`,
|
||||
codeAfter: `const myVar = 5
|
||||
const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([4.46, 5.12], %, $tag)
|
||||
|> line([0.08, myVar], %)
|
||||
|> line([13.03, 2.02], %, $seg01)
|
||||
|> line([3.9, -7.6], %)
|
||||
|> line([-11.18, -2.15], %)
|
||||
|> line([5.41, -9.61], %)
|
||||
|> line([-8.54, -2.51], %)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)
|
||||
const sketch002 = startSketchOn({
|
||||
plane: {
|
||||
origin: { x: 1, y: 2, z: 3 },
|
||||
x_axis: { x: 4, y: 5, z: 6 },
|
||||
y_axis: { x: 7, y: 8, z: 9 },
|
||||
z_axis: { x: 10, y: 11, z: 12 }
|
||||
}
|
||||
})
|
||||
|> startProfileAt([-12.55, 2.89], %)
|
||||
|> line([3.02, 1.9], %)
|
||||
|> line([1.82, -1.49], %, $seg02)
|
||||
|> angledLine([-86, segLen(seg02, %)], %)
|
||||
|> line([-3.97, -0.53], %)
|
||||
|> line([0.3, 0.84], %)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)
|
||||
`,
|
||||
lineOfInterest: 'line([-11.18, -2.15], %)',
|
||||
type: 'extrude-wall',
|
||||
},
|
||||
],
|
||||
[
|
||||
'delete extrude with sketch on it',
|
||||
{
|
||||
codeBefore: `const myVar = 5
|
||||
const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([4.46, 5.12], %, $tag)
|
||||
|> line([0.08, myVar], %)
|
||||
|> line([13.03, 2.02], %, $seg01)
|
||||
|> line([3.9, -7.6], %)
|
||||
|> line([-11.18, -2.15], %)
|
||||
|> line([5.41, -9.61], %)
|
||||
|> line([-8.54, -2.51], %)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)
|
||||
const extrude001 = extrude(5, sketch001)
|
||||
const sketch002 = startSketchOn(extrude001, seg01)
|
||||
|> startProfileAt([-12.55, 2.89], %)
|
||||
|> line([3.02, 1.9], %)
|
||||
|> line([1.82, -1.49], %, $seg02)
|
||||
|> angledLine([-86, segLen(seg02, %)], %)
|
||||
|> line([-3.97, -0.53], %)
|
||||
|> line([0.3, 0.84], %)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)`,
|
||||
codeAfter: `const myVar = 5
|
||||
const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([4.46, 5.12], %, $tag)
|
||||
|> line([0.08, myVar], %)
|
||||
|> line([13.03, 2.02], %, $seg01)
|
||||
|> line([3.9, -7.6], %)
|
||||
|> line([-11.18, -2.15], %)
|
||||
|> line([5.41, -9.61], %)
|
||||
|> line([-8.54, -2.51], %)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)
|
||||
const sketch002 = startSketchOn({
|
||||
plane: {
|
||||
origin: { x: 1, y: 2, z: 3 },
|
||||
x_axis: { x: 4, y: 5, z: 6 },
|
||||
y_axis: { x: 7, y: 8, z: 9 },
|
||||
z_axis: { x: 10, y: 11, z: 12 }
|
||||
}
|
||||
})
|
||||
|> startProfileAt([-12.55, 2.89], %)
|
||||
|> line([3.02, 1.9], %)
|
||||
|> line([1.82, -1.49], %, $seg02)
|
||||
|> angledLine([-86, segLen(seg02, %)], %)
|
||||
|> line([-3.97, -0.53], %)
|
||||
|> line([0.3, 0.84], %)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)
|
||||
`,
|
||||
lineOfInterest: 'startProfileAt([4.46, 5.12], %, $tag)',
|
||||
type: 'end-cap',
|
||||
},
|
||||
],
|
||||
] as const
|
||||
test.each(cases)(
|
||||
'%s',
|
||||
async (name, { codeBefore, codeAfter, lineOfInterest, type }) => {
|
||||
// const lineOfInterest = 'line([-2.94, 2.7], %)'
|
||||
const ast = parse(codeBefore)
|
||||
if (err(ast)) throw ast
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
|
||||
// deleteFromSelection
|
||||
const range: [number, number] = [
|
||||
codeBefore.indexOf(lineOfInterest),
|
||||
codeBefore.indexOf(lineOfInterest) + lineOfInterest.length,
|
||||
]
|
||||
const newAst = await deleteFromSelection(
|
||||
ast,
|
||||
{
|
||||
range,
|
||||
type,
|
||||
},
|
||||
programMemory,
|
||||
async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100))
|
||||
return {
|
||||
origin: { x: 1, y: 2, z: 3 },
|
||||
x_axis: { x: 4, y: 5, z: 6 },
|
||||
y_axis: { x: 7, y: 8, z: 9 },
|
||||
z_axis: { x: 10, y: 11, z: 12 },
|
||||
}
|
||||
}
|
||||
)
|
||||
if (err(newAst)) throw newAst
|
||||
const newCode = recast(newAst)
|
||||
expect(newCode).toBe(codeAfter)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
@ -17,7 +17,6 @@ import {
|
||||
PathToNode,
|
||||
ProgramMemory,
|
||||
SourceRange,
|
||||
SketchGroup,
|
||||
} from './wasm'
|
||||
import {
|
||||
isNodeSafeToReplacePath,
|
||||
@ -26,7 +25,6 @@ import {
|
||||
getNodeFromPath,
|
||||
getNodePathFromSourceRange,
|
||||
isNodeSafeToReplace,
|
||||
traverse,
|
||||
} from './queryAst'
|
||||
import { addTagForSketchOnFace, getConstraintInfo } from './std/sketch'
|
||||
import {
|
||||
@ -39,8 +37,6 @@ import { DefaultPlaneStr } from 'clientSideScene/sceneEntities'
|
||||
import { isOverlap, roundOff } from 'lib/utils'
|
||||
import { KCL_DEFAULT_CONSTANT_PREFIXES } from 'lib/constants'
|
||||
import { ConstrainInfo } from './std/stdTypes'
|
||||
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
|
||||
import { Models } from '@kittycad/lib'
|
||||
|
||||
export function startSketchOnDefault(
|
||||
node: Program,
|
||||
@ -383,7 +379,7 @@ export function sketchOnExtrudedFace(
|
||||
const { node: extrudeVarDec } = _node3
|
||||
const extrudeName = extrudeVarDec.id?.name
|
||||
|
||||
let _tag = null
|
||||
let _tag = ''
|
||||
if (cap === 'none') {
|
||||
const __tag = addTagForSketchOnFace(
|
||||
{
|
||||
@ -395,17 +391,17 @@ export function sketchOnExtrudedFace(
|
||||
)
|
||||
if (err(__tag)) return __tag
|
||||
const { modifiedAst, tag } = __tag
|
||||
_tag = createIdentifier(tag)
|
||||
_tag = tag
|
||||
_node = modifiedAst
|
||||
} else {
|
||||
_tag = createLiteral(cap.toUpperCase())
|
||||
_tag = cap.toUpperCase()
|
||||
}
|
||||
|
||||
const newSketch = createVariableDeclaration(
|
||||
newSketchName,
|
||||
createCallExpressionStdLib('startSketchOn', [
|
||||
createIdentifier(extrudeName ? extrudeName : oldSketchName),
|
||||
_tag,
|
||||
createLiteral(_tag),
|
||||
]),
|
||||
'const'
|
||||
)
|
||||
@ -487,15 +483,6 @@ export function createLiteral(value: string | number): Literal {
|
||||
}
|
||||
}
|
||||
|
||||
export function createTagDeclarator(value: string): TagDeclarator {
|
||||
return {
|
||||
type: 'TagDeclarator',
|
||||
start: 0,
|
||||
end: 0,
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
||||
export function createIdentifier(name: string): Identifier {
|
||||
return {
|
||||
type: 'Identifier',
|
||||
@ -670,18 +657,17 @@ export function giveSketchFnCallTag(
|
||||
// Tag is always 3rd expression now, using arg index feels brittle
|
||||
// but we can come up with a better way to identify tag later.
|
||||
const thirdArg = primaryCallExp.arguments?.[2]
|
||||
const tagDeclarator =
|
||||
thirdArg ||
|
||||
(createTagDeclarator(tag || findUniqueName(ast, 'seg', 2)) as TagDeclarator)
|
||||
const tagLiteral =
|
||||
thirdArg || (createLiteral(tag || findUniqueName(ast, 'seg', 2)) as Literal)
|
||||
const isTagExisting = !!thirdArg
|
||||
if (!isTagExisting) {
|
||||
primaryCallExp.arguments[2] = tagDeclarator
|
||||
primaryCallExp.arguments[2] = tagLiteral
|
||||
}
|
||||
if ('value' in tagDeclarator) {
|
||||
// Now TypeScript knows tagDeclarator has a value property
|
||||
if ('value' in tagLiteral) {
|
||||
// Now TypeScript knows tagLiteral has a value property
|
||||
return {
|
||||
modifiedAst: ast,
|
||||
tag: String(tagDeclarator.value),
|
||||
tag: String(tagLiteral.value),
|
||||
isTagExisting,
|
||||
pathToNode: path,
|
||||
}
|
||||
@ -710,7 +696,7 @@ export function moveValueIntoNewVariablePath(
|
||||
programMemory,
|
||||
pathToNode
|
||||
)
|
||||
let _node = ast
|
||||
let _node = JSON.parse(JSON.stringify(ast))
|
||||
const boop = replacer(_node, variableName)
|
||||
if (trap(boop)) return { modifiedAst: ast }
|
||||
|
||||
@ -742,7 +728,7 @@ export function moveValueIntoNewVariable(
|
||||
programMemory,
|
||||
sourceRange
|
||||
)
|
||||
let _node = ast
|
||||
let _node = JSON.parse(JSON.stringify(ast))
|
||||
const replaced = replacer(_node, variableName)
|
||||
if (trap(replaced)) return { modifiedAst: ast }
|
||||
|
||||
@ -767,7 +753,7 @@ export function deleteSegmentFromPipeExpression(
|
||||
code: string,
|
||||
pathToNode: PathToNode
|
||||
): Program | Error {
|
||||
let _modifiedAst: Program = modifiedAst
|
||||
let _modifiedAst: Program = JSON.parse(JSON.stringify(modifiedAst))
|
||||
|
||||
dependentRanges.forEach((range) => {
|
||||
const path = getNodePathFromSourceRange(_modifiedAst, range)
|
||||
@ -876,175 +862,3 @@ export function removeSingleConstraintInfo(
|
||||
if (err(retval)) return false
|
||||
return retval
|
||||
}
|
||||
|
||||
export async function deleteFromSelection(
|
||||
ast: Program,
|
||||
selection: Selection,
|
||||
programMemory: ProgramMemory,
|
||||
getFaceDetails: (id: string) => Promise<Models['FaceIsPlanar_type']> = () =>
|
||||
({} as any)
|
||||
): Promise<Program | Error> {
|
||||
const astClone = ast
|
||||
const range = selection.range
|
||||
const path = getNodePathFromSourceRange(ast, range)
|
||||
const varDec = getNodeFromPath<VariableDeclarator>(
|
||||
ast,
|
||||
path,
|
||||
'VariableDeclarator'
|
||||
)
|
||||
if (err(varDec)) return varDec
|
||||
if (
|
||||
(selection.type === 'extrude-wall' ||
|
||||
selection.type === 'end-cap' ||
|
||||
selection.type === 'start-cap') &&
|
||||
varDec.node.init.type === 'PipeExpression'
|
||||
) {
|
||||
const varDecName = varDec.node.id.name
|
||||
let pathToNode: PathToNode | null = null
|
||||
let extrudeNameToDelete = ''
|
||||
traverse(astClone, {
|
||||
enter: (node, path) => {
|
||||
if (node.type === 'VariableDeclaration') {
|
||||
const dec = node.declarations[0]
|
||||
if (
|
||||
dec.init.type === 'CallExpression' &&
|
||||
(dec.init.callee.name === 'extrude' ||
|
||||
dec.init.callee.name === 'revolve') &&
|
||||
dec.init.arguments?.[1].type === 'Identifier' &&
|
||||
dec.init.arguments?.[1].name === varDecName
|
||||
) {
|
||||
pathToNode = path
|
||||
extrudeNameToDelete = dec.id.name
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
if (!pathToNode) return new Error('Could not find extrude variable')
|
||||
|
||||
const expressionIndex = pathToNode[1][0] as number
|
||||
astClone.body.splice(expressionIndex, 1)
|
||||
if (extrudeNameToDelete) {
|
||||
await new Promise(async (resolve) => {
|
||||
let currentVariableName = ''
|
||||
const pathsDependingOnExtrude: Array<{
|
||||
path: PathToNode
|
||||
sketchName: string
|
||||
}> = []
|
||||
traverse(astClone, {
|
||||
leave: (node) => {
|
||||
if (node.type === 'VariableDeclaration') {
|
||||
currentVariableName = ''
|
||||
}
|
||||
},
|
||||
enter: async (node, path) => {
|
||||
if (node.type === 'VariableDeclaration') {
|
||||
currentVariableName = node.declarations[0].id.name
|
||||
}
|
||||
if (
|
||||
// match startSketchOn(${extrudeNameToDelete})
|
||||
node.type === 'CallExpression' &&
|
||||
node.callee.name === 'startSketchOn' &&
|
||||
node.arguments[0].type === 'Identifier' &&
|
||||
node.arguments[0].name === extrudeNameToDelete
|
||||
) {
|
||||
pathsDependingOnExtrude.push({
|
||||
path,
|
||||
sketchName: currentVariableName,
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
const roundLiteral = (x: number) => createLiteral(roundOff(x))
|
||||
const modificationDetails: {
|
||||
parent: PipeExpression['body']
|
||||
faceDetails: Models['FaceIsPlanar_type']
|
||||
lastKey: number
|
||||
}[] = []
|
||||
for (const { path, sketchName } of pathsDependingOnExtrude) {
|
||||
const parent = getNodeFromPath<PipeExpression['body']>(
|
||||
astClone,
|
||||
path.slice(0, -1)
|
||||
)
|
||||
if (err(parent)) {
|
||||
return
|
||||
}
|
||||
const sketchToPreserve = programMemory.root[sketchName] as SketchGroup
|
||||
console.log('sketchName', sketchName)
|
||||
// Can't kick off multiple requests at once as getFaceDetails
|
||||
// is three engine calls in one and they conflict
|
||||
const faceDetails = await getFaceDetails(sketchToPreserve.on.id)
|
||||
if (
|
||||
!(
|
||||
faceDetails.origin &&
|
||||
faceDetails.x_axis &&
|
||||
faceDetails.y_axis &&
|
||||
faceDetails.z_axis
|
||||
)
|
||||
) {
|
||||
return
|
||||
}
|
||||
const lastKey = Number(path.slice(-1)[0][0])
|
||||
modificationDetails.push({
|
||||
parent: parent.node,
|
||||
faceDetails,
|
||||
lastKey,
|
||||
})
|
||||
}
|
||||
for (const { parent, faceDetails, lastKey } of modificationDetails) {
|
||||
if (
|
||||
!(
|
||||
faceDetails.origin &&
|
||||
faceDetails.x_axis &&
|
||||
faceDetails.y_axis &&
|
||||
faceDetails.z_axis
|
||||
)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
parent[lastKey] = createCallExpressionStdLib('startSketchOn', [
|
||||
createObjectExpression({
|
||||
plane: createObjectExpression({
|
||||
origin: createObjectExpression({
|
||||
x: roundLiteral(faceDetails.origin.x),
|
||||
y: roundLiteral(faceDetails.origin.y),
|
||||
z: roundLiteral(faceDetails.origin.z),
|
||||
}),
|
||||
x_axis: createObjectExpression({
|
||||
x: roundLiteral(faceDetails.x_axis.x),
|
||||
y: roundLiteral(faceDetails.x_axis.y),
|
||||
z: roundLiteral(faceDetails.x_axis.z),
|
||||
}),
|
||||
y_axis: createObjectExpression({
|
||||
x: roundLiteral(faceDetails.y_axis.x),
|
||||
y: roundLiteral(faceDetails.y_axis.y),
|
||||
z: roundLiteral(faceDetails.y_axis.z),
|
||||
}),
|
||||
z_axis: createObjectExpression({
|
||||
x: roundLiteral(faceDetails.z_axis.x),
|
||||
y: roundLiteral(faceDetails.z_axis.y),
|
||||
z: roundLiteral(faceDetails.z_axis.z),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
])
|
||||
}
|
||||
resolve(true)
|
||||
})
|
||||
}
|
||||
// await prom
|
||||
return astClone
|
||||
} else if (varDec.node.init.type === 'PipeExpression') {
|
||||
const pipeBody = varDec.node.init.body
|
||||
if (
|
||||
pipeBody[0].type === 'CallExpression' &&
|
||||
pipeBody[0].callee.name === 'startSketchOn'
|
||||
) {
|
||||
// remove varDec
|
||||
const varDecIndex = varDec.shallowPath[1][0] as number
|
||||
astClone.body.splice(varDecIndex, 1)
|
||||
return astClone
|
||||
}
|
||||
}
|
||||
|
||||
return new Error('Selection not recognised, could not delete')
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { parse, recast, initPromise, PathToNode } from './wasm'
|
||||
import { parse, recast, initPromise } from './wasm'
|
||||
import {
|
||||
findAllPreviousVariables,
|
||||
isNodeSafeToReplace,
|
||||
@ -9,7 +9,6 @@ import {
|
||||
findUsesOfTagInPipe,
|
||||
hasSketchPipeBeenExtruded,
|
||||
hasExtrudableGeometry,
|
||||
traverse,
|
||||
} from './queryAst'
|
||||
import { enginelessExecutor } from '../lib/testHelpers'
|
||||
import {
|
||||
@ -19,7 +18,6 @@ import {
|
||||
createPipeSubstitution,
|
||||
} from './modifyAst'
|
||||
import { err } from 'lib/trap'
|
||||
import { warn } from 'node:console'
|
||||
|
||||
beforeAll(async () => {
|
||||
await initPromise
|
||||
@ -87,7 +85,10 @@ const yo2 = hmm([identifierGuy + 5])`
|
||||
expect(result.isSafe).toBe(true)
|
||||
expect(result.value?.type).toBe('BinaryExpression')
|
||||
expect(code.slice(result.value.start, result.value.end)).toBe('100 + 100')
|
||||
const replaced = result.replacer(ast, 'replaceName')
|
||||
const replaced = result.replacer(
|
||||
JSON.parse(JSON.stringify(ast)),
|
||||
'replaceName'
|
||||
)
|
||||
if (err(replaced)) throw replaced
|
||||
const outCode = recast(replaced.modifiedAst)
|
||||
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
|
||||
@ -111,7 +112,10 @@ const yo2 = hmm([identifierGuy + 5])`
|
||||
expect(result.isSafe).toBe(true)
|
||||
expect(result.value?.type).toBe('CallExpression')
|
||||
expect(code.slice(result.value.start, result.value.end)).toBe("def('yo')")
|
||||
const replaced = result.replacer(ast, 'replaceName')
|
||||
const replaced = result.replacer(
|
||||
JSON.parse(JSON.stringify(ast)),
|
||||
'replaceName'
|
||||
)
|
||||
if (err(replaced)) throw replaced
|
||||
const outCode = recast(replaced.modifiedAst)
|
||||
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
|
||||
@ -148,7 +152,10 @@ const yo2 = hmm([identifierGuy + 5])`
|
||||
expect(result.isSafe).toBe(true)
|
||||
expect(result.value?.type).toBe('BinaryExpression')
|
||||
expect(code.slice(result.value.start, result.value.end)).toBe('5 + 6')
|
||||
const replaced = result.replacer(ast, 'replaceName')
|
||||
const replaced = result.replacer(
|
||||
JSON.parse(JSON.stringify(ast)),
|
||||
'replaceName'
|
||||
)
|
||||
if (err(replaced)) throw replaced
|
||||
const outCode = recast(replaced.modifiedAst)
|
||||
expect(outCode).toContain(`const yo = replaceName`)
|
||||
@ -164,7 +171,10 @@ const yo2 = hmm([identifierGuy + 5])`
|
||||
expect(code.slice(result.value.start, result.value.end)).toBe(
|
||||
"jkl('yo') + 2"
|
||||
)
|
||||
const replaced = result.replacer(ast, 'replaceName')
|
||||
const replaced = result.replacer(
|
||||
JSON.parse(JSON.stringify(ast)),
|
||||
'replaceName'
|
||||
)
|
||||
if (err(replaced)) throw replaced
|
||||
const { modifiedAst } = replaced
|
||||
const outCode = recast(modifiedAst)
|
||||
@ -183,7 +193,10 @@ const yo2 = hmm([identifierGuy + 5])`
|
||||
expect(code.slice(result.value.start, result.value.end)).toBe(
|
||||
'identifierGuy + 5'
|
||||
)
|
||||
const replaced = result.replacer(ast, 'replaceName')
|
||||
const replaced = result.replacer(
|
||||
JSON.parse(JSON.stringify(ast)),
|
||||
'replaceName'
|
||||
)
|
||||
if (err(replaced)) throw replaced
|
||||
const { modifiedAst } = replaced
|
||||
const outCode = recast(modifiedAst)
|
||||
@ -398,15 +411,15 @@ describe('Testing findUsesOfTagInPipe', () => {
|
||||
const exampleCode = `const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([68.12, 156.65], %)
|
||||
|> line([306.21, 198.82], %)
|
||||
|> line([306.21, 198.85], %, $seg01)
|
||||
|> angledLine([-65, segLen(seg01, %)], %)
|
||||
|> line([306.21, 198.85], %, 'seg01')
|
||||
|> angledLine([-65, segLen('seg01', %)], %)
|
||||
|> line([306.21, 198.87], %)
|
||||
|> angledLine([65, segLen(seg01, %)], %)`
|
||||
|> angledLine([65, segLen('seg01', %)], %)`
|
||||
it('finds the current segment', async () => {
|
||||
const ast = parse(exampleCode)
|
||||
if (err(ast)) throw ast
|
||||
|
||||
const lineOfInterest = `198.85], %, $seg01`
|
||||
const lineOfInterest = `198.85], %, 'seg01'`
|
||||
const characterIndex =
|
||||
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
|
||||
const pathToNode = getNodePathFromSourceRange(ast, [
|
||||
@ -441,7 +454,7 @@ describe('Testing hasSketchPipeBeenExtruded', () => {
|
||||
|> line([2.48, 2.44], %)
|
||||
|> line([2.66, 1.17], %)
|
||||
|> line([3.75, 0.46], %)
|
||||
|> line([4.99, -0.46], %, $seg01)
|
||||
|> line([4.99, -0.46], %, 'seg01')
|
||||
|> line([3.3, -2.12], %)
|
||||
|> line([2.16, -3.33], %)
|
||||
|> line([0.85, -3.08], %)
|
||||
@ -450,7 +463,7 @@ describe('Testing hasSketchPipeBeenExtruded', () => {
|
||||
|> line([-17.67, 0.85], %)
|
||||
|> close(%)
|
||||
const extrude001 = extrude(10, sketch001)
|
||||
const sketch002 = startSketchOn(extrude001, $seg01)
|
||||
const sketch002 = startSketchOn(extrude001, 'seg01')
|
||||
|> startProfileAt([-12.94, 6.6], %)
|
||||
|> line([2.45, -0.2], %)
|
||||
|> line([-2, -1.25], %)
|
||||
@ -460,7 +473,7 @@ const sketch002 = startSketchOn(extrude001, $seg01)
|
||||
it('finds sketch001 pipe to be extruded', async () => {
|
||||
const ast = parse(exampleCode)
|
||||
if (err(ast)) throw ast
|
||||
const lineOfInterest = `line([4.99, -0.46], %, $seg01)`
|
||||
const lineOfInterest = `line([4.99, -0.46], %, 'seg01')`
|
||||
const characterIndex =
|
||||
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
|
||||
const extruded = hasSketchPipeBeenExtruded(
|
||||
@ -498,7 +511,7 @@ describe('Testing hasExtrudableGeometry', () => {
|
||||
|> line([-17.67, 0.85], %)
|
||||
|> close(%)
|
||||
const extrude001 = extrude(10, sketch001)
|
||||
const sketch002 = startSketchOn(extrude001, $seg01)
|
||||
const sketch002 = startSketchOn(extrude001, 'seg01')
|
||||
|> startProfileAt([-12.94, 6.6], %)
|
||||
|> line([2.45, -0.2], %)
|
||||
|> line([-2, -1.25], %)
|
||||
@ -525,53 +538,3 @@ const extrude001 = extrude(10, sketch001)
|
||||
expect(extrudable).toBeFalsy()
|
||||
})
|
||||
})
|
||||
|
||||
describe('Testing traverse and pathToNode', () => {
|
||||
it.each([
|
||||
['basic', '2.73'],
|
||||
[
|
||||
'very nested, array, object, callExpression, array, memberExpression',
|
||||
'.yo',
|
||||
],
|
||||
])('testing %s', async (testName, literalOfInterest) => {
|
||||
const code = `const myVar = 5
|
||||
const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([3.29, 7.86], %)
|
||||
|> line([2.48, 2.44], %)
|
||||
|> line([-3.86, -2.73], %)
|
||||
|> line([-17.67, 0.85], %)
|
||||
|> close(%)
|
||||
const bing = { yo: 55 }
|
||||
const myNestedVar = [
|
||||
{
|
||||
prop: line([bing.yo, 21], sketch001)
|
||||
}
|
||||
]
|
||||
`
|
||||
const ast = parse(code)
|
||||
if (err(ast)) throw ast
|
||||
let pathToNode: PathToNode = []
|
||||
traverse(ast, {
|
||||
enter: (node, path) => {
|
||||
if (
|
||||
node.type === 'Literal' &&
|
||||
String(node.value) === literalOfInterest
|
||||
) {
|
||||
pathToNode = path
|
||||
} else if (
|
||||
node.type === 'Identifier' &&
|
||||
literalOfInterest.includes(node.name)
|
||||
) {
|
||||
pathToNode = path
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const literalIndex = code.indexOf(literalOfInterest)
|
||||
const pathToNode2 = getNodePathFromSourceRange(ast, [
|
||||
literalIndex + 2,
|
||||
literalIndex + 2,
|
||||
])
|
||||
expect(pathToNode).toEqual(pathToNode2)
|
||||
})
|
||||
})
|
||||
|
@ -270,18 +270,6 @@ function moreNodePathFromSourceRange(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_node.type === 'MemberExpression' && isInRange) {
|
||||
const { object, property } = _node
|
||||
if (object.start <= start && object.end >= end) {
|
||||
path.push(['object', 'MemberExpression'])
|
||||
return moreNodePathFromSourceRange(object, sourceRange, path)
|
||||
}
|
||||
if (property.start <= start && property.end >= end) {
|
||||
path.push(['property', 'MemberExpression'])
|
||||
return moreNodePathFromSourceRange(property, sourceRange, path)
|
||||
}
|
||||
return path
|
||||
}
|
||||
if (_node.type === 'PipeSubstitution' && isInRange) return path
|
||||
console.error('not implemented: ' + node.type)
|
||||
return path
|
||||
@ -319,89 +307,48 @@ type KCLNode =
|
||||
| ReturnStatement
|
||||
|
||||
export function traverse(
|
||||
node: KCLNode | Program,
|
||||
node: KCLNode,
|
||||
option: {
|
||||
enter?: (node: KCLNode, pathToNode: PathToNode) => void
|
||||
enter?: (node: KCLNode) => void
|
||||
leave?: (node: KCLNode) => void
|
||||
},
|
||||
pathToNode: PathToNode = []
|
||||
) {
|
||||
const _node = node as KCLNode
|
||||
option?.enter?.(_node, pathToNode)
|
||||
const _traverse = (node: KCLNode, pathToNode: PathToNode) =>
|
||||
traverse(node, option, pathToNode)
|
||||
|
||||
if (_node.type === 'VariableDeclaration') {
|
||||
_node.declarations.forEach((declaration, index) =>
|
||||
_traverse(declaration, [
|
||||
...pathToNode,
|
||||
['declarations', 'VariableDeclaration'],
|
||||
[index, 'index'],
|
||||
])
|
||||
)
|
||||
} else if (_node.type === 'VariableDeclarator') {
|
||||
_traverse(_node.init, [...pathToNode, ['init', '']])
|
||||
} else if (_node.type === 'PipeExpression') {
|
||||
_node.body.forEach((expression, index) =>
|
||||
_traverse(expression, [
|
||||
...pathToNode,
|
||||
['body', 'PipeExpression'],
|
||||
[index, 'index'],
|
||||
])
|
||||
)
|
||||
} else if (_node.type === 'CallExpression') {
|
||||
_traverse(_node.callee, [...pathToNode, ['callee', 'CallExpression']])
|
||||
_node.arguments.forEach((arg, index) =>
|
||||
_traverse(arg, [
|
||||
...pathToNode,
|
||||
['arguments', 'CallExpression'],
|
||||
[index, 'index'],
|
||||
])
|
||||
)
|
||||
} else if (_node.type === 'BinaryExpression') {
|
||||
_traverse(_node.left, [...pathToNode, ['left', 'BinaryExpression']])
|
||||
_traverse(_node.right, [...pathToNode, ['right', 'BinaryExpression']])
|
||||
} else if (_node.type === 'Identifier') {
|
||||
// do nothing
|
||||
} else if (_node.type === 'Literal') {
|
||||
// do nothing
|
||||
} else if (_node.type === 'TagDeclarator') {
|
||||
// do nothing
|
||||
} else if (_node.type === 'ArrayExpression') {
|
||||
_node.elements.forEach((el, index) =>
|
||||
_traverse(el, [
|
||||
...pathToNode,
|
||||
['elements', 'ArrayExpression'],
|
||||
[index, 'index'],
|
||||
])
|
||||
)
|
||||
} else if (_node.type === 'ObjectExpression') {
|
||||
_node.properties.forEach(({ key, value }, index) => {
|
||||
_traverse(key, [
|
||||
...pathToNode,
|
||||
['properties', 'ObjectExpression'],
|
||||
[index, 'index'],
|
||||
['key', 'Property'],
|
||||
])
|
||||
_traverse(value, [
|
||||
...pathToNode,
|
||||
['properties', 'ObjectExpression'],
|
||||
[index, 'index'],
|
||||
['value', 'Property'],
|
||||
])
|
||||
})
|
||||
} else if (_node.type === 'UnaryExpression') {
|
||||
_traverse(_node.argument, [...pathToNode, ['argument', 'UnaryExpression']])
|
||||
} else if (_node.type === 'MemberExpression') {
|
||||
// hmm this smell
|
||||
_traverse(_node.object, [...pathToNode, ['object', 'MemberExpression']])
|
||||
_traverse(_node.property, [...pathToNode, ['property', 'MemberExpression']])
|
||||
} else if ('body' in _node && Array.isArray(_node.body)) {
|
||||
_node.body.forEach((expression, index) =>
|
||||
_traverse(expression, [...pathToNode, ['body', ''], [index, 'index']])
|
||||
)
|
||||
}
|
||||
option?.leave?.(_node)
|
||||
) {
|
||||
option?.enter?.(node)
|
||||
const _traverse = (node: KCLNode) => traverse(node, option)
|
||||
|
||||
if (node.type === 'VariableDeclaration') {
|
||||
node.declarations.forEach(_traverse)
|
||||
} else if (node.type === 'VariableDeclarator') {
|
||||
_traverse(node.init)
|
||||
} else if (node.type === 'PipeExpression') {
|
||||
node.body.forEach(_traverse)
|
||||
} else if (node.type === 'CallExpression') {
|
||||
_traverse(node.callee)
|
||||
node.arguments.forEach(_traverse)
|
||||
} else if (node.type === 'BinaryExpression') {
|
||||
_traverse(node.left)
|
||||
_traverse(node.right)
|
||||
} else if (node.type === 'Identifier') {
|
||||
// do nothing
|
||||
} else if (node.type === 'Literal') {
|
||||
// do nothing
|
||||
} else if (node.type === 'ArrayExpression') {
|
||||
node.elements.forEach(_traverse)
|
||||
} else if (node.type === 'ObjectExpression') {
|
||||
node.properties.forEach(({ key, value }) => {
|
||||
_traverse(key)
|
||||
_traverse(value)
|
||||
})
|
||||
} else if (node.type === 'UnaryExpression') {
|
||||
_traverse(node.argument)
|
||||
} else if (node.type === 'MemberExpression') {
|
||||
// hmm this smell
|
||||
_traverse(node.object)
|
||||
_traverse(node.property)
|
||||
} else if ('body' in node && Array.isArray(node.body)) {
|
||||
node.body.forEach(_traverse)
|
||||
}
|
||||
option?.leave?.(node)
|
||||
}
|
||||
|
||||
export interface PrevVariable<T> {
|
||||
@ -520,8 +467,8 @@ export function isNodeSafeToReplacePath(
|
||||
const replaceNodeWithIdentifier: ReplacerFn = (_ast, varName) => {
|
||||
const identifier = createIdentifier(varName)
|
||||
const last = finPath[finPath.length - 1]
|
||||
const pathToReplaced = finPath
|
||||
pathToReplaced[1][0] = (pathToReplaced[1][0] as number) + 1
|
||||
const pathToReplaced = JSON.parse(JSON.stringify(finPath))
|
||||
pathToReplaced[1][0] = pathToReplaced[1][0] + 1
|
||||
const startPath = finPath.slice(0, -1)
|
||||
const _nodeToReplace = getNodeFromPath(_ast, startPath)
|
||||
if (err(_nodeToReplace)) return _nodeToReplace
|
||||
@ -787,14 +734,8 @@ export function findUsesOfTagInPipe(
|
||||
if (node.type !== 'CallExpression') return []
|
||||
const tagIndex = node.callee.name === 'close' ? 1 : 2
|
||||
const thirdParam = node.arguments[tagIndex]
|
||||
if (
|
||||
!(thirdParam?.type === 'TagDeclarator' || thirdParam?.type === 'Identifier')
|
||||
)
|
||||
return []
|
||||
const tag =
|
||||
thirdParam?.type === 'TagDeclarator'
|
||||
? String(thirdParam.value)
|
||||
: thirdParam.name
|
||||
if (thirdParam?.type !== 'Literal') return []
|
||||
const tag = String(thirdParam.value)
|
||||
|
||||
const varDec = getNodeFromPath<VariableDeclaration>(
|
||||
ast,
|
||||
@ -815,11 +756,9 @@ export function findUsesOfTagInPipe(
|
||||
)
|
||||
return
|
||||
const tagArg = node.arguments[0]
|
||||
if (!(tagArg.type === 'TagDeclarator' || tagArg.type === 'Identifier'))
|
||||
return
|
||||
const tagArgValue =
|
||||
tagArg.type === 'TagDeclarator' ? String(tagArg.value) : tagArg.name
|
||||
if (tagArgValue === tag) dependentRanges.push([node.start, node.end])
|
||||
if (tagArg.type !== 'Literal') return
|
||||
if (String(tagArg.value) === tag)
|
||||
dependentRanges.push([node.start, node.end])
|
||||
},
|
||||
})
|
||||
return dependentRanges
|
||||
|
@ -76,9 +76,9 @@ log(5, myVar)
|
||||
})
|
||||
it('recast sketch declaration', () => {
|
||||
let code = `const mySketch = startSketchAt([0, 0])
|
||||
|> lineTo([0, 1], %, $myPath)
|
||||
|> lineTo([0, 1], %, "myPath")
|
||||
|> lineTo([1, 1], %)
|
||||
|> lineTo([1, 0], %, $rightPath)
|
||||
|> lineTo([1, 0], %, "rightPath")
|
||||
|> close(%)
|
||||
`
|
||||
const { ast } = code2ast(code)
|
||||
@ -90,7 +90,7 @@ log(5, myVar)
|
||||
const code = [
|
||||
'const mySk1 = startSketchAt([0, 0])',
|
||||
' |> lineTo([1, 1], %)',
|
||||
' |> lineTo([0, 1], %, $myTag)',
|
||||
' |> lineTo([0, 1], %, "myTag")',
|
||||
' |> lineTo([1, 1], %)',
|
||||
' |> rx(90, %)',
|
||||
].join('\n')
|
||||
@ -266,7 +266,7 @@ const key = 'c'
|
||||
const code = [
|
||||
'const mySk1 = startSketchAt([0, 0])',
|
||||
' |> lineTo([1, 1], %)',
|
||||
' |> lineTo([0, 1], %, $myTag)',
|
||||
' |> lineTo([0, 1], %, "myTag")',
|
||||
' |> lineTo([1, 1], %)',
|
||||
' // a comment',
|
||||
' |> rx(90, %)',
|
||||
@ -283,7 +283,7 @@ const key = 'c'
|
||||
const mySk1 = startSketchAt([0, 0])
|
||||
|> lineTo([1, 1], %)
|
||||
// comment here
|
||||
|> lineTo([0, 1], %, $myTag)
|
||||
|> lineTo([0, 1], %, 'myTag')
|
||||
|> lineTo([1, 1], %) /* and
|
||||
here
|
||||
*/
|
||||
@ -306,7 +306,7 @@ one more for good measure
|
||||
const mySk1 = startSketchAt([0, 0])
|
||||
|> lineTo([1, 1], %)
|
||||
// comment here
|
||||
|> lineTo([0, 1], %, $myTag)
|
||||
|> lineTo([0, 1], %, 'myTag')
|
||||
|> lineTo([1, 1], %) /* and
|
||||
here */
|
||||
// a comment between pipe expression statements
|
||||
@ -356,12 +356,12 @@ describe('testing call Expressions in BinaryExpressions and UnaryExpressions', (
|
||||
describe('it recasts wrapped object expressions in pipe bodies with correct indentation', () => {
|
||||
it('with a single line', () => {
|
||||
const code = `const part001 = startSketchAt([-0.01, -0.08])
|
||||
|> line([0.62, 4.15], %, $seg01)
|
||||
|> line([0.62, 4.15], %, 'seg01')
|
||||
|> line([2.77, -1.24], %)
|
||||
|> angledLineThatIntersects({
|
||||
angle: 201,
|
||||
offset: -1.35,
|
||||
intersectTag: $seg01
|
||||
intersectTag: 'seg01'
|
||||
}, %)
|
||||
|> line([-0.42, -1.72], %)
|
||||
`
|
||||
@ -374,7 +374,7 @@ describe('it recasts wrapped object expressions in pipe bodies with correct inde
|
||||
const code = `angledLineThatIntersects({
|
||||
angle: 201,
|
||||
offset: -1.35,
|
||||
intersectTag: $seg01
|
||||
intersectTag: 'seg01'
|
||||
}, %)
|
||||
`
|
||||
const { ast } = code2ast(code)
|
||||
|
@ -1249,29 +1249,6 @@ export class EngineCommandManager extends EventTarget {
|
||||
})
|
||||
|
||||
this.initPlanes().then(async () => {
|
||||
// Hide the grid and grid scale text.
|
||||
this.sendSceneCommand({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'object_visible' as any,
|
||||
// Found in engine/constants.h
|
||||
object_id: 'cfa78409-653d-4c26-96f1-7c45fb784840',
|
||||
hidden: true,
|
||||
},
|
||||
})
|
||||
|
||||
this.sendSceneCommand({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'object_visible' as any,
|
||||
// Found in engine/constants.h
|
||||
object_id: '10782f33-f588-4668-8bcd-040502d26590',
|
||||
hidden: true,
|
||||
},
|
||||
})
|
||||
|
||||
this.resolveReady()
|
||||
setIsStreamReady(true)
|
||||
await executeCode()
|
||||
|
@ -230,7 +230,7 @@ describe('testing addTagForSketchOnFace', () => {
|
||||
if (err(sketchOnFaceRetVal)) return sketchOnFaceRetVal
|
||||
|
||||
const { modifiedAst } = sketchOnFaceRetVal
|
||||
const expectedCode = genCode('lineTo([-1.59, -1.54], %, $seg01)')
|
||||
const expectedCode = genCode("lineTo([-1.59, -1.54], %, 'seg01')")
|
||||
expect(recast(modifiedAst)).toBe(expectedCode)
|
||||
})
|
||||
})
|
||||
|
@ -11,7 +11,6 @@ import {
|
||||
Value,
|
||||
Literal,
|
||||
VariableDeclaration,
|
||||
Identifier,
|
||||
} from 'lang/wasm'
|
||||
import {
|
||||
getNodeFromPath,
|
||||
@ -41,7 +40,6 @@ import {
|
||||
|
||||
import {
|
||||
createLiteral,
|
||||
createTagDeclarator,
|
||||
createCallExpression,
|
||||
createArrayExpression,
|
||||
createPipeSubstitution,
|
||||
@ -53,7 +51,6 @@ import {
|
||||
import { roundOff, getLength, getAngle } from 'lib/utils'
|
||||
import { err } from 'lib/trap'
|
||||
import { perpendicularDistance } from 'sketch-helpers'
|
||||
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
|
||||
|
||||
export type Coords2d = [number, number]
|
||||
|
||||
@ -1409,7 +1406,7 @@ export const angledLineThatIntersects: SketchLineHelper = {
|
||||
?.value || createLiteral('')
|
||||
: createLiteral('')
|
||||
const intersectTagName =
|
||||
intersectTag.type === 'Identifier' ? intersectTag.name : ''
|
||||
intersectTag.type === 'Literal' ? intersectTag.value : ''
|
||||
const nodeMeta2 = getNodeFromPath<VariableDeclaration>(
|
||||
_node,
|
||||
pathToNode,
|
||||
@ -1500,23 +1497,23 @@ export const angledLineThatIntersects: SketchLineHelper = {
|
||||
)
|
||||
}
|
||||
if (intersectTag !== -1) {
|
||||
const tag = firstArg.properties[intersectTag]?.value as Identifier
|
||||
const tag = firstArg.properties[intersectTag]?.value
|
||||
const pathToTagProp: PathToNode = [
|
||||
...pathToObjectExp,
|
||||
[intersectTag, 'index'],
|
||||
['value', 'Property'],
|
||||
]
|
||||
const info = constrainInfo(
|
||||
'intersectionTag',
|
||||
// This will always be a tag identifier.
|
||||
false,
|
||||
code.slice(tag.start, tag.end),
|
||||
'angledLineThatIntersects',
|
||||
'intersectTag',
|
||||
[tag.start, tag.end],
|
||||
pathToTagProp
|
||||
returnVal.push(
|
||||
constrainInfo(
|
||||
'intersectionTag',
|
||||
isNotLiteralArrayOrStatic(tag),
|
||||
code.slice(tag.start, tag.end),
|
||||
'angledLineThatIntersects',
|
||||
'intersectTag',
|
||||
[tag.start, tag.end],
|
||||
pathToTagProp
|
||||
)
|
||||
)
|
||||
returnVal.push(info)
|
||||
}
|
||||
return returnVal
|
||||
},
|
||||
@ -1833,18 +1830,17 @@ function addTag(tagIndex = 2): addTagFn {
|
||||
// Tag is always 3rd expression now, using arg index feels brittle
|
||||
// but we can come up with a better way to identify tag later.
|
||||
const thirdArg = primaryCallExp.arguments?.[tagIndex]
|
||||
const tagDeclarator =
|
||||
thirdArg ||
|
||||
(createTagDeclarator(findUniqueName(_node, 'seg', 2)) as TagDeclarator)
|
||||
const tagLiteral =
|
||||
thirdArg || (createLiteral(findUniqueName(_node, 'seg', 2)) as Literal)
|
||||
const isTagExisting = !!thirdArg
|
||||
if (!isTagExisting) {
|
||||
primaryCallExp.arguments[tagIndex] = tagDeclarator
|
||||
primaryCallExp.arguments[tagIndex] = tagLiteral
|
||||
}
|
||||
if ('value' in tagDeclarator) {
|
||||
// Now TypeScript knows tagDeclarator has a value property
|
||||
if ('value' in tagLiteral) {
|
||||
// Now TypeScript knows tagLiteral has a value property
|
||||
return {
|
||||
modifiedAst: _node,
|
||||
tag: String(tagDeclarator.value),
|
||||
tag: String(tagLiteral.value),
|
||||
}
|
||||
} else {
|
||||
return new Error('Unable to assign tag without value')
|
||||
|
@ -65,17 +65,17 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
|
||||
const bigExampleArr = [
|
||||
`const part001 = startSketchOn('XY')`,
|
||||
` |> startProfileAt([0, 0], %)`,
|
||||
` |> lineTo([1, 1], %, $abc1)`,
|
||||
` |> line([-2.04, -0.7], %, $abc2)`,
|
||||
` |> angledLine({ angle: 157, length: 1.69 }, %, $abc3)`,
|
||||
` |> angledLineOfXLength({ angle: 217, length: 0.86 }, %, $abc4)`,
|
||||
` |> angledLineOfYLength({ angle: 104, length: 1.58 }, %, $abc5)`,
|
||||
` |> angledLineToX({ angle: 55, to: -2.89 }, %, $abc6)`,
|
||||
` |> angledLineToY({ angle: 330, to: 2.53 }, %, $abc7)`,
|
||||
` |> xLine(1.47, %, $abc8)`,
|
||||
` |> yLine(1.57, %, $abc9)`,
|
||||
` |> xLineTo(1.49, %, $abc10)`,
|
||||
` |> yLineTo(2.64, %, $abc11)`,
|
||||
` |> lineTo([1, 1], %, 'abc1')`,
|
||||
` |> line([-2.04, -0.7], %, 'abc2')`,
|
||||
` |> angledLine({ angle: 157, length: 1.69 }, %, 'abc3')`,
|
||||
` |> angledLineOfXLength({ angle: 217, length: 0.86 }, %, 'abc4')`,
|
||||
` |> angledLineOfYLength({ angle: 104, length: 1.58 }, %, 'abc5')`,
|
||||
` |> angledLineToX({ angle: 55, to: -2.89 }, %, 'abc6')`,
|
||||
` |> angledLineToY({ angle: 330, to: 2.53 }, %, 'abc7')`,
|
||||
` |> xLine(1.47, %, 'abc8')`,
|
||||
` |> yLine(1.57, %, 'abc9')`,
|
||||
` |> xLineTo(1.49, %, 'abc10')`,
|
||||
` |> yLineTo(2.64, %, 'abc11')`,
|
||||
` |> lineTo([2.55, 3.58], %) // lineTo`,
|
||||
` |> line([0.73, -0.75], %)`,
|
||||
` |> angledLine([63, 1.38], %) // angledLine`,
|
||||
@ -90,8 +90,8 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
|
||||
]
|
||||
const bigExample = bigExampleArr.join('\n')
|
||||
it('line with tag converts to xLine', async () => {
|
||||
const callToSwap = 'line([-2.04, -0.7], %, $abc2)'
|
||||
const expectedLine = 'xLine(-2.04, %, $abc2)'
|
||||
const callToSwap = "line([-2.04, -0.7], %, 'abc2')"
|
||||
const expectedLine = "xLine(-2.04, %, 'abc2')"
|
||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||
inputCode: bigExample,
|
||||
callToSwap,
|
||||
@ -116,10 +116,10 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
|
||||
it('lineTo with tag converts to xLineTo', async () => {
|
||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||
inputCode: bigExample,
|
||||
callToSwap: 'lineTo([1, 1], %, $abc1)',
|
||||
callToSwap: "lineTo([1, 1], %, 'abc1')",
|
||||
constraintType: 'horizontal',
|
||||
})
|
||||
const expectedLine = 'xLineTo(1, %, $abc1)'
|
||||
const expectedLine = "xLineTo(1, %, 'abc1')"
|
||||
expect(newCode).toContain(expectedLine)
|
||||
// new line should start at the same place as the old line
|
||||
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
||||
@ -138,10 +138,10 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
|
||||
it('angledLine with tag converts to xLine', async () => {
|
||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||
inputCode: bigExample,
|
||||
callToSwap: 'angledLine({ angle: 157, length: 1.69 }, %, $abc3)',
|
||||
callToSwap: "angledLine({ angle: 157, length: 1.69 }, %, 'abc3')",
|
||||
constraintType: 'horizontal',
|
||||
})
|
||||
const expectedLine = 'xLine(-1.56, %, $abc3)'
|
||||
const expectedLine = "xLine(-1.56, %, 'abc3')"
|
||||
console.log(newCode)
|
||||
expect(newCode).toContain(expectedLine)
|
||||
// new line should start at the same place as the old line
|
||||
@ -161,10 +161,11 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
|
||||
it('angledLineOfXLength with tag converts to xLine', async () => {
|
||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||
inputCode: bigExample,
|
||||
callToSwap: 'angledLineOfXLength({ angle: 217, length: 0.86 }, %, $abc4)',
|
||||
callToSwap:
|
||||
"angledLineOfXLength({ angle: 217, length: 0.86 }, %, 'abc4')",
|
||||
constraintType: 'horizontal',
|
||||
})
|
||||
const expectedLine = 'xLine(-0.86, %, $abc4)'
|
||||
const expectedLine = "xLine(-0.86, %, 'abc4')"
|
||||
// hmm "-0.86" is correct since the angle is 104, but need to make sure this is compatible `-myVar`
|
||||
expect(newCode).toContain(expectedLine)
|
||||
// new line should start at the same place as the old line
|
||||
@ -184,10 +185,11 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
|
||||
it('angledLineOfYLength with tag converts to yLine', async () => {
|
||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||
inputCode: bigExample,
|
||||
callToSwap: 'angledLineOfYLength({ angle: 104, length: 1.58 }, %, $abc5)',
|
||||
callToSwap:
|
||||
"angledLineOfYLength({ angle: 104, length: 1.58 }, %, 'abc5')",
|
||||
constraintType: 'vertical',
|
||||
})
|
||||
const expectedLine = 'yLine(1.58, %, $abc5)'
|
||||
const expectedLine = "yLine(1.58, %, 'abc5')"
|
||||
expect(newCode).toContain(expectedLine)
|
||||
// new line should start at the same place as the old line
|
||||
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
||||
@ -206,10 +208,10 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
|
||||
it('angledLineToX with tag converts to xLineTo', async () => {
|
||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||
inputCode: bigExample,
|
||||
callToSwap: 'angledLineToX({ angle: 55, to: -2.89 }, %, $abc6)',
|
||||
callToSwap: "angledLineToX({ angle: 55, to: -2.89 }, %, 'abc6')",
|
||||
constraintType: 'horizontal',
|
||||
})
|
||||
const expectedLine = 'xLineTo(-2.89, %, $abc6)'
|
||||
const expectedLine = "xLineTo(-2.89, %, 'abc6')"
|
||||
expect(newCode).toContain(expectedLine)
|
||||
// new line should start at the same place as the old line
|
||||
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
||||
@ -228,10 +230,10 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
|
||||
it('angledLineToY with tag converts to yLineTo', async () => {
|
||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||
inputCode: bigExample,
|
||||
callToSwap: 'angledLineToY({ angle: 330, to: 2.53 }, %, $abc7)',
|
||||
callToSwap: "angledLineToY({ angle: 330, to: 2.53 }, %, 'abc7')",
|
||||
constraintType: 'vertical',
|
||||
})
|
||||
const expectedLine = 'yLineTo(2.53, %, $abc7)'
|
||||
const expectedLine = "yLineTo(2.53, %, 'abc7')"
|
||||
expect(newCode).toContain(expectedLine)
|
||||
// new line should start at the same place as the old line
|
||||
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
||||
|
@ -139,70 +139,70 @@ const myAng = 40
|
||||
const myAng2 = 134
|
||||
const part001 = startSketchOn('XY')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([1, 3.82], %, $seg01) // ln-should-get-tag
|
||||
|> line([1, 3.82], %, 'seg01') // ln-should-get-tag
|
||||
|> angledLineToX([
|
||||
-angleToMatchLengthX(seg01, myVar, %),
|
||||
-angleToMatchLengthX('seg01', myVar, %),
|
||||
myVar
|
||||
], %) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|
||||
|> angledLineToY([
|
||||
-angleToMatchLengthY(seg01, myVar, %),
|
||||
-angleToMatchLengthY('seg01', myVar, %),
|
||||
myVar
|
||||
], %) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper
|
||||
|> angledLine([45, segLen(seg01, %)], %) // ln-lineTo-free should become angledLine
|
||||
|> angledLine([45, segLen(seg01, %)], %) // ln-angledLineToX-free should become angledLine
|
||||
|> angledLine([myAng, segLen(seg01, %)], %) // ln-angledLineToX-angle should become angledLine
|
||||
|> angledLine([45, segLen('seg01', %)], %) // ln-lineTo-free should become angledLine
|
||||
|> angledLine([45, segLen('seg01', %)], %) // ln-angledLineToX-free should become angledLine
|
||||
|> angledLine([myAng, segLen('seg01', %)], %) // ln-angledLineToX-angle should become angledLine
|
||||
|> angledLineToX([
|
||||
angleToMatchLengthX(seg01, myVar2, %),
|
||||
angleToMatchLengthX('seg01', myVar2, %),
|
||||
myVar2
|
||||
], %) // ln-angledLineToX-xAbsolute should use angleToMatchLengthX to get angle
|
||||
|> angledLine([-45, segLen(seg01, %)], %) // ln-angledLineToY-free should become angledLine
|
||||
|> angledLine([myAng2, segLen(seg01, %)], %) // ln-angledLineToY-angle should become angledLine
|
||||
|> angledLine([-45, segLen('seg01', %)], %) // ln-angledLineToY-free should become angledLine
|
||||
|> angledLine([myAng2, segLen('seg01', %)], %) // ln-angledLineToY-angle should become angledLine
|
||||
|> angledLineToY([
|
||||
angleToMatchLengthY(seg01, myVar3, %),
|
||||
angleToMatchLengthY('seg01', myVar3, %),
|
||||
myVar3
|
||||
], %) // ln-angledLineToY-yAbsolute should use angleToMatchLengthY to get angle
|
||||
|> line([
|
||||
min(segLen(seg01, %), myVar),
|
||||
legLen(segLen(seg01, %), myVar)
|
||||
min(segLen('seg01', %), myVar),
|
||||
legLen(segLen('seg01', %), myVar)
|
||||
], %) // ln-should use legLen for y
|
||||
|> line([
|
||||
min(segLen(seg01, %), myVar),
|
||||
-legLen(segLen(seg01, %), myVar)
|
||||
min(segLen('seg01', %), myVar),
|
||||
-legLen(segLen('seg01', %), myVar)
|
||||
], %) // ln-legLen but negative
|
||||
|> angledLine([-112, segLen(seg01, %)], %) // ln-should become angledLine
|
||||
|> angledLine([myVar, segLen(seg01, %)], %) // ln-use segLen for second arg
|
||||
|> angledLine([45, segLen(seg01, %)], %) // ln-segLen again
|
||||
|> angledLine([54, segLen(seg01, %)], %) // ln-should be transformed to angledLine
|
||||
|> angledLine([-112, segLen('seg01', %)], %) // ln-should become angledLine
|
||||
|> angledLine([myVar, segLen('seg01', %)], %) // ln-use segLen for second arg
|
||||
|> angledLine([45, segLen('seg01', %)], %) // ln-segLen again
|
||||
|> angledLine([54, segLen('seg01', %)], %) // ln-should be transformed to angledLine
|
||||
|> angledLineOfXLength([
|
||||
legAngX(segLen(seg01, %), myVar),
|
||||
min(segLen(seg01, %), myVar)
|
||||
legAngX(segLen('seg01', %), myVar),
|
||||
min(segLen('seg01', %), myVar)
|
||||
], %) // ln-should use legAngX to calculate angle
|
||||
|> angledLineOfXLength([
|
||||
180 + legAngX(segLen(seg01, %), myVar),
|
||||
min(segLen(seg01, %), myVar)
|
||||
180 + legAngX(segLen('seg01', %), myVar),
|
||||
min(segLen('seg01', %), myVar)
|
||||
], %) // ln-same as above but should have + 180 to match original quadrant
|
||||
|> line([
|
||||
legLen(segLen(seg01, %), myVar),
|
||||
min(segLen(seg01, %), myVar)
|
||||
legLen(segLen('seg01', %), myVar),
|
||||
min(segLen('seg01', %), myVar)
|
||||
], %) // ln-legLen again but yRelative
|
||||
|> line([
|
||||
-legLen(segLen(seg01, %), myVar),
|
||||
min(segLen(seg01, %), myVar)
|
||||
-legLen(segLen('seg01', %), myVar),
|
||||
min(segLen('seg01', %), myVar)
|
||||
], %) // ln-negative legLen yRelative
|
||||
|> angledLine([58, segLen(seg01, %)], %) // ln-angledLineOfYLength-free should become angledLine
|
||||
|> angledLine([myAng, segLen(seg01, %)], %) // ln-angledLineOfYLength-angle should become angledLine
|
||||
|> angledLine([58, segLen('seg01', %)], %) // ln-angledLineOfYLength-free should become angledLine
|
||||
|> angledLine([myAng, segLen('seg01', %)], %) // ln-angledLineOfYLength-angle should become angledLine
|
||||
|> angledLineOfXLength([
|
||||
legAngY(segLen(seg01, %), myVar),
|
||||
min(segLen(seg01, %), myVar)
|
||||
legAngY(segLen('seg01', %), myVar),
|
||||
min(segLen('seg01', %), myVar)
|
||||
], %) // ln-angledLineOfYLength-yRelative use legAngY
|
||||
|> angledLineOfXLength([
|
||||
270 + legAngY(segLen(seg01, %), myVar),
|
||||
min(segLen(seg01, %), myVar)
|
||||
270 + legAngY(segLen('seg01', %), myVar),
|
||||
min(segLen('seg01', %), myVar)
|
||||
], %) // ln-angledLineOfYLength-yRelative with angle > 90 use binExp
|
||||
|> xLine(segLen(seg01, %), %) // ln-xLine-free should sub in segLen
|
||||
|> yLine(segLen(seg01, %), %) // ln-yLine-free should sub in segLen
|
||||
|> xLine(segLen(seg01, %), %) // ln-xLineTo-free should convert to xLine
|
||||
|> yLine(segLen(seg01, %), %) // ln-yLineTo-free should convert to yLine
|
||||
|> xLine(segLen('seg01', %), %) // ln-xLine-free should sub in segLen
|
||||
|> yLine(segLen('seg01', %), %) // ln-yLine-free should sub in segLen
|
||||
|> xLine(segLen('seg01', %), %) // ln-xLineTo-free should convert to xLine
|
||||
|> yLine(segLen('seg01', %), %) // ln-yLineTo-free should convert to yLine
|
||||
`
|
||||
it('should transform the ast', async () => {
|
||||
const ast = parse(inputScript)
|
||||
@ -417,10 +417,10 @@ const part001 = startSketchOn('XY')
|
||||
'setVertDistance'
|
||||
)
|
||||
expect(expectedHorizontalCode).toContain(
|
||||
`lineTo([segEndX(seg01, %) + 0.9, 4.59], %) // free`
|
||||
`lineTo([segEndX('seg01', %) + 0.9, 4.59], %) // free`
|
||||
)
|
||||
expect(expectedVerticalCode).toContain(
|
||||
`lineTo([1.21, segEndY(seg01, %) + 2.92], %) // free`
|
||||
`lineTo([1.21, segEndY('seg01', %) + 2.92], %) // free`
|
||||
)
|
||||
})
|
||||
it('testing for xRelative to vertical distance', async () => {
|
||||
@ -431,7 +431,7 @@ const part001 = startSketchOn('XY')
|
||||
)
|
||||
expect(expectedCode).toContain(`|> lineTo([
|
||||
lastSegX(%) + myVar,
|
||||
segEndY(seg01, %) + 2.93
|
||||
segEndY('seg01', %) + 2.93
|
||||
], %) // xRelative`)
|
||||
})
|
||||
it('testing for yRelative to horizontal distance', async () => {
|
||||
@ -441,7 +441,7 @@ const part001 = startSketchOn('XY')
|
||||
'setHorzDistance'
|
||||
)
|
||||
expect(expectedCode).toContain(`|> lineTo([
|
||||
segEndX(seg01, %) + 2.6,
|
||||
segEndX('seg01', %) + 2.6,
|
||||
lastSegY(%) + myVar
|
||||
], %) // yRelative`)
|
||||
})
|
||||
|
@ -462,7 +462,7 @@ const setAngledIntersectLineForLines: TransformInfo['createNode'] =
|
||||
angleVal,
|
||||
offsetVal:
|
||||
forceValueUsedInTransform || createLiteral(valueUsedInTransform),
|
||||
intersectTag: createIdentifier(referenceSegName),
|
||||
intersectTag: createLiteral(referenceSegName),
|
||||
tag,
|
||||
valueUsedInTransform,
|
||||
})
|
||||
@ -481,7 +481,7 @@ const setAngledIntersectForAngledLines: TransformInfo['createNode'] =
|
||||
angleVal: varValA,
|
||||
offsetVal:
|
||||
forceValueUsedInTransform || createLiteral(valueUsedInTransform),
|
||||
intersectTag: createIdentifier(referenceSegName),
|
||||
intersectTag: createLiteral(referenceSegName),
|
||||
tag,
|
||||
valueUsedInTransform,
|
||||
})
|
||||
@ -675,7 +675,7 @@ const transformMap: TransformMap = {
|
||||
const angleToMatchLengthXCall = createCallExpression(
|
||||
'angleToMatchLengthX',
|
||||
[
|
||||
createIdentifier(referenceSegName),
|
||||
createLiteral(referenceSegName),
|
||||
varValA,
|
||||
createPipeSubstitution(),
|
||||
]
|
||||
@ -708,7 +708,7 @@ const transformMap: TransformMap = {
|
||||
const angleToMatchLengthYCall = createCallExpression(
|
||||
'angleToMatchLengthY',
|
||||
[
|
||||
createIdentifier(referenceSegName),
|
||||
createLiteral(referenceSegName),
|
||||
varValB,
|
||||
createPipeSubstitution(),
|
||||
]
|
||||
@ -973,7 +973,7 @@ const transformMap: TransformMap = {
|
||||
const angleToMatchLengthXCall = createCallExpression(
|
||||
'angleToMatchLengthX',
|
||||
[
|
||||
createIdentifier(referenceSegName),
|
||||
createLiteral(referenceSegName),
|
||||
varValB,
|
||||
createPipeSubstitution(),
|
||||
]
|
||||
@ -1023,7 +1023,7 @@ const transformMap: TransformMap = {
|
||||
const angleToMatchLengthXCall = createCallExpression(
|
||||
'angleToMatchLengthY',
|
||||
[
|
||||
createIdentifier(referenceSegName),
|
||||
createLiteral(referenceSegName),
|
||||
varValB,
|
||||
createPipeSubstitution(),
|
||||
]
|
||||
@ -1174,7 +1174,7 @@ export function getRemoveConstraintsTransform(
|
||||
// fnName: name,
|
||||
// angleVal: args[0],
|
||||
// offsetVal: args[1],
|
||||
// intersectTag: createIdentifier(referenceSegName),
|
||||
// intersectTag: createLiteral(referenceSegName),
|
||||
// tag,
|
||||
// })
|
||||
// }
|
||||
@ -1496,7 +1496,7 @@ export function transformSecondarySketchLinesTagFirst({
|
||||
}
|
||||
}
|
||||
| Error {
|
||||
// let node = ast
|
||||
// let node = JSON.parse(JSON.stringify(ast))
|
||||
const primarySelection = selectionRanges.codeBasedSelections[0].range
|
||||
|
||||
const _tag = giveSketchFnCallTag(ast, primarySelection, forceSegName)
|
||||
@ -1565,7 +1565,7 @@ export function transformAstSketchLines({
|
||||
}
|
||||
| Error {
|
||||
// deep clone since we are mutating in a loop, of which any could fail
|
||||
let node = ast
|
||||
let node = JSON.parse(JSON.stringify(ast))
|
||||
let _valueUsedInTransform // TODO should this be an array?
|
||||
const pathToNodeMap: PathToNodeMap = {}
|
||||
|
||||
@ -1593,8 +1593,8 @@ export function transformAstSketchLines({
|
||||
const _referencedSegmentName =
|
||||
referenceSegName ||
|
||||
(_referencedSegmentNameVal &&
|
||||
_referencedSegmentNameVal.type === 'Identifier' &&
|
||||
String(_referencedSegmentNameVal.name)) ||
|
||||
_referencedSegmentNameVal.type === 'Literal' &&
|
||||
String(_referencedSegmentNameVal.value)) ||
|
||||
''
|
||||
const { val } = firstArg
|
||||
const [varValA, varValB] = Array.isArray(val) ? val : [val, val]
|
||||
@ -1714,21 +1714,21 @@ export function transformAstSketchLines({
|
||||
|
||||
function createSegLen(referenceSegName: string): Value {
|
||||
return createCallExpression('segLen', [
|
||||
createIdentifier(referenceSegName),
|
||||
createLiteral(referenceSegName),
|
||||
createPipeSubstitution(),
|
||||
])
|
||||
}
|
||||
|
||||
function createSegAngle(referenceSegName: string): Value {
|
||||
return createCallExpression('segAng', [
|
||||
createIdentifier(referenceSegName),
|
||||
createLiteral(referenceSegName),
|
||||
createPipeSubstitution(),
|
||||
])
|
||||
}
|
||||
|
||||
function createSegEnd(referenceSegName: string, isX: boolean): CallExpression {
|
||||
return createCallExpression(isX ? 'segEndX' : 'segEndY', [
|
||||
createIdentifier(referenceSegName),
|
||||
createLiteral(referenceSegName),
|
||||
createPipeSubstitution(),
|
||||
])
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ export function updatePathToNodeFromMap(
|
||||
oldPath: PathToNode,
|
||||
pathToNodeMap: { [key: number]: PathToNode }
|
||||
): PathToNode {
|
||||
const updatedPathToNode = oldPath
|
||||
const updatedPathToNode = JSON.parse(JSON.stringify(oldPath))
|
||||
let max = 0
|
||||
Object.values(pathToNodeMap).forEach((path) => {
|
||||
const index = Number(path[1][0])
|
||||
|
@ -2,7 +2,6 @@ import init, {
|
||||
parse_wasm,
|
||||
recast_wasm,
|
||||
execute_wasm,
|
||||
kcl_lint,
|
||||
lexer_wasm,
|
||||
modify_ast_for_sketch_wasm,
|
||||
is_points_ccw,
|
||||
@ -21,7 +20,6 @@ import { KCLError } from './errors'
|
||||
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
|
||||
import { EngineCommandManager } from './std/engineConnection'
|
||||
import { ProgramReturn } from '../wasm-lib/kcl/bindings/ProgramReturn'
|
||||
import { Discovered } from '../wasm-lib/kcl/bindings/Discovered'
|
||||
import { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
|
||||
import type { Program } from '../wasm-lib/kcl/bindings/Program'
|
||||
import type { Token } from '../wasm-lib/kcl/bindings/Token'
|
||||
@ -207,17 +205,6 @@ export const _executor = async (
|
||||
}
|
||||
}
|
||||
|
||||
export const kclLint = async (ast: Program): Promise<Array<Discovered>> => {
|
||||
try {
|
||||
const discovered_findings: Array<Discovered> = await kcl_lint(
|
||||
JSON.stringify(ast)
|
||||
)
|
||||
return discovered_findings
|
||||
} catch (e: any) {
|
||||
return Promise.reject(e)
|
||||
}
|
||||
}
|
||||
|
||||
export const recast = (ast: Program): string | Error => {
|
||||
return recast_wasm(JSON.stringify(ast))
|
||||
}
|
||||
@ -334,7 +321,6 @@ export async function coreDump(
|
||||
openGithubIssue: boolean = false
|
||||
): Promise<CoreDumpInfo> {
|
||||
try {
|
||||
console.warn('CoreDump: Initializing core dump')
|
||||
const dump: CoreDumpInfo = await coredump(coreDumpManager)
|
||||
/* NOTE: this console output of the coredump should include the field
|
||||
`github_issue_url` which is not in the uploaded coredump file.
|
||||
|
@ -13,14 +13,6 @@ import screenshot from 'lib/screenshot'
|
||||
import React from 'react'
|
||||
import { VITE_KC_API_BASE_URL } from 'env'
|
||||
|
||||
/* eslint-disable suggest-no-throw/suggest-no-throw --
|
||||
* All the throws in CoreDumpManager are intentional and should be caught and handled properly
|
||||
* by the calling Promises with a catch block. The throws are essential to properly handling
|
||||
* when the app isn't ready enough or otherwise unable to produce a core dump. By throwing
|
||||
* instead of simply erroring, the code halts execution at the first point which it cannot
|
||||
* complete the core dump request.
|
||||
**/
|
||||
|
||||
/**
|
||||
* CoreDumpManager module
|
||||
* - for getting all the values from the JS world to pass to the Rust world for a core dump.
|
||||
@ -30,7 +22,6 @@ import { VITE_KC_API_BASE_URL } from 'env'
|
||||
// CoreDumpManager is instantiated in ModelingMachineProvider and passed to coreDump() in wasm.ts
|
||||
// The async function coreDump() handles any errors thrown in its Promise catch method and rethrows
|
||||
// them to so the toast handler in ModelingMachineProvider can show the user an error message toast
|
||||
// TODO: Throw more
|
||||
export class CoreDumpManager {
|
||||
engineCommandManager: EngineCommandManager
|
||||
htmlRef: React.RefObject<HTMLDivElement> | null
|
||||
|
@ -9,12 +9,12 @@ const wallMountL = 6 // the length of the bracket
|
||||
const sigmaAllow = 35000 // psi
|
||||
const width = 6 // inch
|
||||
const p = 300 // Force on shelf - lbs
|
||||
const shelfLength = 12 // inches
|
||||
const moment = shelfLength * p / 2 // Moment experienced at fixed end of bracket
|
||||
const factorOfSafety = 2 // Factor of safety of 2 to be conservative
|
||||
const L = 12 // inches
|
||||
const M = L * p / 2 // Moment experienced at fixed end of bracket
|
||||
const FOS = 2 // Factor of safety of 2 to be conservative
|
||||
|
||||
// Calculate the thickness off the bending stress and factor of safety
|
||||
const thickness = sqrt(6 * moment * factorOfSafety / (width * sigmaAllow))
|
||||
const thickness = sqrt(6 * M * FOS / (width * sigmaAllow))
|
||||
|
||||
// 0.25 inch fillet radius
|
||||
const filletR = 0.25
|
||||
@ -22,20 +22,20 @@ const filletR = 0.25
|
||||
// Sketch the bracket and extrude with fillets
|
||||
const bracket = startSketchOn('XY')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([0, wallMountL], %, $outerEdge)
|
||||
|> line([0, wallMountL], %, 'outerEdge')
|
||||
|> line([-shelfMountL, 0], %)
|
||||
|> line([0, -thickness], %)
|
||||
|> line([shelfMountL - thickness, 0], %, $innerEdge)
|
||||
|> line([shelfMountL - thickness, 0], %, 'innerEdge')
|
||||
|> line([0, -wallMountL + thickness], %)
|
||||
|> close(%)
|
||||
|> extrude(width, %)
|
||||
|> fillet({
|
||||
radius: filletR,
|
||||
tags: [getPreviousAdjacentEdge(innerEdge, %)]
|
||||
tags: [getPreviousAdjacentEdge('innerEdge', %)]
|
||||
}, %)
|
||||
|> fillet({
|
||||
radius: filletR + thickness,
|
||||
tags: [getPreviousAdjacentEdge(outerEdge, %)]
|
||||
tags: [getPreviousAdjacentEdge('outerEdge', %)]
|
||||
}, %)`
|
||||
|
||||
function findLineInExampleCode({
|
||||
|
@ -2,10 +2,8 @@ import {
|
||||
createArrayExpression,
|
||||
createBinaryExpression,
|
||||
createCallExpressionStdLib,
|
||||
createIdentifier,
|
||||
createLiteral,
|
||||
createPipeSubstitution,
|
||||
createTagDeclarator,
|
||||
createUnaryExpression,
|
||||
} from 'lang/modifyAst'
|
||||
import { roundOff } from './utils'
|
||||
@ -37,13 +35,13 @@ export const getRectangleCallExpressions = (
|
||||
createLiteral(0), // This will be the width of the rectangle
|
||||
]),
|
||||
createPipeSubstitution(),
|
||||
createTagDeclarator(tags[0]),
|
||||
createLiteral(tags[0]),
|
||||
]),
|
||||
createCallExpressionStdLib('angledLine', [
|
||||
createArrayExpression([
|
||||
createBinaryExpression([
|
||||
createCallExpressionStdLib('segAng', [
|
||||
createIdentifier(tags[0]),
|
||||
createLiteral(tags[0]),
|
||||
createPipeSubstitution(),
|
||||
]),
|
||||
'+',
|
||||
@ -52,24 +50,24 @@ export const getRectangleCallExpressions = (
|
||||
createLiteral(0), // This will be the height of the rectangle
|
||||
]),
|
||||
createPipeSubstitution(),
|
||||
createTagDeclarator(tags[1]),
|
||||
createLiteral(tags[1]),
|
||||
]),
|
||||
createCallExpressionStdLib('angledLine', [
|
||||
createArrayExpression([
|
||||
createCallExpressionStdLib('segAng', [
|
||||
createIdentifier(tags[0]),
|
||||
createLiteral(tags[0]),
|
||||
createPipeSubstitution(),
|
||||
]), // same angle as the first line
|
||||
createUnaryExpression(
|
||||
createCallExpressionStdLib('segLen', [
|
||||
createIdentifier(tags[0]),
|
||||
createLiteral(tags[0]),
|
||||
createPipeSubstitution(),
|
||||
]),
|
||||
'-'
|
||||
), // negative height
|
||||
]),
|
||||
createPipeSubstitution(),
|
||||
createTagDeclarator(tags[2]),
|
||||
createLiteral(tags[2]),
|
||||
]),
|
||||
createCallExpressionStdLib('lineTo', [
|
||||
createArrayExpression([
|
||||
@ -103,7 +101,7 @@ export function updateRectangleSketch(
|
||||
.arguments[0] as ArrayExpression) = createArrayExpression([
|
||||
createBinaryExpression([
|
||||
createCallExpressionStdLib('segAng', [
|
||||
createIdentifier(tag),
|
||||
createLiteral(tag),
|
||||
createPipeSubstitution(),
|
||||
]),
|
||||
Math.sign(y) === Math.sign(x) ? '+' : '-',
|
||||
|
@ -29,10 +29,7 @@ export function cleanErrs<T>(
|
||||
return [argsWOutErr.length !== value.length, argsWOutErr, argsWErr]
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to report errors to user at a certain point in execution
|
||||
* @returns boolean
|
||||
*/
|
||||
// Used to report errors to user at a certain point in execution
|
||||
export function trap<T>(
|
||||
value: ExcludeErr<T> | Error,
|
||||
opts?: {
|
||||
@ -46,8 +43,6 @@ export function trap<T>(
|
||||
|
||||
console.error(value)
|
||||
opts?.suppress ||
|
||||
toast.error((opts?.altErr ?? value ?? new Error('Unknown')).toString(), {
|
||||
id: 'error',
|
||||
})
|
||||
toast.error((opts?.altErr ?? value ?? new Error('Unknown')).toString())
|
||||
return true
|
||||
}
|
||||
|
@ -96,7 +96,9 @@ export function useCalculateKclExpression({
|
||||
ast,
|
||||
engineCommandManager,
|
||||
useFakeExecutor: true,
|
||||
programMemoryOverride: kclManager.programMemory,
|
||||
programMemoryOverride: JSON.parse(
|
||||
JSON.stringify(kclManager.programMemory)
|
||||
),
|
||||
})
|
||||
const resultDeclaration = ast.body.find(
|
||||
(a) =>
|
||||
|
@ -26,11 +26,7 @@ import {
|
||||
applyConstraintEqualLength,
|
||||
setEqualLengthInfo,
|
||||
} from 'components/Toolbar/EqualLength'
|
||||
import {
|
||||
addStartProfileAt,
|
||||
deleteFromSelection,
|
||||
extrudeSketch,
|
||||
} from 'lang/modifyAst'
|
||||
import { addStartProfileAt, extrudeSketch } from 'lang/modifyAst'
|
||||
import { getNodeFromPath } from '../lang/queryAst'
|
||||
import {
|
||||
applyConstraintEqualAngle,
|
||||
@ -48,14 +44,12 @@ import {
|
||||
import { Models } from '@kittycad/lib/dist/types/src'
|
||||
import { ModelingCommandSchema } from 'lib/commandBarConfigs/modelingCommandConfig'
|
||||
import { err, trap } from 'lib/trap'
|
||||
import { DefaultPlaneStr, getFaceDetails } from 'clientSideScene/sceneEntities'
|
||||
import { DefaultPlaneStr } from 'clientSideScene/sceneEntities'
|
||||
import { Vector3 } from 'three'
|
||||
import { quaternionFromUpNForward } from 'clientSideScene/helpers'
|
||||
import { uuidv4 } from 'lib/utils'
|
||||
import { Coords2d } from 'lang/std/sketch'
|
||||
import { deleteSegment } from 'clientSideScene/ClientSideSceneComp'
|
||||
import { executeAst } from 'useStore'
|
||||
import toast from 'react-hot-toast'
|
||||
|
||||
export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY'
|
||||
|
||||
@ -163,9 +157,6 @@ export type ModelingMachineEvent =
|
||||
type: 'Set selection'
|
||||
data: SetSelections
|
||||
}
|
||||
| {
|
||||
type: 'Delete selection'
|
||||
}
|
||||
| { type: 'Sketch no face' }
|
||||
| { type: 'Toggle gui mode' }
|
||||
| { type: 'Cancel' }
|
||||
@ -282,13 +273,6 @@ export const modelingMachine = createMachine(
|
||||
cond: 'Has exportable geometry',
|
||||
actions: 'Engine export',
|
||||
},
|
||||
|
||||
'Delete selection': {
|
||||
target: 'idle',
|
||||
cond: 'has valid selection for deletion',
|
||||
actions: ['AST delete selection'],
|
||||
internal: true,
|
||||
},
|
||||
},
|
||||
|
||||
entry: 'reset client scene mouse handlers',
|
||||
@ -979,42 +963,6 @@ export const modelingMachine = createMachine(
|
||||
editorManager.selectRange(updatedAst?.selections)
|
||||
}
|
||||
},
|
||||
'AST delete selection': async ({ sketchDetails, selectionRanges }) => {
|
||||
let ast = kclManager.ast
|
||||
|
||||
const getScaledFaceDetails = async (entityId: string) => {
|
||||
const faceDetails = await getFaceDetails(entityId)
|
||||
if (err(faceDetails)) return {}
|
||||
return {
|
||||
...faceDetails,
|
||||
origin: {
|
||||
x: faceDetails.origin.x / sceneInfra._baseUnitMultiplier,
|
||||
y: faceDetails.origin.y / sceneInfra._baseUnitMultiplier,
|
||||
z: faceDetails.origin.z / sceneInfra._baseUnitMultiplier,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const modifiedAst = await deleteFromSelection(
|
||||
ast,
|
||||
selectionRanges.codeBasedSelections[0],
|
||||
kclManager.programMemory,
|
||||
getScaledFaceDetails
|
||||
)
|
||||
if (err(modifiedAst)) return
|
||||
|
||||
const testExecute = await executeAst({
|
||||
ast: modifiedAst,
|
||||
useFakeExecutor: true,
|
||||
engineCommandManager,
|
||||
})
|
||||
if (testExecute.errors.length) {
|
||||
toast.error('Unable to delete part')
|
||||
return
|
||||
}
|
||||
|
||||
await kclManager.updateAst(modifiedAst, true)
|
||||
},
|
||||
'conditionally equip line tool': (_, { type }) => {
|
||||
if (type === 'done.invoke.animate-to-face') {
|
||||
sceneInfra.modelingSend('Equip Line tool')
|
||||
|
@ -19,12 +19,8 @@ export default function UserMenu() {
|
||||
'[data-testid="user-sidebar-toggle"] img'
|
||||
)
|
||||
|
||||
const onError = () => setAvatarErrored(true)
|
||||
if (element?.tagName === 'IMG') {
|
||||
element?.addEventListener('error', onError)
|
||||
}
|
||||
return () => {
|
||||
element?.removeEventListener('error', onError)
|
||||
element.addEventListener('error', () => setAvatarErrored(true))
|
||||
}
|
||||
}, [])
|
||||
|
||||
|
@ -5,13 +5,11 @@ import {
|
||||
_executor,
|
||||
ProgramMemory,
|
||||
programMemoryInit,
|
||||
kclLint,
|
||||
} from './lang/wasm'
|
||||
import { enginelessExecutor } from './lib/testHelpers'
|
||||
import { EngineCommandManager } from './lang/std/engineConnection'
|
||||
import { KCLError } from './lang/errors'
|
||||
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
|
||||
import { Diagnostic } from '@codemirror/lint'
|
||||
|
||||
export type ToolTip =
|
||||
| 'lineTo'
|
||||
@ -189,24 +187,3 @@ export async function executeAst({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function lintAst({
|
||||
ast,
|
||||
}: {
|
||||
ast: Program
|
||||
}): Promise<Array<Diagnostic>> {
|
||||
try {
|
||||
const discovered_findings = await kclLint(ast)
|
||||
return discovered_findings.map((lint) => {
|
||||
return {
|
||||
message: lint.finding.title,
|
||||
severity: 'info',
|
||||
from: lint.pos[0],
|
||||
to: lint.pos[1],
|
||||
}
|
||||
})
|
||||
} catch (e: any) {
|
||||
console.log(e)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
71
src/wasm-lib/Cargo.lock
generated
@ -183,6 +183,12 @@ dependencies = [
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba"
|
||||
|
||||
[[package]]
|
||||
name = "auto_impl"
|
||||
version = "1.2.0"
|
||||
@ -533,7 +539,6 @@ dependencies = [
|
||||
"ciborium",
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"futures",
|
||||
"is-terminal",
|
||||
"itertools 0.10.5",
|
||||
"num-traits",
|
||||
@ -546,7 +551,6 @@ dependencies = [
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tinytemplate",
|
||||
"tokio",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
@ -658,20 +662,6 @@ dependencies = [
|
||||
"parking_lot_core 0.9.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "6.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "804c8821570c3f8b70230c2ba75ffa5c0f9a4189b9a432b6656c536712acae28"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"hashbrown 0.14.3",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core 0.9.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.5.0"
|
||||
@ -712,7 +702,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "derive-docs"
|
||||
version = "0.1.19"
|
||||
version = "0.1.18"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"anyhow",
|
||||
@ -1385,7 +1375,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.1.68"
|
||||
version = "0.1.66"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx",
|
||||
@ -1397,7 +1387,7 @@ dependencies = [
|
||||
"clap",
|
||||
"convert_case",
|
||||
"criterion",
|
||||
"dashmap 6.0.1",
|
||||
"dashmap",
|
||||
"databake",
|
||||
"derive-docs",
|
||||
"expectorate",
|
||||
@ -1996,15 +1986,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3"
|
||||
version = "0.22.0"
|
||||
version = "0.21.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1962a33ed2a201c637fc14a4e0fd4e06e6edfdeee6a5fede0dab55507ad74cf7"
|
||||
checksum = "a5e00b96a521718e08e03b1a622f01c8a8deb50719335de3f60b3b3950f069d8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"indoc",
|
||||
"libc",
|
||||
"memoffset",
|
||||
"once_cell",
|
||||
"parking_lot 0.12.1",
|
||||
"portable-atomic",
|
||||
"pyo3-build-config",
|
||||
"pyo3-ffi",
|
||||
@ -2014,9 +2004,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-build-config"
|
||||
version = "0.22.0"
|
||||
version = "0.21.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab7164b2202753bd33afc7f90a10355a719aa973d1f94502c50d06f3488bc420"
|
||||
checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"target-lexicon",
|
||||
@ -2024,9 +2014,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-ffi"
|
||||
version = "0.22.0"
|
||||
version = "0.21.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6424906ca49013c0829c5c1ed405e20e2da2dc78b82d198564880a704e6a7b7"
|
||||
checksum = "01be5843dc60b916ab4dad1dca6d20b9b4e6ddc8e15f50c47fe6d85f1fb97403"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"pyo3-build-config",
|
||||
@ -2034,9 +2024,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-macros"
|
||||
version = "0.22.0"
|
||||
version = "0.21.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82b2f19e153122d64afd8ce7aaa72f06a00f52e34e1d1e74b6d71baea396460a"
|
||||
checksum = "77b34069fc0682e11b31dbd10321cbf94808394c56fd996796ce45217dfac53c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"pyo3-macros-backend",
|
||||
@ -2046,11 +2036,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-macros-backend"
|
||||
version = "0.22.0"
|
||||
version = "0.21.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd698c04cac17cf0fe63d47790ab311b8b25542f5cb976b65c374035c50f1eef"
|
||||
checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
"pyo3-build-config",
|
||||
"quote",
|
||||
@ -2606,9 +2596,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.118"
|
||||
version = "1.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
|
||||
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
||||
dependencies = [
|
||||
"indexmap 2.2.5",
|
||||
"itoa",
|
||||
@ -3170,7 +3160,7 @@ dependencies = [
|
||||
"async-trait",
|
||||
"auto_impl",
|
||||
"bytes",
|
||||
"dashmap 5.5.3",
|
||||
"dashmap",
|
||||
"futures",
|
||||
"httparse",
|
||||
"lsp-types",
|
||||
@ -3277,9 +3267,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs"
|
||||
version = "9.0.1"
|
||||
version = "9.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b44017f9f875786e543595076374b9ef7d13465a518dd93d6ccdbf5b432dde8c"
|
||||
checksum = "5e2dcf58e612adda9a83800731e8e4aba04d8a302b9029617b0b6e4b021d5357"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"serde_json",
|
||||
@ -3291,9 +3281,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs-macros"
|
||||
version = "9.0.1"
|
||||
version = "9.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c88cc88fd23b5a04528f3a8436024f20010a16ec18eb23c164b1242f65860130"
|
||||
checksum = "cbdee324e50a7402416d9c25270d3df4241ed528af5d36dda18b6f219551c577"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -3419,10 +3409,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.9.1"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439"
|
||||
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
|
||||
dependencies = [
|
||||
"atomic",
|
||||
"getrandom",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
|
@ -15,10 +15,10 @@ clap = "4.5.7"
|
||||
gloo-utils = "0.2.0"
|
||||
kcl-lib = { path = "kcl" }
|
||||
kittycad.workspace = true
|
||||
serde_json = "1.0.118"
|
||||
serde_json = "1.0.116"
|
||||
tokio = { version = "1.38.0", features = ["sync"] }
|
||||
toml = "0.8.14"
|
||||
uuid = { version = "1.9.1", features = ["v4", "js", "serde"] }
|
||||
uuid = { version = "1.8.0", features = ["v4", "js", "serde"] }
|
||||
wasm-bindgen = "0.2.91"
|
||||
wasm-bindgen-futures = "0.4.42"
|
||||
|
||||
@ -31,7 +31,7 @@ pretty_assertions = "1.4.0"
|
||||
reqwest = { version = "0.11.26", default-features = false }
|
||||
tokio = { version = "1.38.0", features = ["rt-multi-thread", "macros", "time"] }
|
||||
twenty-twenty = "0.8"
|
||||
uuid = { version = "1.9.1", features = ["v4", "js", "serde"] }
|
||||
uuid = { version = "1.8.0", features = ["v4", "js", "serde"] }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
console_error_panic_hook = "0.1.7"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "derive-docs"
|
||||
description = "A tool for generating documentation from Rust derive macros"
|
||||
version = "0.1.19"
|
||||
version = "0.1.18"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -96,16 +96,10 @@ fn do_stdlib_inner(
|
||||
}
|
||||
|
||||
if !ast.sig.generics.params.is_empty() {
|
||||
if ast.sig.generics.params.iter().any(|generic_type| match generic_type {
|
||||
syn::GenericParam::Lifetime(_) => false,
|
||||
syn::GenericParam::Type(_) => true,
|
||||
syn::GenericParam::Const(_) => true,
|
||||
}) {
|
||||
errors.push(Error::new_spanned(
|
||||
&ast.sig.generics,
|
||||
"Stdlib functions may not be generic over types or constants, only lifetimes.",
|
||||
));
|
||||
}
|
||||
errors.push(Error::new_spanned(
|
||||
&ast.sig.generics,
|
||||
"generics are not permitted for stdlib functions",
|
||||
));
|
||||
}
|
||||
|
||||
if ast.sig.variadic.is_some() {
|
||||
@ -656,12 +650,7 @@ impl Parse for ItemFnForSignature {
|
||||
}
|
||||
|
||||
fn clean_ty_string(t: &str) -> (String, proc_macro2::TokenStream) {
|
||||
let mut ty_string = t
|
||||
.replace("& 'a", "")
|
||||
.replace('&', "")
|
||||
.replace("mut", "")
|
||||
.replace("< 'a >", "")
|
||||
.replace(' ', "");
|
||||
let mut ty_string = t.replace('&', "").replace("mut", "").replace(' ', "");
|
||||
if ty_string.starts_with("Args") {
|
||||
ty_string = "Args".to_string();
|
||||
}
|
||||
@ -761,7 +750,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
|
||||
is_mock: true,
|
||||
};
|
||||
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -795,7 +784,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
|
||||
let program = parser.ast().unwrap();
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default()).await.unwrap();
|
||||
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
|
||||
// Zoom to fit.
|
||||
ctx.engine
|
||||
|
@ -35,56 +35,6 @@ fn test_get_inner_array_type() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_args_with_refs() {
|
||||
let (item, mut errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "someFn",
|
||||
},
|
||||
quote! {
|
||||
/// Docs
|
||||
/// ```
|
||||
/// someFn()
|
||||
/// ```
|
||||
fn someFn(
|
||||
data: &'a str,
|
||||
) -> i32 {
|
||||
3
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
if let Some(e) = errors.pop() {
|
||||
panic!("{e}");
|
||||
}
|
||||
expectorate::assert_contents("tests/args_with_refs.gen", &get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_args_with_lifetime() {
|
||||
let (item, mut errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "someFn",
|
||||
},
|
||||
quote! {
|
||||
/// Docs
|
||||
/// ```
|
||||
/// someFn()
|
||||
/// ```
|
||||
fn someFn<'a>(
|
||||
data: Foo<'a>,
|
||||
) -> i32 {
|
||||
3
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
if let Some(e) = errors.pop() {
|
||||
panic!("{e}");
|
||||
}
|
||||
expectorate::assert_contents("tests/args_with_lifetime.gen", &get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_line_to() {
|
||||
let (item, errors) = do_stdlib(
|
||||
@ -114,6 +64,7 @@ fn test_stdlib_line_to() {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/lineTo.gen", &get_text_fmt(&item).unwrap());
|
||||
|
@ -1,194 +0,0 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_someFn {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_someFn0() {
|
||||
let tokens = crate::token::lexer("someFn()").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: std::sync::Arc::new(crate::fs::FileManager::new()),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_someFn0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
|
||||
client.set_base_url(addr);
|
||||
}
|
||||
|
||||
let tokens = crate::token::lexer("someFn()").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
crate::executor::SourceRange::default(),
|
||||
kittycad::types::ModelingCmd::ZoomToFit {
|
||||
object_ids: Default::default(),
|
||||
padding: 0.1,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let resp = ctx
|
||||
.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
crate::executor::SourceRange::default(),
|
||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||
format: kittycad::types::ImageFormat::Png,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let output_file =
|
||||
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
|
||||
if let kittycad::types::OkWebSocketResponseData::Modeling {
|
||||
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
|
||||
} = &resp
|
||||
{
|
||||
std::fs::write(&output_file, &data.contents.0).unwrap();
|
||||
} else {
|
||||
panic!("Unexpected response from engine: {:?}", resp);
|
||||
}
|
||||
|
||||
let actual = image::io::Reader::open(output_file)
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
twenty_twenty::assert_image(
|
||||
&format!("tests/outputs/{}.png", "serial_test_example_someFn0"),
|
||||
&actual,
|
||||
1.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: someFn\nDocs"]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct SomeFn {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: someFn\nDocs"]
|
||||
pub(crate) const SomeFn: SomeFn = SomeFn {};
|
||||
fn boxed_someFn(
|
||||
args: crate::std::Args,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn std::future::Future<
|
||||
Output = anyhow::Result<crate::executor::MemoryItem, crate::errors::KclError>,
|
||||
> + Send,
|
||||
>,
|
||||
> {
|
||||
Box::pin(someFn(args))
|
||||
}
|
||||
|
||||
impl crate::docs::StdLibFn for SomeFn {
|
||||
fn name(&self) -> String {
|
||||
"someFn".to_string()
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"Docs".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn args(&self) -> Vec<crate::docs::StdLibFnArg> {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = true;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "data".to_string(),
|
||||
type_: "Foo".to_string(),
|
||||
schema: Foo::json_schema(&mut generator),
|
||||
required: true,
|
||||
}]
|
||||
}
|
||||
|
||||
fn return_value(&self) -> Option<crate::docs::StdLibFnArg> {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = true;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "i32".to_string(),
|
||||
schema: <i32>::json_schema(&mut generator),
|
||||
required: true,
|
||||
})
|
||||
}
|
||||
|
||||
fn unpublished(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn deprecated(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["someFn()"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb).unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_someFn
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" Docs"]
|
||||
#[doc = r" ```"]
|
||||
#[doc = r" someFn()"]
|
||||
#[doc = r" ```"]
|
||||
fn someFn<'a>(data: Foo<'a>) -> i32 {
|
||||
3
|
||||
}
|
@ -1,194 +0,0 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_someFn {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_someFn0() {
|
||||
let tokens = crate::token::lexer("someFn()").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: std::sync::Arc::new(crate::fs::FileManager::new()),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_someFn0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
|
||||
client.set_base_url(addr);
|
||||
}
|
||||
|
||||
let tokens = crate::token::lexer("someFn()").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
crate::executor::SourceRange::default(),
|
||||
kittycad::types::ModelingCmd::ZoomToFit {
|
||||
object_ids: Default::default(),
|
||||
padding: 0.1,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let resp = ctx
|
||||
.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
crate::executor::SourceRange::default(),
|
||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||
format: kittycad::types::ImageFormat::Png,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let output_file =
|
||||
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
|
||||
if let kittycad::types::OkWebSocketResponseData::Modeling {
|
||||
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
|
||||
} = &resp
|
||||
{
|
||||
std::fs::write(&output_file, &data.contents.0).unwrap();
|
||||
} else {
|
||||
panic!("Unexpected response from engine: {:?}", resp);
|
||||
}
|
||||
|
||||
let actual = image::io::Reader::open(output_file)
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
twenty_twenty::assert_image(
|
||||
&format!("tests/outputs/{}.png", "serial_test_example_someFn0"),
|
||||
&actual,
|
||||
1.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: someFn\nDocs"]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct SomeFn {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: someFn\nDocs"]
|
||||
pub(crate) const SomeFn: SomeFn = SomeFn {};
|
||||
fn boxed_someFn(
|
||||
args: crate::std::Args,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn std::future::Future<
|
||||
Output = anyhow::Result<crate::executor::MemoryItem, crate::errors::KclError>,
|
||||
> + Send,
|
||||
>,
|
||||
> {
|
||||
Box::pin(someFn(args))
|
||||
}
|
||||
|
||||
impl crate::docs::StdLibFn for SomeFn {
|
||||
fn name(&self) -> String {
|
||||
"someFn".to_string()
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"Docs".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn args(&self) -> Vec<crate::docs::StdLibFnArg> {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = true;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "data".to_string(),
|
||||
type_: "string".to_string(),
|
||||
schema: str::json_schema(&mut generator),
|
||||
required: true,
|
||||
}]
|
||||
}
|
||||
|
||||
fn return_value(&self) -> Option<crate::docs::StdLibFnArg> {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = true;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "i32".to_string(),
|
||||
schema: <i32>::json_schema(&mut generator),
|
||||
required: true,
|
||||
})
|
||||
}
|
||||
|
||||
fn unpublished(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn deprecated(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["someFn()"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb).unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_someFn
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" Docs"]
|
||||
#[doc = r" ```"]
|
||||
#[doc = r" someFn()"]
|
||||
#[doc = r" ```"]
|
||||
fn someFn(data: &'a str) -> i32 {
|
||||
3
|
||||
}
|
@ -16,7 +16,7 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -45,7 +45,7 @@ mod test_examples_show {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
@ -106,7 +106,7 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -135,7 +135,7 @@ mod test_examples_show {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
|
@ -16,7 +16,7 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -45,7 +45,7 @@ mod test_examples_show {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
|
@ -17,7 +17,7 @@ mod test_examples_my_func {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -47,7 +47,7 @@ mod test_examples_my_func {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
@ -108,7 +108,7 @@ mod test_examples_my_func {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -137,7 +137,7 @@ mod test_examples_my_func {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
|
@ -17,7 +17,7 @@ mod test_examples_line_to {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -47,7 +47,7 @@ mod test_examples_line_to {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
@ -108,7 +108,7 @@ mod test_examples_line_to {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -137,7 +137,7 @@ mod test_examples_line_to {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
|
@ -16,7 +16,7 @@ mod test_examples_min {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -45,7 +45,7 @@ mod test_examples_min {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
@ -106,7 +106,7 @@ mod test_examples_min {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -135,7 +135,7 @@ mod test_examples_min {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
|
@ -16,7 +16,7 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -45,7 +45,7 @@ mod test_examples_show {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
|
@ -16,7 +16,7 @@ mod test_examples_import {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -45,7 +45,7 @@ mod test_examples_import {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
|
@ -16,7 +16,7 @@ mod test_examples_import {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -45,7 +45,7 @@ mod test_examples_import {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
|
@ -16,7 +16,7 @@ mod test_examples_import {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -45,7 +45,7 @@ mod test_examples_import {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
|
@ -16,7 +16,7 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
is_mock: true,
|
||||
};
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -45,7 +45,7 @@ mod test_examples_show {
|
||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
ctx.run(program, None).await.unwrap();
|
||||
ctx.engine
|
||||
.send_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
|