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
|
- name: Benchmark kcl library
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |-
|
run: |-
|
||||||
cd src/wasm-lib/kcl; cargo bench --all-features -- iai
|
cd src/wasm-lib/kcl; cargo bench -- iai
|
||||||
env:
|
|
||||||
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}
|
|
||||||
|
|
||||||
|
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
|
'.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' \
|
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
|
'.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
|
'.productName=$name' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
@ -286,9 +286,9 @@ jobs:
|
|||||||
|
|
||||||
yarn tauri build --target "${target}" --verbose --config src-tauri/tauri.app-store.conf.json
|
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"
|
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"
|
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"
|
cp_dir="src-tauri/target/${target}/release/bundle/macos/zoo-modeling-app.app/Contents/embedded.provisionprofile"
|
||||||
entitlements="src-tauri/entitlements/app-store.entitlements"
|
entitlements="src-tauri/entitlements/app-store.entitlements"
|
||||||
|
|
||||||
cp "${profile}" "${cp_dir}"
|
cp "${profile}" "${cp_dir}"
|
||||||
@ -312,7 +312,7 @@ jobs:
|
|||||||
uses: apple-actions/upload-testflight-build@v1
|
uses: apple-actions/upload-testflight-build@v1
|
||||||
if: ${{ github.event_name == 'schedule' && matrix.os == 'macos-14' }}
|
if: ${{ github.event_name == 'schedule' && matrix.os == 'macos-14' }}
|
||||||
with:
|
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 }}
|
issuer-id: ${{ secrets.APPLE_STORE_ISSUER_ID }}
|
||||||
api-key-id: ${{ secrets.APPLE_STORE_API_KEY_ID }}
|
api-key-id: ${{ secrets.APPLE_STORE_API_KEY_ID }}
|
||||||
api-private-key: ${{ secrets.APPLE_STORE_API_PRIVATE_KEY }}
|
api-private-key: ${{ secrets.APPLE_STORE_API_PRIVATE_KEY }}
|
||||||
@ -367,7 +367,7 @@ jobs:
|
|||||||
export VITE_KC_API_BASE_URL
|
export VITE_KC_API_BASE_URL
|
||||||
xvfb-run yarn test:e2e:tauri
|
xvfb-run yarn test:e2e:tauri
|
||||||
env:
|
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 }}
|
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
|
|
||||||
- name: Run e2e tests (windows only)
|
- name: Run e2e tests (windows only)
|
||||||
@ -376,7 +376,7 @@ jobs:
|
|||||||
cargo install tauri-driver --force
|
cargo install tauri-driver --force
|
||||||
yarn wdio run wdio.conf.ts
|
yarn wdio run wdio.conf.ts
|
||||||
env:
|
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 }}
|
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' }}
|
VITE_KC_API_BASE_URL: ${{ env.BUILD_RELEASE == 'true' && 'https://api.zoo.dev' || 'https://api.dev.zoo.dev' }}
|
||||||
E2E_TAURI_ENABLED: true
|
E2E_TAURI_ENABLED: true
|
||||||
|
52
.github/workflows/playwright.yml
vendored
@ -38,8 +38,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest-8-cores
|
runs-on: ubuntu-latest-8-cores
|
||||||
needs: check-rust-changes
|
needs: check-rust-changes
|
||||||
steps:
|
steps:
|
||||||
- name: Tune GitHub-hosted runner network
|
|
||||||
uses: smorimoto/tune-github-hosted-runner-network@v1
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
@ -92,17 +90,11 @@ jobs:
|
|||||||
- name: build web
|
- name: build web
|
||||||
run: yarn build:local
|
run: yarn build:local
|
||||||
- name: Run ubuntu/chrome snapshots
|
- 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:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
|
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
|
- name: check for changes
|
||||||
id: git-check
|
id: git-check
|
||||||
run: |
|
run: |
|
||||||
@ -129,7 +121,7 @@ jobs:
|
|||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: steps.git-check.outputs.modified == 'true'
|
if: steps.git-check.outputs.modified == 'true'
|
||||||
with:
|
with:
|
||||||
name: playwright-report-ubuntu-${{ github.sha }}
|
name: playwright-report
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
# if have previous run results, use them
|
# if have previous run results, use them
|
||||||
@ -137,18 +129,16 @@ jobs:
|
|||||||
if: always()
|
if: always()
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
name: test-results-ubuntu-${{ github.sha }}
|
name: test-results
|
||||||
path: test-results/
|
path: test-results/
|
||||||
- name: Run ubuntu/chrome flow retry failures
|
- name: Run ubuntu/chrome flow retry failures
|
||||||
id: retry
|
id: retry
|
||||||
if: always()
|
if: always()
|
||||||
run: |
|
run: |
|
||||||
if [[ -d "test-results" ]];
|
ls -1 "test-results"
|
||||||
then if [[ $(ls -1 "test-results" | wc -l) != "0" ]];
|
if [[ $(ls -1 "test-results" | wc -l) == "0" ]];
|
||||||
then echo "retried=true" >> $GITHUB_OUTPUT;
|
then echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
|
||||||
else echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
|
else echo "retried=true" >> $GITHUB_OUTPUT;
|
||||||
fi;
|
|
||||||
else echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
|
|
||||||
fi;
|
fi;
|
||||||
yarn playwright test --project="Google Chrome" --last-failed e2e/playwright/flow-tests.spec.ts
|
yarn playwright test --project="Google Chrome" --last-failed e2e/playwright/flow-tests.spec.ts
|
||||||
env:
|
env:
|
||||||
@ -163,25 +153,23 @@ jobs:
|
|||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: test-results-ubuntu-${{ github.sha }}
|
name: test-results
|
||||||
path: test-results/
|
path: test-results/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
overwrite: true
|
overwrite: true
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: playwright-report-ubuntu-${{ github.sha }}
|
name: playwright-report
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
overwrite: true
|
overwrite: true
|
||||||
|
|
||||||
playwright-macos:
|
playwright-macos:
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
runs-on: macos-14-large
|
runs-on: macos-14
|
||||||
needs: check-rust-changes
|
needs: check-rust-changes
|
||||||
steps:
|
steps:
|
||||||
- name: Tune GitHub-hosted runner network
|
|
||||||
uses: smorimoto/tune-github-hosted-runner-network@v1
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
@ -239,25 +227,23 @@ jobs:
|
|||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
name: test-results-macos-${{ github.sha }}
|
name: test-results
|
||||||
path: test-results/
|
path: test-results/
|
||||||
- name: Run macos/safari flow retry failures
|
- name: Run macos/safari flow retry failures
|
||||||
id: retry
|
id: retry
|
||||||
if: always()
|
continue-on-error: true
|
||||||
|
if: ${{ success() }}
|
||||||
run: |
|
run: |
|
||||||
if [[ -d "test-results" ]];
|
if [ -d "test-results" ];
|
||||||
then if [[ $(ls -1 "test-results" | wc -l) != "0" ]];
|
then echo "retried=true" >> $GITHUB_OUTPUT;
|
||||||
then echo "retried=true" >> $GITHUB_OUTPUT;
|
else echo "retried=false" >> $GITHUB_OUTPUT;
|
||||||
else echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
|
|
||||||
fi;
|
|
||||||
else echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
|
|
||||||
fi;
|
fi;
|
||||||
yarn playwright test --project="webkit" --last-failed e2e/playwright/flow-tests.spec.ts
|
yarn playwright test --project="webkit" --last-failed e2e/playwright/flow-tests.spec.ts
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
- name: Run macos/safari flow
|
- 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)
|
# 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
|
# 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
|
run: yarn playwright test --project="webkit" e2e/playwright/flow-tests.spec.ts
|
||||||
@ -267,14 +253,14 @@ jobs:
|
|||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
with:
|
with:
|
||||||
name: test-results-macos-${{ github.sha }}
|
name: test-results
|
||||||
path: test-results/
|
path: test-results/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
overwrite: true
|
overwrite: true
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
with:
|
with:
|
||||||
name: playwright-report-macos-${{ github.sha }}
|
name: playwright-report
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
overwrite: true
|
overwrite: true
|
||||||
|
@ -17,8 +17,11 @@ angleToMatchLengthX(segment_name: TagIdentifier, to: number, sketch_group: Sketc
|
|||||||
```js
|
```js
|
||||||
const sketch001 = startSketchOn('XZ')
|
const sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([2, 5], %, $seg01)
|
|> line([2, 5], %, 'seg01')
|
||||||
|> angledLineToX([-angleToMatchLengthX(seg01, 7, %), 10], %)
|
|> angledLineToX([
|
||||||
|
-angleToMatchLengthX('seg01', 7, %),
|
||||||
|
10
|
||||||
|
], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
const extrusion = extrude(5, sketch001)
|
const extrusion = extrude(5, sketch001)
|
||||||
|
@ -17,9 +17,9 @@ angleToMatchLengthY(segment_name: TagIdentifier, to: number, sketch_group: Sketc
|
|||||||
```js
|
```js
|
||||||
const sketch001 = startSketchOn('XZ')
|
const sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([1, 2], %, $seg01)
|
|> line([1, 2], %, 'seg01')
|
||||||
|> angledLine({
|
|> angledLine({
|
||||||
angle: angleToMatchLengthY(seg01, 15, %),
|
angle: angleToMatchLengthY('seg01', 15, %),
|
||||||
length: 5
|
length: 5
|
||||||
}, %)
|
}, %)
|
||||||
|> yLineTo(0, %)
|
|> yLineTo(0, %)
|
||||||
|
@ -17,10 +17,10 @@ angledLineOfXLength(data: AngledLineData, sketch_group: SketchGroup, tag?: TagDe
|
|||||||
```js
|
```js
|
||||||
const sketch001 = startSketchOn('XZ')
|
const sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> angledLineOfXLength({ angle: 45, length: 10 }, %, $edge1)
|
|> angledLineOfXLength({ angle: 45, length: 10 }, %, "edge1")
|
||||||
|> angledLineOfXLength({ angle: -15, length: 20 }, %, $edge2)
|
|> angledLineOfXLength({ angle: -15, length: 20 }, %, "edge2")
|
||||||
|> line([0, -5], %)
|
|> line([0, -5], %)
|
||||||
|> close(%, $edge3)
|
|> close(%, "edge3")
|
||||||
|
|
||||||
const extrusion = extrude(10, sketch001)
|
const extrusion = extrude(10, sketch001)
|
||||||
```
|
```
|
||||||
|
@ -18,7 +18,7 @@ angledLineThatIntersects(data: AngledLineThatIntersectsData, sketch_group: Sketc
|
|||||||
const exampleSketch = startSketchOn('XZ')
|
const exampleSketch = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> lineTo([5, 10], %)
|
|> lineTo([5, 10], %)
|
||||||
|> lineTo([-10, 10], %, $lineToIntersect)
|
|> lineTo([-10, 10], %, "lineToIntersect")
|
||||||
|> lineTo([0, 20], %)
|
|> lineTo([0, 20], %)
|
||||||
|> angledLineThatIntersects({
|
|> angledLineThatIntersects({
|
||||||
angle: 80,
|
angle: 80,
|
||||||
|
@ -22,19 +22,19 @@ const chamferLength = 2
|
|||||||
|
|
||||||
const mountingPlateSketch = startSketchOn("XY")
|
const mountingPlateSketch = startSketchOn("XY")
|
||||||
|> startProfileAt([-width / 2, -length / 2], %)
|
|> startProfileAt([-width / 2, -length / 2], %)
|
||||||
|> lineTo([width / 2, -length / 2], %, $edge1)
|
|> lineTo([width / 2, -length / 2], %, 'edge1')
|
||||||
|> lineTo([width / 2, length / 2], %, $edge2)
|
|> lineTo([width / 2, length / 2], %, 'edge2')
|
||||||
|> lineTo([-width / 2, length / 2], %, $edge3)
|
|> lineTo([-width / 2, length / 2], %, 'edge3')
|
||||||
|> close(%, $edge4)
|
|> close(%, 'edge4')
|
||||||
|
|
||||||
const mountingPlate = extrude(thickness, mountingPlateSketch)
|
const mountingPlate = extrude(thickness, mountingPlateSketch)
|
||||||
|> chamfer({
|
|> chamfer({
|
||||||
length: chamferLength,
|
length: chamferLength,
|
||||||
tags: [
|
tags: [
|
||||||
getNextAdjacentEdge(edge1, %),
|
getNextAdjacentEdge('edge1', %),
|
||||||
getNextAdjacentEdge(edge2, %),
|
getNextAdjacentEdge('edge2', %),
|
||||||
getNextAdjacentEdge(edge3, %),
|
getNextAdjacentEdge('edge3', %),
|
||||||
getNextAdjacentEdge(edge4, %)
|
getNextAdjacentEdge('edge4', %)
|
||||||
]
|
]
|
||||||
}, %)
|
}, %)
|
||||||
```
|
```
|
||||||
|
@ -9,7 +9,7 @@ Sketch a circle.
|
|||||||
|
|
||||||
|
|
||||||
```js
|
```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
|
### Examples
|
||||||
@ -41,6 +41,14 @@ const example = extrude(5, exampleSketch)
|
|||||||
|
|
||||||
* `center`: `[number]` (REQUIRED)
|
* `center`: `[number]` (REQUIRED)
|
||||||
* `radius`: `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)
|
* `sketch_surface_or_group`: `SketchSurfaceOrGroup` - A sketch surface or a sketch group. (REQUIRED)
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
@ -502,14 +510,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
}],
|
}],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
* `tag`: `TagDeclarator` (OPTIONAL)
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
end: number,
|
|
||||||
start: number,
|
|
||||||
value: string,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -22,19 +22,19 @@ const filletRadius = 2
|
|||||||
|
|
||||||
const mountingPlateSketch = startSketchOn("XY")
|
const mountingPlateSketch = startSketchOn("XY")
|
||||||
|> startProfileAt([-width / 2, -length / 2], %)
|
|> startProfileAt([-width / 2, -length / 2], %)
|
||||||
|> lineTo([width / 2, -length / 2], %, $edge1)
|
|> lineTo([width / 2, -length / 2], %, 'edge1')
|
||||||
|> lineTo([width / 2, length / 2], %, $edge2)
|
|> lineTo([width / 2, length / 2], %, 'edge2')
|
||||||
|> lineTo([-width / 2, length / 2], %, $edge3)
|
|> lineTo([-width / 2, length / 2], %, 'edge3')
|
||||||
|> close(%, $edge4)
|
|> close(%, 'edge4')
|
||||||
|
|
||||||
const mountingPlate = extrude(thickness, mountingPlateSketch)
|
const mountingPlate = extrude(thickness, mountingPlateSketch)
|
||||||
|> fillet({
|
|> fillet({
|
||||||
radius: filletRadius,
|
radius: filletRadius,
|
||||||
tags: [
|
tags: [
|
||||||
getNextAdjacentEdge(edge1, %),
|
getNextAdjacentEdge('edge1', %),
|
||||||
getNextAdjacentEdge(edge2, %),
|
getNextAdjacentEdge('edge2', %),
|
||||||
getNextAdjacentEdge(edge3, %),
|
getNextAdjacentEdge('edge3', %),
|
||||||
getNextAdjacentEdge(edge4, %)
|
getNextAdjacentEdge('edge4', %)
|
||||||
]
|
]
|
||||||
}, %)
|
}, %)
|
||||||
```
|
```
|
||||||
|
@ -17,7 +17,7 @@ getEdge(tag: TagIdentifier, extrude_group: ExtrudeGroup) -> Uuid
|
|||||||
```js
|
```js
|
||||||
const box = startSketchOn('XZ')
|
const box = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([0, 10], %, $revolveAxis)
|
|> line([0, 10], %, 'revolveAxis')
|
||||||
|> line([10, 0], %)
|
|> line([10, 0], %)
|
||||||
|> line([0, -10], %)
|
|> line([0, -10], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
@ -30,7 +30,7 @@ const revolution = startSketchOn(box, "revolveAxis")
|
|||||||
|> line([0, -10], %)
|
|> line([0, -10], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|> revolve({
|
|> revolve({
|
||||||
axis: getEdge(revolveAxis, box),
|
axis: getEdge('revolveAxis', box),
|
||||||
angle: 90
|
angle: 90
|
||||||
}, %)
|
}, %)
|
||||||
```
|
```
|
||||||
|
@ -21,13 +21,15 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
|> angledLine({ angle: 60, length: 10 }, %)
|
|> angledLine({ angle: 60, length: 10 }, %)
|
||||||
|> angledLine({ angle: 120, length: 10 }, %)
|
|> angledLine({ angle: 120, length: 10 }, %)
|
||||||
|> line([-10, 0], %)
|
|> line([-10, 0], %)
|
||||||
|> angledLine({ angle: 240, length: 10 }, %, $referenceEdge)
|
|> angledLine({ angle: 240, length: 10 }, %, 'referenceEdge')
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
const example = extrude(5, exampleSketch)
|
const example = extrude(5, exampleSketch)
|
||||||
|> fillet({
|
|> fillet({
|
||||||
radius: 3,
|
radius: 3,
|
||||||
tags: [getNextAdjacentEdge(referenceEdge, %)]
|
tags: [
|
||||||
|
getNextAdjacentEdge("referenceEdge", %)
|
||||||
|
]
|
||||||
}, %)
|
}, %)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -21,13 +21,13 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
|> angledLine({ angle: 60, length: 10 }, %)
|
|> angledLine({ angle: 60, length: 10 }, %)
|
||||||
|> angledLine({ angle: 120, length: 10 }, %)
|
|> angledLine({ angle: 120, length: 10 }, %)
|
||||||
|> line([-10, 0], %)
|
|> line([-10, 0], %)
|
||||||
|> angledLine({ angle: 240, length: 10 }, %, $referenceEdge)
|
|> angledLine({ angle: 240, length: 10 }, %, 'referenceEdge')
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
const example = extrude(5, exampleSketch)
|
const example = extrude(5, exampleSketch)
|
||||||
|> fillet({
|
|> fillet({
|
||||||
radius: 3,
|
radius: 3,
|
||||||
tags: [getOppositeEdge(referenceEdge, %)]
|
tags: [getOppositeEdge("referenceEdge", %)]
|
||||||
}, %)
|
}, %)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -21,14 +21,14 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
|> angledLine({ angle: 60, length: 10 }, %)
|
|> angledLine({ angle: 60, length: 10 }, %)
|
||||||
|> angledLine({ angle: 120, length: 10 }, %)
|
|> angledLine({ angle: 120, length: 10 }, %)
|
||||||
|> line([-10, 0], %)
|
|> line([-10, 0], %)
|
||||||
|> angledLine({ angle: 240, length: 10 }, %, $referenceEdge)
|
|> angledLine({ angle: 240, length: 10 }, %, 'referenceEdge')
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
const example = extrude(5, exampleSketch)
|
const example = extrude(5, exampleSketch)
|
||||||
|> fillet({
|
|> fillet({
|
||||||
radius: 3,
|
radius: 3,
|
||||||
tags: [
|
tags: [
|
||||||
getPreviousAdjacentEdge(referenceEdge, %)
|
getPreviousAdjacentEdge("referenceEdge", %)
|
||||||
]
|
]
|
||||||
}, %)
|
}, %)
|
||||||
```
|
```
|
||||||
|
@ -55,7 +55,6 @@ layout: manual
|
|||||||
* [`patternCircular3d`](kcl/patternCircular3d)
|
* [`patternCircular3d`](kcl/patternCircular3d)
|
||||||
* [`patternLinear2d`](kcl/patternLinear2d)
|
* [`patternLinear2d`](kcl/patternLinear2d)
|
||||||
* [`patternLinear3d`](kcl/patternLinear3d)
|
* [`patternLinear3d`](kcl/patternLinear3d)
|
||||||
* [`patternTransform`](kcl/patternTransform)
|
|
||||||
* [`pi`](kcl/pi)
|
* [`pi`](kcl/pi)
|
||||||
* [`pow`](kcl/pow)
|
* [`pow`](kcl/pow)
|
||||||
* [`profileStart`](kcl/profileStart)
|
* [`profileStart`](kcl/profileStart)
|
||||||
|
@ -17,9 +17,9 @@ profileStart(sketch_group: SketchGroup) -> [number]
|
|||||||
```js
|
```js
|
||||||
const sketch001 = startSketchOn('XY')
|
const sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([5, 2], %)
|
|> startProfileAt([5, 2], %)
|
||||||
|> angledLine({ angle: 120, length: 50 }, %, $seg01)
|
|> angledLine({ angle: 120, length: 50 }, %, 'seg01')
|
||||||
|> angledLine({
|
|> angledLine({
|
||||||
angle: segAng(seg01, %) + 120,
|
angle: segAng('seg01', %) + 120,
|
||||||
length: 50
|
length: 50
|
||||||
}, %)
|
}, %)
|
||||||
|> lineTo(profileStart(%), %)
|
|> lineTo(profileStart(%), %)
|
||||||
|
@ -99,7 +99,7 @@ const box = startSketchOn('XY')
|
|||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([0, 20], %)
|
|> line([0, 20], %)
|
||||||
|> line([20, 0], %)
|
|> line([20, 0], %)
|
||||||
|> line([0, -20], %, $revolveAxis)
|
|> line([0, -20], %, 'revolveAxis')
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|> extrude(20, %)
|
|> extrude(20, %)
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ const sketch001 = startSketchOn(box, "END")
|
|||||||
|> circle([10, 10], 4, %)
|
|> circle([10, 10], 4, %)
|
||||||
|> revolve({
|
|> revolve({
|
||||||
angle: 90,
|
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')
|
const exampleSketch = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([10, 0], %)
|
|> line([10, 0], %)
|
||||||
|> line([5, 10], %, $seg01)
|
|> line([5, 10], %, 'seg01')
|
||||||
|> line([-10, 0], %)
|
|> line([-10, 0], %)
|
||||||
|> angledLine([segAng(seg01, %), 10], %)
|
|> angledLine([segAng('seg01', %), 10], %)
|
||||||
|> line([-10, 0], %)
|
|> line([-10, 0], %)
|
||||||
|> angledLine([segAng(seg01, %), -15], %)
|
|> angledLine([segAng('seg01', %), -15], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
const example = extrude(4, exampleSketch)
|
const example = extrude(4, exampleSketch)
|
||||||
|
@ -17,9 +17,9 @@ segEndX(segment_name: TagIdentifier, sketch_group: SketchGroup) -> number
|
|||||||
```js
|
```js
|
||||||
const exampleSketch = startSketchOn('XZ')
|
const exampleSketch = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([20, 0], %, $thing)
|
|> line([20, 0], %, "thing")
|
||||||
|> line([0, 5], %)
|
|> line([0, 5], %)
|
||||||
|> line([segEndX(thing, %), 0], %)
|
|> line([segEndX("thing", %), 0], %)
|
||||||
|> line([-20, 10], %)
|
|> line([-20, 10], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ segEndY(segment_name: TagIdentifier, sketch_group: SketchGroup) -> number
|
|||||||
const exampleSketch = startSketchOn('XZ')
|
const exampleSketch = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([20, 0], %)
|
|> line([20, 0], %)
|
||||||
|> line([0, 3], %, $thing)
|
|> line([0, 3], %, "thing")
|
||||||
|> line([-10, 0], %)
|
|> line([-10, 0], %)
|
||||||
|> line([0, segEndY(thing, %)], %)
|
|> line([0, segEndY("thing", %)], %)
|
||||||
|> line([-10, 0], %)
|
|> line([-10, 0], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
|
@ -17,9 +17,12 @@ segLen(segment_name: TagIdentifier, sketch_group: SketchGroup) -> number
|
|||||||
```js
|
```js
|
||||||
const exampleSketch = startSketchOn("XZ")
|
const exampleSketch = startSketchOn("XZ")
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> angledLine({ angle: 60, length: 10 }, %, $thing)
|
|> angledLine({ angle: 60, length: 10 }, %, "thing")
|
||||||
|> tangentialArc({ offset: -120, radius: 5 }, %)
|
|> tangentialArc({ offset: -120, radius: 5 }, %)
|
||||||
|> angledLine({ angle: -60, length: segLen(thing, %) }, %)
|
|> angledLine({
|
||||||
|
angle: -60,
|
||||||
|
length: segLen("thing", %)
|
||||||
|
}, %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
const example = extrude(5, exampleSketch)
|
const example = extrude(5, exampleSketch)
|
||||||
|
@ -49,7 +49,7 @@ const example003 = extrude(5, exampleSketch003)
|
|||||||
const exampleSketch = startSketchOn("XY")
|
const exampleSketch = startSketchOn("XY")
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([10, 0], %)
|
|> line([10, 0], %)
|
||||||
|> line([0, 10], %, $sketchingFace)
|
|> line([0, 10], %, 'sketchingFace')
|
||||||
|> line([-10, 0], %)
|
|> line([-10, 0], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ const exampleSketch002 = startSketchOn(example, 'sketchingFace')
|
|||||||
|> line([8, 0], %)
|
|> line([8, 0], %)
|
||||||
|> line([0, 8], %)
|
|> line([0, 8], %)
|
||||||
|> line([-8, 0], %)
|
|> line([-8, 0], %)
|
||||||
|> close(%, $sketchingFace002)
|
|> close(%, 'sketchingFace002')
|
||||||
|
|
||||||
const example002 = extrude(10, exampleSketch002)
|
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()
|
await page.getByTestId('clear-commands').click()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function expectCmdLog(page: Page, locatorStr: string, timeout = 5000) {
|
async function expectCmdLog(page: Page, locatorStr: string) {
|
||||||
await expect(page.locator(locatorStr).last()).toBeVisible({ timeout })
|
await expect(page.locator(locatorStr).last()).toBeVisible()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitForDefaultPlanesToBeVisible(page: Page) {
|
async function waitForDefaultPlanesToBeVisible(page: Page) {
|
||||||
@ -228,8 +228,7 @@ export async function getUtils(page: Page) {
|
|||||||
await fillInput('z', xyz[2])
|
await fillInput('z', xyz[2])
|
||||||
},
|
},
|
||||||
clearCommandLogs: () => clearCommandLogs(page),
|
clearCommandLogs: () => clearCommandLogs(page),
|
||||||
expectCmdLog: (locatorStr: string, timeout = 5000) =>
|
expectCmdLog: (locatorStr: string) => expectCmdLog(page, locatorStr),
|
||||||
expectCmdLog(page, locatorStr, timeout),
|
|
||||||
openKclCodePanel: () => openKclCodePanel(page),
|
openKclCodePanel: () => openKclCodePanel(page),
|
||||||
closeKclCodePanel: () => closeKclCodePanel(page),
|
closeKclCodePanel: () => closeKclCodePanel(page),
|
||||||
openDebugPanel: () => openDebugPanel(page),
|
openDebugPanel: () => openDebugPanel(page),
|
||||||
@ -301,19 +300,11 @@ export async function getUtils(page: Page) {
|
|||||||
(screenshot.width * coords.y * pixMultiplier +
|
(screenshot.width * coords.y * pixMultiplier +
|
||||||
coords.x * pixMultiplier) *
|
coords.x * pixMultiplier) *
|
||||||
4 // rbga is 4 channels
|
4 // rbga is 4 channels
|
||||||
const maxDiff = Math.max(
|
return Math.max(
|
||||||
Math.abs(screenshot.data[index] - expected[0]),
|
Math.abs(screenshot.data[index] - expected[0]),
|
||||||
Math.abs(screenshot.data[index + 1] - expected[1]),
|
Math.abs(screenshot.data[index + 1] - expected[1]),
|
||||||
Math.abs(screenshot.data[index + 2] - expected[2])
|
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) =>
|
doAndWaitForImageDiff: (fn: () => Promise<any>, diffCount = 200) =>
|
||||||
new Promise(async (resolve) => {
|
new Promise(async (resolve) => {
|
||||||
|
@ -89,7 +89,7 @@
|
|||||||
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e",
|
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e",
|
||||||
"fetch:wasm": "./get-latest-wasm-bundle.sh",
|
"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-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",
|
"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\"",
|
"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",
|
"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({
|
export default defineConfig({
|
||||||
testDir: './e2e/playwright',
|
testDir: './e2e/playwright',
|
||||||
/* Run tests in files in parallel */
|
/* 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. */
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
forbidOnly: !!process.env.CI,
|
forbidOnly: !!process.env.CI,
|
||||||
/* Retry on CI only */
|
/* Retry on CI only */
|
||||||
retries: process.env.CI ? 3 : 0,
|
retries: process.env.CI ? 3 : 0,
|
||||||
/* Different amount of parallelism on CI and local. */
|
/* 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 to use. See https://playwright.dev/docs/test-reporters */
|
||||||
reporter: 'html',
|
reporter: 'html',
|
||||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
/* 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",
|
"system-deps",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atomic-waker"
|
name = "atomic-waker"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
@ -1140,20 +1146,6 @@ dependencies = [
|
|||||||
"parking_lot_core 0.9.9",
|
"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]]
|
[[package]]
|
||||||
name = "data-encoding"
|
name = "data-encoding"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
@ -2576,7 +2568,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.1.67"
|
version = "0.1.65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"approx",
|
"approx",
|
||||||
@ -2586,7 +2578,7 @@ dependencies = [
|
|||||||
"bson",
|
"bson",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"dashmap 6.0.1",
|
"dashmap",
|
||||||
"databake",
|
"databake",
|
||||||
"derive-docs",
|
"derive-docs",
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
@ -4546,9 +4538,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.118"
|
version = "1.0.116"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
|
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.2.6",
|
"indexmap 2.2.6",
|
||||||
"itoa 1.0.11",
|
"itoa 1.0.11",
|
||||||
@ -5874,7 +5866,7 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"auto_impl",
|
"auto_impl",
|
||||||
"bytes",
|
"bytes",
|
||||||
"dashmap 5.5.3",
|
"dashmap",
|
||||||
"futures",
|
"futures",
|
||||||
"httparse",
|
"httparse",
|
||||||
"lsp-types",
|
"lsp-types",
|
||||||
@ -6224,10 +6216,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.9.1"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439"
|
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"atomic",
|
||||||
"getrandom 0.2.14",
|
"getrandom 0.2.14",
|
||||||
"serde",
|
"serde",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "app"
|
name = "zoo-modeling-app"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "The Zoo Modeling App"
|
description = "The Zoo Modeling App"
|
||||||
authors = ["Zoo Engineers <eng@zoo.dev>"]
|
authors = ["Zoo Engineers <eng@zoo.dev>"]
|
||||||
|
@ -73,6 +73,6 @@
|
|||||||
"open": true
|
"open": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"productName": "Zoo Modeling App",
|
"productName": "zoo-modeling-app",
|
||||||
"version": "0.22.6"
|
"version": "0.22.6"
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ import { LowerRightControls } from 'components/LowerRightControls'
|
|||||||
import ModalContainer from 'react-modal-promise'
|
import ModalContainer from 'react-modal-promise'
|
||||||
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
||||||
import Gizmo from 'components/Gizmo'
|
import Gizmo from 'components/Gizmo'
|
||||||
import { CoreDumpManager } from 'lib/coredump'
|
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
useRefreshSettings(paths.FILE + 'SETTINGS')
|
useRefreshSettings(paths.FILE + 'SETTINGS')
|
||||||
@ -56,11 +55,7 @@ export function App() {
|
|||||||
setHtmlRef(ref)
|
setHtmlRef(ref)
|
||||||
}, [ref])
|
}, [ref])
|
||||||
|
|
||||||
const { auth, settings } = useSettingsAuthContext()
|
const { settings } = useSettingsAuthContext()
|
||||||
const token = auth?.context?.token
|
|
||||||
|
|
||||||
const coreDumpManager = new CoreDumpManager(engineCommandManager, ref, token)
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
app: { onboardingStatus },
|
app: { onboardingStatus },
|
||||||
} = settings.context
|
} = settings.context
|
||||||
@ -134,7 +129,7 @@ export function App() {
|
|||||||
<ModelingSidebar paneOpacity={paneOpacity} />
|
<ModelingSidebar paneOpacity={paneOpacity} />
|
||||||
<Stream />
|
<Stream />
|
||||||
{/* <CamToggle /> */}
|
{/* <CamToggle /> */}
|
||||||
<LowerRightControls coreDumpManager={coreDumpManager}>
|
<LowerRightControls>
|
||||||
<Gizmo />
|
<Gizmo />
|
||||||
</LowerRightControls>
|
</LowerRightControls>
|
||||||
</div>
|
</div>
|
||||||
|
@ -534,7 +534,7 @@ export class SceneEntities {
|
|||||||
segmentName: 'line' | 'tangentialArcTo' = 'line',
|
segmentName: 'line' | 'tangentialArcTo' = 'line',
|
||||||
shouldTearDown = true
|
shouldTearDown = true
|
||||||
) => {
|
) => {
|
||||||
const _ast = kclManager.ast
|
const _ast = JSON.parse(JSON.stringify(kclManager.ast))
|
||||||
|
|
||||||
const _node1 = getNodeFromPath<VariableDeclaration>(
|
const _node1 = getNodeFromPath<VariableDeclaration>(
|
||||||
_ast,
|
_ast,
|
||||||
@ -692,7 +692,7 @@ export class SceneEntities {
|
|||||||
sketchOrigin: [number, number, number],
|
sketchOrigin: [number, number, number],
|
||||||
rectangleOrigin: [x: number, y: number]
|
rectangleOrigin: [x: number, y: number]
|
||||||
) => {
|
) => {
|
||||||
let _ast = kclManager.ast
|
let _ast = JSON.parse(JSON.stringify(kclManager.ast))
|
||||||
|
|
||||||
const _node1 = getNodeFromPath<VariableDeclaration>(
|
const _node1 = getNodeFromPath<VariableDeclaration>(
|
||||||
_ast,
|
_ast,
|
||||||
@ -723,9 +723,7 @@ export class SceneEntities {
|
|||||||
...getRectangleCallExpressions(rectangleOrigin, tags),
|
...getRectangleCallExpressions(rectangleOrigin, tags),
|
||||||
])
|
])
|
||||||
|
|
||||||
let result = parse(recast(_ast))
|
_ast = parse(recast(_ast))
|
||||||
if (trap(result)) return Promise.reject(result)
|
|
||||||
_ast = result
|
|
||||||
|
|
||||||
const { programMemoryOverride, truncatedAst } = await this.setupSketch({
|
const { programMemoryOverride, truncatedAst } = await this.setupSketch({
|
||||||
sketchPathToNode,
|
sketchPathToNode,
|
||||||
@ -739,7 +737,7 @@ export class SceneEntities {
|
|||||||
sceneInfra.setCallbacks({
|
sceneInfra.setCallbacks({
|
||||||
onMove: async (args) => {
|
onMove: async (args) => {
|
||||||
// Update the width and height of the draft rectangle
|
// Update the width and height of the draft rectangle
|
||||||
const pathToNodeTwo = sketchPathToNode
|
const pathToNodeTwo = JSON.parse(JSON.stringify(sketchPathToNode))
|
||||||
pathToNodeTwo[1][0] = 0
|
pathToNodeTwo[1][0] = 0
|
||||||
|
|
||||||
const _node = getNodeFromPath<VariableDeclaration>(
|
const _node = getNodeFromPath<VariableDeclaration>(
|
||||||
@ -801,9 +799,7 @@ export class SceneEntities {
|
|||||||
if (sketchInit.type === 'PipeExpression') {
|
if (sketchInit.type === 'PipeExpression') {
|
||||||
updateRectangleSketch(sketchInit, x, y, tags[0])
|
updateRectangleSketch(sketchInit, x, y, tags[0])
|
||||||
|
|
||||||
let result = parse(recast(_ast))
|
_ast = parse(recast(_ast))
|
||||||
if (trap(result)) return Promise.reject(result)
|
|
||||||
_ast = result
|
|
||||||
|
|
||||||
// Update the primary AST and unequip the rectangle tool
|
// Update the primary AST and unequip the rectangle tool
|
||||||
await kclManager.executeAstMock(_ast)
|
await kclManager.executeAstMock(_ast)
|
||||||
@ -1007,8 +1003,10 @@ export class SceneEntities {
|
|||||||
PROFILE_START,
|
PROFILE_START,
|
||||||
])
|
])
|
||||||
if (!group) return
|
if (!group) return
|
||||||
const pathToNode: PathToNode = group.userData.pathToNode
|
const pathToNode: PathToNode = JSON.parse(
|
||||||
const varDecIndex: number = pathToNode[1][0] as number
|
JSON.stringify(group.userData.pathToNode)
|
||||||
|
)
|
||||||
|
const varDecIndex = JSON.parse(JSON.stringify(pathToNode[1][0]))
|
||||||
if (draftInfo) {
|
if (draftInfo) {
|
||||||
pathToNode[1][0] = 0
|
pathToNode[1][0] = 0
|
||||||
}
|
}
|
||||||
@ -1721,7 +1719,7 @@ function prepareTruncatedMemoryAndAst(
|
|||||||
}
|
}
|
||||||
| Error {
|
| Error {
|
||||||
const bodyIndex = Number(sketchPathToNode?.[1]?.[0]) || 0
|
const bodyIndex = Number(sketchPathToNode?.[1]?.[0]) || 0
|
||||||
const _ast = ast
|
const _ast = JSON.parse(JSON.stringify(ast))
|
||||||
|
|
||||||
const _node = getNodeFromPath<VariableDeclaration>(
|
const _node = getNodeFromPath<VariableDeclaration>(
|
||||||
_ast,
|
_ast,
|
||||||
@ -1780,36 +1778,11 @@ function prepareTruncatedMemoryAndAst(
|
|||||||
}
|
}
|
||||||
const truncatedAst: Program = {
|
const truncatedAst: Program = {
|
||||||
..._ast,
|
..._ast,
|
||||||
body: [_ast.body[bodyIndex]],
|
body: [JSON.parse(JSON.stringify(_ast.body[bodyIndex]))],
|
||||||
}
|
}
|
||||||
const programMemoryOverride = programMemoryInit()
|
const programMemoryOverride = programMemoryInit()
|
||||||
if (err(programMemoryOverride)) return programMemoryOverride
|
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++) {
|
for (let i = 0; i < bodyIndex; i++) {
|
||||||
const node = _ast.body[i]
|
const node = _ast.body[i]
|
||||||
if (node.type !== 'VariableDeclaration') {
|
if (node.type !== 'VariableDeclaration') {
|
||||||
@ -1821,7 +1794,7 @@ function prepareTruncatedMemoryAndAst(
|
|||||||
if (!memoryItem) {
|
if (!memoryItem) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
programMemoryOverride.root[name] = memoryItem
|
programMemoryOverride.root[name] = JSON.parse(JSON.stringify(memoryItem))
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
truncatedAst,
|
truncatedAst,
|
||||||
@ -1969,9 +1942,9 @@ export async function getSketchOrientationDetails(
|
|||||||
* @param entityId - The ID of the entity for which orientation details are being fetched.
|
* @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.
|
* @returns A promise that resolves with the orientation details of the face.
|
||||||
*/
|
*/
|
||||||
export async function getFaceDetails(
|
async function getFaceDetails(
|
||||||
entityId: string
|
entityId: string
|
||||||
): Promise<Models['GetSketchModePlane_type']> {
|
): Promise<Models['FaceIsPlanar_type']> {
|
||||||
// TODO mode engine connection to allow batching returns and batch the following
|
// TODO mode engine connection to allow batching returns and batch the following
|
||||||
await engineCommandManager.sendSceneCommand({
|
await engineCommandManager.sendSceneCommand({
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
@ -1984,7 +1957,8 @@ export async function getFaceDetails(
|
|||||||
entity_id: entityId,
|
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({
|
await engineCommandManager.sendSceneCommand({
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd_id: uuidv4(),
|
cmd_id: uuidv4(),
|
||||||
|
@ -151,7 +151,9 @@ export function useCalc({
|
|||||||
ast,
|
ast,
|
||||||
engineCommandManager,
|
engineCommandManager,
|
||||||
useFakeExecutor: true,
|
useFakeExecutor: true,
|
||||||
programMemoryOverride: kclManager.programMemory,
|
programMemoryOverride: JSON.parse(
|
||||||
|
JSON.stringify(kclManager.programMemory)
|
||||||
|
),
|
||||||
}).then(({ programMemory }) => {
|
}).then(({ programMemory }) => {
|
||||||
const resultDeclaration = ast.body.find(
|
const resultDeclaration = ast.body.find(
|
||||||
(a) =>
|
(a) =>
|
||||||
|
@ -6,18 +6,8 @@ import { NetworkHealthIndicator } from 'components/NetworkHealthIndicator'
|
|||||||
import { HelpMenu } from './HelpMenu'
|
import { HelpMenu } from './HelpMenu'
|
||||||
import { Link, useLocation } from 'react-router-dom'
|
import { Link, useLocation } from 'react-router-dom'
|
||||||
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
|
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({
|
export function LowerRightControls(props: React.PropsWithChildren) {
|
||||||
children,
|
|
||||||
coreDumpManager,
|
|
||||||
}: {
|
|
||||||
children?: React.ReactNode
|
|
||||||
coreDumpManager?: CoreDumpManager
|
|
||||||
}) {
|
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const filePath = useAbsoluteFilePath()
|
const filePath = useAbsoluteFilePath()
|
||||||
const linkOverrideClassName =
|
const linkOverrideClassName =
|
||||||
@ -25,42 +15,9 @@ export function LowerRightControls({
|
|||||||
|
|
||||||
const isPlayWright = window?.localStorage.getItem('playwright') === 'true'
|
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 (
|
return (
|
||||||
<section className="fixed bottom-2 right-2 flex flex-col items-end gap-3 pointer-events-none">
|
<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">
|
<menu className="flex items-center justify-end gap-3 pointer-events-auto">
|
||||||
<a
|
<a
|
||||||
href={`https://github.com/KittyCAD/modeling-app/releases/tag/v${APP_VERSION}`}
|
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}
|
v{isPlayWright ? '11.22.33' : APP_VERSION}
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
onClick={reportbug}
|
|
||||||
href="https://github.com/KittyCAD/modeling-app/issues/new/choose"
|
href="https://github.com/KittyCAD/modeling-app/issues/new/choose"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
|
@ -30,7 +30,7 @@ import { wasmUrl } from 'lang/wasm'
|
|||||||
import { PROJECT_ENTRYPOINT } from 'lib/constants'
|
import { PROJECT_ENTRYPOINT } from 'lib/constants'
|
||||||
import { useNetworkContext } from 'hooks/useNetworkContext'
|
import { useNetworkContext } from 'hooks/useNetworkContext'
|
||||||
import { NetworkHealthState } from 'hooks/useNetworkStatus'
|
import { NetworkHealthState } from 'hooks/useNetworkStatus'
|
||||||
import { err } from 'lib/trap'
|
import { err, trap } from 'lib/trap'
|
||||||
|
|
||||||
function getWorkspaceFolders(): LSP.WorkspaceFolder[] {
|
function getWorkspaceFolders(): LSP.WorkspaceFolder[] {
|
||||||
return []
|
return []
|
||||||
|
@ -23,7 +23,6 @@ import {
|
|||||||
editorManager,
|
editorManager,
|
||||||
sceneEntitiesManager,
|
sceneEntitiesManager,
|
||||||
} from 'lib/singletons'
|
} from 'lib/singletons'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
|
||||||
import { applyConstraintHorzVertDistance } from './Toolbar/SetHorzVertDistance'
|
import { applyConstraintHorzVertDistance } from './Toolbar/SetHorzVertDistance'
|
||||||
import {
|
import {
|
||||||
angleBetweenInfo,
|
angleBetweenInfo,
|
||||||
@ -79,7 +78,6 @@ import { getVarNameModal } from 'hooks/useToolbarGuards'
|
|||||||
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { uuidv4 } from 'lib/utils'
|
||||||
import { err, trap } from 'lib/trap'
|
import { err, trap } from 'lib/trap'
|
||||||
import { useCommandsContext } from 'hooks/useCommandsContext'
|
|
||||||
|
|
||||||
type MachineContext<T extends AnyStateMachine> = {
|
type MachineContext<T extends AnyStateMachine> = {
|
||||||
state: StateFrom<T>
|
state: StateFrom<T>
|
||||||
@ -126,6 +124,7 @@ export const ModelingMachineProvider = ({
|
|||||||
token
|
token
|
||||||
)
|
)
|
||||||
useHotkeyWrapper(['meta + shift + .'], () => {
|
useHotkeyWrapper(['meta + shift + .'], () => {
|
||||||
|
console.warn('CoreDump: Initializing core dump')
|
||||||
toast.promise(
|
toast.promise(
|
||||||
coreDump(coreDumpManager, true),
|
coreDump(coreDumpManager, true),
|
||||||
{
|
{
|
||||||
@ -142,7 +141,6 @@ export const ModelingMachineProvider = ({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
const { commandBarState } = useCommandsContext()
|
|
||||||
|
|
||||||
// Settings machine setup
|
// Settings machine setup
|
||||||
// const retrievedSettings = useRef(
|
// const retrievedSettings = useRef(
|
||||||
@ -328,11 +326,6 @@ export const ModelingMachineProvider = ({
|
|||||||
)
|
)
|
||||||
updateSceneObjectColors()
|
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 {
|
return {
|
||||||
selectionRanges: selections,
|
selectionRanges: selections,
|
||||||
}
|
}
|
||||||
@ -467,11 +460,6 @@ export const ModelingMachineProvider = ({
|
|||||||
|
|
||||||
return canExtrudeSelection(selectionRanges)
|
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 }) => {
|
'Sketch is empty': ({ sketchDetails }) => {
|
||||||
const node = getNodeFromPath<VariableDeclaration>(
|
const node = getNodeFromPath<VariableDeclaration>(
|
||||||
kclManager.ast,
|
kclManager.ast,
|
||||||
@ -513,7 +501,7 @@ export const ModelingMachineProvider = ({
|
|||||||
services: {
|
services: {
|
||||||
'AST-undo-startSketchOn': async ({ sketchDetails }) => {
|
'AST-undo-startSketchOn': async ({ sketchDetails }) => {
|
||||||
if (!sketchDetails) return
|
if (!sketchDetails) return
|
||||||
const newAst: Program = kclManager.ast
|
const newAst: Program = JSON.parse(JSON.stringify(kclManager.ast))
|
||||||
const varDecIndex = sketchDetails.sketchPathToNode[1][0]
|
const varDecIndex = sketchDetails.sketchPathToNode[1][0]
|
||||||
// remove body item at varDecIndex
|
// remove body item at varDecIndex
|
||||||
newAst.body = newAst.body.filter((_, i) => i !== varDecIndex)
|
newAst.body = newAst.body.filter((_, i) => i !== varDecIndex)
|
||||||
@ -935,11 +923,6 @@ export const ModelingMachineProvider = ({
|
|||||||
}
|
}
|
||||||
}, [modelingSend])
|
}, [modelingSend])
|
||||||
|
|
||||||
// Allow using the delete key to delete solids
|
|
||||||
useHotkeys(['backspace', 'delete', 'del'], () => {
|
|
||||||
modelingSend({ type: 'Delete selection' })
|
|
||||||
})
|
|
||||||
|
|
||||||
useStateMachineCommands({
|
useStateMachineCommands({
|
||||||
machineId: 'modeling',
|
machineId: 'modeling',
|
||||||
state: modelingState,
|
state: modelingState,
|
||||||
|
@ -1,25 +1,7 @@
|
|||||||
import { coreDump } from 'lang/wasm'
|
|
||||||
import { CoreDumpManager } from 'lib/coredump'
|
|
||||||
import { CustomIcon } from './CustomIcon'
|
import { CustomIcon } from './CustomIcon'
|
||||||
import { engineCommandManager } from 'lib/singletons'
|
|
||||||
import React from 'react'
|
|
||||||
import toast from 'react-hot-toast'
|
|
||||||
import Tooltip from './Tooltip'
|
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() {
|
async function refresh() {
|
||||||
if (window && 'plausible' in window) {
|
if (window && 'plausible' in window) {
|
||||||
const p = window.plausible as (
|
const p = window.plausible as (
|
||||||
@ -35,26 +17,8 @@ export const RefreshButton = ({ children }: React.PropsWithChildren) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
toast
|
// Window may not be available in some environments
|
||||||
.promise(
|
window?.location.reload()
|
||||||
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()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -83,7 +83,6 @@ export const Stream = ({ className = '' }: { className?: string }) => {
|
|||||||
if (!videoRef.current) return
|
if (!videoRef.current) return
|
||||||
if (state.matches('Sketch')) return
|
if (state.matches('Sketch')) return
|
||||||
if (state.matches('Sketch no face')) return
|
if (state.matches('Sketch no face')) return
|
||||||
|
|
||||||
const { x, y } = getNormalisedCoordinates({
|
const { x, y } = getNormalisedCoordinates({
|
||||||
clientX: e.clientX,
|
clientX: e.clientX,
|
||||||
clientY: e.clientY,
|
clientY: e.clientY,
|
||||||
@ -128,7 +127,6 @@ export const Stream = ({ className = '' }: { className?: string }) => {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="absolute inset-0 z-0"
|
className="absolute inset-0 z-0"
|
||||||
id="stream"
|
|
||||||
data-testid="stream"
|
data-testid="stream"
|
||||||
onMouseUp={handleMouseUp}
|
onMouseUp={handleMouseUp}
|
||||||
onMouseDown={handleMouseDown}
|
onMouseDown={handleMouseDown}
|
||||||
|
@ -145,7 +145,7 @@ export async function applyConstraintIntersect({
|
|||||||
const { transforms, forcedSelectionRanges } = info
|
const { transforms, forcedSelectionRanges } = info
|
||||||
|
|
||||||
const transform1 = transformSecondarySketchLinesTagFirst({
|
const transform1 = transformSecondarySketchLinesTagFirst({
|
||||||
ast: kclManager.ast,
|
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||||
selectionRanges: forcedSelectionRanges,
|
selectionRanges: forcedSelectionRanges,
|
||||||
transformInfos: transforms,
|
transformInfos: transforms,
|
||||||
programMemory: kclManager.programMemory,
|
programMemory: kclManager.programMemory,
|
||||||
|
@ -106,7 +106,7 @@ export async function applyConstraintAbsDistance({
|
|||||||
const transformInfos = info.transforms
|
const transformInfos = info.transforms
|
||||||
|
|
||||||
const transform1 = transformAstSketchLines({
|
const transform1 = transformAstSketchLines({
|
||||||
ast: kclManager.ast,
|
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||||
selectionRanges: selectionRanges,
|
selectionRanges: selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory: kclManager.programMemory,
|
programMemory: kclManager.programMemory,
|
||||||
@ -128,7 +128,7 @@ export async function applyConstraintAbsDistance({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const transform2 = transformAstSketchLines({
|
const transform2 = transformAstSketchLines({
|
||||||
ast: kclManager.ast,
|
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||||
selectionRanges: selectionRanges,
|
selectionRanges: selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory: kclManager.programMemory,
|
programMemory: kclManager.programMemory,
|
||||||
@ -176,7 +176,7 @@ export function applyConstraintAxisAlign({
|
|||||||
let finalValue = createIdentifier('ZERO')
|
let finalValue = createIdentifier('ZERO')
|
||||||
|
|
||||||
return transformAstSketchLines({
|
return transformAstSketchLines({
|
||||||
ast: kclManager.ast,
|
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||||
selectionRanges: selectionRanges,
|
selectionRanges: selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory: kclManager.programMemory,
|
programMemory: kclManager.programMemory,
|
||||||
|
@ -100,7 +100,7 @@ export async function applyConstraintAngleBetween({
|
|||||||
const transformInfos = info.transforms
|
const transformInfos = info.transforms
|
||||||
|
|
||||||
const transformed1 = transformSecondarySketchLinesTagFirst({
|
const transformed1 = transformSecondarySketchLinesTagFirst({
|
||||||
ast: kclManager.ast,
|
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory: kclManager.programMemory,
|
programMemory: kclManager.programMemory,
|
||||||
|
@ -108,7 +108,7 @@ export async function applyConstraintHorzVertDistance({
|
|||||||
if (err(info)) return Promise.reject(info)
|
if (err(info)) return Promise.reject(info)
|
||||||
const transformInfos = info.transforms
|
const transformInfos = info.transforms
|
||||||
const transformed = transformSecondarySketchLinesTagFirst({
|
const transformed = transformSecondarySketchLinesTagFirst({
|
||||||
ast: kclManager.ast,
|
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory: kclManager.programMemory,
|
programMemory: kclManager.programMemory,
|
||||||
|
@ -84,7 +84,7 @@ export async function applyConstraintAngleLength({
|
|||||||
|
|
||||||
const { transforms } = angleLength
|
const { transforms } = angleLength
|
||||||
const sketched = transformAstSketchLines({
|
const sketched = transformAstSketchLines({
|
||||||
ast: kclManager.ast,
|
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
transformInfos: transforms,
|
transformInfos: transforms,
|
||||||
programMemory: kclManager.programMemory,
|
programMemory: kclManager.programMemory,
|
||||||
@ -139,7 +139,7 @@ export async function applyConstraintAngleLength({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const retval = transformAstSketchLines({
|
const retval = transformAstSketchLines({
|
||||||
ast: kclManager.ast,
|
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
transformInfos: transforms,
|
transformInfos: transforms,
|
||||||
programMemory: kclManager.programMemory,
|
programMemory: kclManager.programMemory,
|
||||||
|
@ -20,12 +20,6 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
|
|||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const send = useSettingsAuthContext()?.auth?.send
|
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":
|
// Fallback logic for displaying user's "name":
|
||||||
// 1. user.name
|
// 1. user.name
|
||||||
// 2. user.first_name + ' ' + user.last_name
|
// 2. user.first_name + ' ' + user.last_name
|
||||||
|
@ -23,7 +23,7 @@ export default class EditorManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _lastSelectionEvent: number | null = null
|
private _lastSelectionEvent: number | null = null
|
||||||
lastSelection: string = ''
|
private _lastSelection: string = ''
|
||||||
private _lastEvent: { event: string; time: number } | null = null
|
private _lastEvent: { event: string; time: number } | null = null
|
||||||
|
|
||||||
private _modelingSend: (eventInfo: ModelingMachineEvent) => void = () => {}
|
private _modelingSend: (eventInfo: ModelingMachineEvent) => void = () => {}
|
||||||
@ -199,14 +199,12 @@ export default class EditorManager {
|
|||||||
viewUpdate?.state?.selection?.ranges || []
|
viewUpdate?.state?.selection?.ranges || []
|
||||||
)
|
)
|
||||||
|
|
||||||
if (selString === this.lastSelection) {
|
if (selString === this._lastSelection) {
|
||||||
// onUpdate is noisy and is fired a lot by extensions
|
// onUpdate is noisy and is fired a lot by extensions
|
||||||
// since we're only interested in selections changes we can ignore most of these.
|
// since we're only interested in selections changes we can ignore most of these.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// note this is also set from the "Set selection" action to stop code mirror from updating selections right after
|
this._lastSelection = selString
|
||||||
// selections are made from the scene
|
|
||||||
this.lastSelection = selString
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this._lastSelectionEvent &&
|
this._lastSelectionEvent &&
|
||||||
|
@ -42,8 +42,9 @@ function registerServerCapability(
|
|||||||
serverCapabilities: ServerCapabilities,
|
serverCapabilities: ServerCapabilities,
|
||||||
registration: Registration
|
registration: Registration
|
||||||
): ServerCapabilities | Error {
|
): ServerCapabilities | Error {
|
||||||
const serverCapabilitiesCopy =
|
const serverCapabilitiesCopy = JSON.parse(
|
||||||
serverCapabilities as IFlexibleServerCapabilities
|
JSON.stringify(serverCapabilities)
|
||||||
|
) as IFlexibleServerCapabilities
|
||||||
const { method, registerOptions } = registration
|
const { method, registerOptions } = registration
|
||||||
const providerName = ServerCapabilitiesProviders[method]
|
const providerName = ServerCapabilitiesProviders[method]
|
||||||
|
|
||||||
@ -51,7 +52,10 @@ function registerServerCapability(
|
|||||||
if (!registerOptions) {
|
if (!registerOptions) {
|
||||||
serverCapabilitiesCopy[providerName] = true
|
serverCapabilitiesCopy[providerName] = true
|
||||||
} else {
|
} else {
|
||||||
serverCapabilitiesCopy[providerName] = Object.assign({}, registerOptions)
|
serverCapabilitiesCopy[providerName] = Object.assign(
|
||||||
|
{},
|
||||||
|
JSON.parse(JSON.stringify(registerOptions))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return new Error('Could not register server capability.')
|
return new Error('Could not register server capability.')
|
||||||
@ -64,8 +68,9 @@ function unregisterServerCapability(
|
|||||||
serverCapabilities: ServerCapabilities,
|
serverCapabilities: ServerCapabilities,
|
||||||
unregistration: Unregistration
|
unregistration: Unregistration
|
||||||
): ServerCapabilities {
|
): ServerCapabilities {
|
||||||
const serverCapabilitiesCopy =
|
const serverCapabilitiesCopy = JSON.parse(
|
||||||
serverCapabilities as IFlexibleServerCapabilities
|
JSON.stringify(serverCapabilities)
|
||||||
|
) as IFlexibleServerCapabilities
|
||||||
const { method } = unregistration
|
const { method } = unregistration
|
||||||
const providerName = ServerCapabilitiesProviders[method]
|
const providerName = ServerCapabilitiesProviders[method]
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { executeAst, lintAst } from 'useStore'
|
import { executeAst } from 'useStore'
|
||||||
import { Selections } from 'lib/selections'
|
import { Selections } from 'lib/selections'
|
||||||
import { KCLError, kclErrorsToDiagnostics } from './errors'
|
import { KCLError, kclErrorsToDiagnostics } from './errors'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { uuidv4 } from 'lib/utils'
|
||||||
@ -211,9 +211,6 @@ export class KclManager {
|
|||||||
ast,
|
ast,
|
||||||
engineCommandManager: this.engineCommandManager,
|
engineCommandManager: this.engineCommandManager,
|
||||||
})
|
})
|
||||||
|
|
||||||
editorManager.addDiagnostics(await lintAst({ ast: ast }))
|
|
||||||
|
|
||||||
sceneInfra.modelingSend({ type: 'code edit during sketch' })
|
sceneInfra.modelingSend({ type: 'code edit during sketch' })
|
||||||
defaultSelectionFilter(programMemory, this.engineCommandManager)
|
defaultSelectionFilter(programMemory, this.engineCommandManager)
|
||||||
|
|
||||||
@ -264,10 +261,7 @@ export class KclManager {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const newAst = this.safeParse(newCode)
|
const newAst = this.safeParse(newCode)
|
||||||
if (!newAst) {
|
if (!newAst) return
|
||||||
this.clearAst()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
codeManager.updateCodeEditor(newCode)
|
codeManager.updateCodeEditor(newCode)
|
||||||
// Write the file to disk.
|
// Write the file to disk.
|
||||||
await codeManager.writeToFile()
|
await codeManager.writeToFile()
|
||||||
@ -284,9 +278,6 @@ export class KclManager {
|
|||||||
engineCommandManager: this.engineCommandManager,
|
engineCommandManager: this.engineCommandManager,
|
||||||
useFakeExecutor: true,
|
useFakeExecutor: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
editorManager.addDiagnostics(await lintAst({ ast: ast }))
|
|
||||||
|
|
||||||
this._logs = logs
|
this._logs = logs
|
||||||
this._kclErrors = errors
|
this._kclErrors = errors
|
||||||
this._programMemory = programMemory
|
this._programMemory = programMemory
|
||||||
|
@ -502,10 +502,11 @@ describe('testing pipe operator special', () => {
|
|||||||
},
|
},
|
||||||
{ type: 'PipeSubstitution', start: 82, end: 83 },
|
{ type: 'PipeSubstitution', start: 82, end: 83 },
|
||||||
{
|
{
|
||||||
type: 'TagDeclarator',
|
type: 'Literal',
|
||||||
start: 85,
|
start: 85,
|
||||||
end: 93,
|
end: 93,
|
||||||
value: 'myPath',
|
value: 'myPath',
|
||||||
|
raw: '"myPath"',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
optional: false,
|
optional: false,
|
||||||
@ -1656,10 +1657,11 @@ describe('should recognise callExpresions in binaryExpressions', () => {
|
|||||||
callee: { type: 'Identifier', start: 8, end: 15, name: 'segEndX' },
|
callee: { type: 'Identifier', start: 8, end: 15, name: 'segEndX' },
|
||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
type: 'Identifier',
|
type: 'Literal',
|
||||||
start: 16,
|
start: 16,
|
||||||
end: 23,
|
end: 23,
|
||||||
name: 'seg02',
|
value: 'seg02',
|
||||||
|
raw: "'seg02'",
|
||||||
},
|
},
|
||||||
{ type: 'PipeSubstitution', start: 25, end: 26 },
|
{ type: 'PipeSubstitution', start: 25, end: 26 },
|
||||||
],
|
],
|
||||||
|
@ -128,7 +128,7 @@ const mySketch001 = startSketchOn('XY')
|
|||||||
const sk1 = startSketchOn('XY')
|
const sk1 = startSketchOn('XY')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> lineTo([-2.5, 0], %)
|
|> lineTo([-2.5, 0], %)
|
||||||
|> lineTo([0, 10], %, $p)
|
|> lineTo([0, 10], %, "p")
|
||||||
|> lineTo([2.5, 0], %)
|
|> lineTo([2.5, 0], %)
|
||||||
// |> rx(45, %)
|
// |> rx(45, %)
|
||||||
// |> translate([1,0,1], %)
|
// |> translate([1,0,1], %)
|
||||||
@ -138,7 +138,7 @@ const theExtrude = extrude(2, sk1)
|
|||||||
const sk2 = startSketchOn('XY')
|
const sk2 = startSketchOn('XY')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> lineTo([-2.5, 0], %)
|
|> lineTo([-2.5, 0], %)
|
||||||
|> lineTo([0, 3], %, $o)
|
|> lineTo([0, 3], %, "p")
|
||||||
|> lineTo([2.5, 0], %)
|
|> lineTo([2.5, 0], %)
|
||||||
// |> transform(theTransf, %)
|
// |> transform(theTransf, %)
|
||||||
|> extrude(2, %)
|
|> extrude(2, %)
|
||||||
@ -163,20 +163,20 @@ const sk2 = startSketchOn('XY')
|
|||||||
type: 'extrudePlane',
|
type: 'extrudePlane',
|
||||||
faceId: expect.any(String),
|
faceId: expect.any(String),
|
||||||
tag: {
|
tag: {
|
||||||
end: 116,
|
end: 117,
|
||||||
start: 114,
|
start: 114,
|
||||||
type: 'TagDeclarator',
|
type: 'TagDeclarator',
|
||||||
value: 'p',
|
value: 'p',
|
||||||
},
|
},
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
sourceRange: [95, 117],
|
sourceRange: [95, 118],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'extrudePlane',
|
type: 'extrudePlane',
|
||||||
faceId: expect.any(String),
|
faceId: expect.any(String),
|
||||||
tag: null,
|
tag: null,
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
sourceRange: [123, 142],
|
sourceRange: [124, 143],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
sketchGroup: {
|
sketchGroup: {
|
||||||
@ -201,14 +201,14 @@ const sk2 = startSketchOn('XY')
|
|||||||
from: [-2.5, 0],
|
from: [-2.5, 0],
|
||||||
to: [0, 10],
|
to: [0, 10],
|
||||||
tag: {
|
tag: {
|
||||||
end: 116,
|
end: 117,
|
||||||
start: 114,
|
start: 114,
|
||||||
type: 'TagDeclarator',
|
type: 'TagDeclarator',
|
||||||
value: 'p',
|
value: 'p',
|
||||||
},
|
},
|
||||||
__geoMeta: {
|
__geoMeta: {
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
sourceRange: [95, 117],
|
sourceRange: [95, 118],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -218,7 +218,7 @@ const sk2 = startSketchOn('XY')
|
|||||||
tag: null,
|
tag: null,
|
||||||
__geoMeta: {
|
__geoMeta: {
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
sourceRange: [123, 142],
|
sourceRange: [124, 143],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -237,26 +237,26 @@ const sk2 = startSketchOn('XY')
|
|||||||
faceId: expect.any(String),
|
faceId: expect.any(String),
|
||||||
tag: null,
|
tag: null,
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
sourceRange: [373, 393],
|
sourceRange: [374, 394],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'extrudePlane',
|
type: 'extrudePlane',
|
||||||
faceId: expect.any(String),
|
faceId: expect.any(String),
|
||||||
tag: {
|
tag: {
|
||||||
end: 419,
|
end: 421,
|
||||||
start: 417,
|
start: 418,
|
||||||
type: 'TagDeclarator',
|
type: 'TagDeclarator',
|
||||||
value: 'o',
|
value: 'p',
|
||||||
},
|
},
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
sourceRange: [399, 420],
|
sourceRange: [400, 422],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'extrudePlane',
|
type: 'extrudePlane',
|
||||||
faceId: expect.any(String),
|
faceId: expect.any(String),
|
||||||
tag: null,
|
tag: null,
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
sourceRange: [426, 445],
|
sourceRange: [428, 447],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
sketchGroup: {
|
sketchGroup: {
|
||||||
@ -273,7 +273,7 @@ const sk2 = startSketchOn('XY')
|
|||||||
tag: null,
|
tag: null,
|
||||||
__geoMeta: {
|
__geoMeta: {
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
sourceRange: [373, 393],
|
sourceRange: [374, 394],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -281,14 +281,14 @@ const sk2 = startSketchOn('XY')
|
|||||||
from: [-2.5, 0],
|
from: [-2.5, 0],
|
||||||
to: [0, 3],
|
to: [0, 3],
|
||||||
tag: {
|
tag: {
|
||||||
end: 419,
|
end: 421,
|
||||||
start: 417,
|
start: 418,
|
||||||
type: 'TagDeclarator',
|
type: 'TagDeclarator',
|
||||||
value: 'o',
|
value: 'p',
|
||||||
},
|
},
|
||||||
__geoMeta: {
|
__geoMeta: {
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
sourceRange: [399, 420],
|
sourceRange: [400, 422],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -298,7 +298,7 @@ const sk2 = startSketchOn('XY')
|
|||||||
tag: null,
|
tag: null,
|
||||||
__geoMeta: {
|
__geoMeta: {
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
sourceRange: [426, 445],
|
sourceRange: [428, 447],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -306,7 +306,7 @@ const sk2 = startSketchOn('XY')
|
|||||||
height: 2,
|
height: 2,
|
||||||
startCapId: expect.any(String),
|
startCapId: expect.any(String),
|
||||||
endCapId: expect.any(String),
|
endCapId: expect.any(String),
|
||||||
__meta: [{ sourceRange: [342, 367] }],
|
__meta: [{ sourceRange: [343, 368] }],
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
@ -15,7 +15,6 @@ import {
|
|||||||
sketchOnExtrudedFace,
|
sketchOnExtrudedFace,
|
||||||
deleteSegmentFromPipeExpression,
|
deleteSegmentFromPipeExpression,
|
||||||
removeSingleConstraintInfo,
|
removeSingleConstraintInfo,
|
||||||
deleteFromSelection,
|
|
||||||
} from './modifyAst'
|
} from './modifyAst'
|
||||||
import { enginelessExecutor } from '../lib/testHelpers'
|
import { enginelessExecutor } from '../lib/testHelpers'
|
||||||
import { findUsesOfTagInPipe, getNodePathFromSourceRange } from './queryAst'
|
import { findUsesOfTagInPipe, getNodePathFromSourceRange } from './queryAst'
|
||||||
@ -164,25 +163,25 @@ describe('Testing giveSketchFnCallTag', () => {
|
|||||||
code,
|
code,
|
||||||
'line([0, 0.83], %)'
|
'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(tag).toBe('seg01')
|
||||||
expect(isTagExisting).toBe(false)
|
expect(isTagExisting).toBe(false)
|
||||||
})
|
})
|
||||||
it('Should create a unique tag if seg01 already exists', () => {
|
it('Should create a unique tag if seg01 already exists', () => {
|
||||||
let _code = code.replace(
|
let _code = code.replace(
|
||||||
'line([-2.57, -0.13], %)',
|
'line([-2.57, -0.13], %)',
|
||||||
'line([-2.57, -0.13], %, $seg01)'
|
"line([-2.57, -0.13], %, 'seg01')"
|
||||||
)
|
)
|
||||||
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
|
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
|
||||||
_code,
|
_code,
|
||||||
'line([0, 0.83], %)'
|
'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(tag).toBe('seg02')
|
||||||
expect(isTagExisting).toBe(false)
|
expect(isTagExisting).toBe(false)
|
||||||
})
|
})
|
||||||
it('Should return existing tag if it already exists', () => {
|
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)
|
let _code = code.replace('line([-2.57, -0.13], %)', lineButWithTag)
|
||||||
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
|
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
|
||||||
_code,
|
_code,
|
||||||
@ -329,11 +328,11 @@ describe('testing sketchOnExtrudedFace', () => {
|
|||||||
const newCode = recast(modifiedAst)
|
const newCode = recast(modifiedAst)
|
||||||
expect(newCode).toContain(`const part001 = startSketchOn('-XZ')
|
expect(newCode).toContain(`const part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([3.58, 2.06], %)
|
|> startProfileAt([3.58, 2.06], %)
|
||||||
|> line([9.7, 9.19], %, $seg01)
|
|> line([9.7, 9.19], %, 'seg01')
|
||||||
|> line([8.62, -9.57], %)
|
|> line([8.62, -9.57], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|> extrude(5 + 7, %)
|
|> extrude(5 + 7, %)
|
||||||
const sketch001 = startSketchOn(part001, seg01)`)
|
const sketch001 = startSketchOn(part001, 'seg01')`)
|
||||||
})
|
})
|
||||||
test('it should be able to extrude on close segments', async () => {
|
test('it should be able to extrude on close segments', async () => {
|
||||||
const code = `const part001 = startSketchOn('-XZ')
|
const code = `const part001 = startSketchOn('-XZ')
|
||||||
@ -372,9 +371,9 @@ const sketch001 = startSketchOn(part001, seg01)`)
|
|||||||
|> startProfileAt([3.58, 2.06], %)
|
|> startProfileAt([3.58, 2.06], %)
|
||||||
|> line([9.7, 9.19], %)
|
|> line([9.7, 9.19], %)
|
||||||
|> line([8.62, -9.57], %)
|
|> line([8.62, -9.57], %)
|
||||||
|> close(%, $seg01)
|
|> close(%, 'seg01')
|
||||||
|> extrude(5 + 7, %)
|
|> 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 () => {
|
test('it should be able to extrude on start-end caps', async () => {
|
||||||
const code = `const part001 = startSketchOn('-XZ')
|
const code = `const part001 = startSketchOn('-XZ')
|
||||||
@ -458,7 +457,7 @@ const sketch001 = startSketchOn(part001, 'END')`)
|
|||||||
if (err(updatedAst)) throw updatedAst
|
if (err(updatedAst)) throw updatedAst
|
||||||
const newCode = recast(updatedAst.modifiedAst)
|
const newCode = recast(updatedAst.modifiedAst)
|
||||||
expect(newCode).toContain(`const part001 = extrude(5 + 7, sketch001)
|
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 = ''
|
replace2 = ''
|
||||||
) => `const part001 = startSketchOn('-XZ')
|
) => `const part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([54.78, -95.91], %)
|
|> startProfileAt([54.78, -95.91], %)
|
||||||
|> line([306.21, 198.82], %, $b)
|
|> line([306.21, 198.82], %, 'b')
|
||||||
${!replace1 ? ` |> ${line}\n` : ''} |> angledLine([-65, ${
|
${!replace1 ? ` |> ${line}\n` : ''} |> angledLine([-65, ${
|
||||||
!replace1 ? 'segLen(a, %)' : replace1
|
!replace1 ? "segLen('a', %)" : replace1
|
||||||
}], %)
|
}], %)
|
||||||
|> line([306.21, 198.87], %)
|
|> line([306.21, 198.87], %)
|
||||||
|> angledLine([65, ${!replace2 ? 'segAng(a, %)' : replace2}], %)
|
|> angledLine([65, ${!replace2 ? "segAng('a', %)" : replace2}], %)
|
||||||
|> line([-963.39, -154.67], %)
|
|> line([-963.39, -154.67], %)
|
||||||
`
|
`
|
||||||
test.each([
|
test.each([
|
||||||
['line', 'line([306.21, 198.85], %, $a)', ['365.11', '33']],
|
['line', "line([306.21, 198.85], %, 'a')", ['365.11', '33']],
|
||||||
['lineTo', 'lineTo([306.21, 198.85], %, $a)', ['110.48', '119.73']],
|
['lineTo', "lineTo([306.21, 198.85], %, 'a')", ['110.48', '119.73']],
|
||||||
['yLine', 'yLine(198.85, %, $a)', ['198.85', '90']],
|
['yLine', "yLine(198.85, %, 'a')", ['198.85', '90']],
|
||||||
['xLine', 'xLine(198.85, %, $a)', ['198.85', '0']],
|
['xLine', "xLine(198.85, %, 'a')", ['198.85', '0']],
|
||||||
['yLineTo', 'yLineTo(198.85, %, $a)', ['95.94', '90']],
|
['yLineTo', "yLineTo(198.85, %, 'a')", ['95.94', '90']],
|
||||||
['xLineTo', 'xLineTo(198.85, %, $a)', ['162.14', '180']],
|
['xLineTo', "xLineTo(198.85, %, 'a')", ['162.14', '180']],
|
||||||
[
|
[
|
||||||
'angledLine',
|
'angledLine',
|
||||||
'angledLine({ angle: 45.5, length: 198.85 }, %, $a)',
|
"angledLine({ angle: 45.5, length: 198.85 }, %, 'a')",
|
||||||
['198.85', '45.5'],
|
['198.85', '45.5'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'angledLineOfXLength',
|
'angledLineOfXLength',
|
||||||
'angledLineOfXLength({ angle: 45.5, length: 198.85 }, %, $a)',
|
"angledLineOfXLength({ angle: 45.5, length: 198.85 }, %, 'a')",
|
||||||
['283.7', '45.5'],
|
['283.7', '45.5'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'angledLineOfYLength',
|
'angledLineOfYLength',
|
||||||
'angledLineOfYLength({ angle: 45.5, length: 198.85 }, %, $a)',
|
"angledLineOfYLength({ angle: 45.5, length: 198.85 }, %, 'a')",
|
||||||
['278.79', '45.5'],
|
['278.79', '45.5'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'angledLineToX',
|
'angledLineToX',
|
||||||
'angledLineToX({ angle: 45.5, to: 198.85 }, %, $a)',
|
"angledLineToX({ angle: 45.5, to: 198.85 }, %, 'a')",
|
||||||
['231.33', '134.5'],
|
['231.33', '134.5'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'angledLineToY',
|
'angledLineToY',
|
||||||
'angledLineToY({ angle: 45.5, to: 198.85 }, %, $a)',
|
"angledLineToY({ angle: 45.5, to: 198.85 }, %, 'a')",
|
||||||
['134.51', '45.5'],
|
['134.51', '45.5'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'angledLineThatIntersects',
|
'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'],
|
['918.4', '45.5'],
|
||||||
],
|
],
|
||||||
])(`%s`, async (_, line, [replace1, replace2]) => {
|
])(`%s`, async (_, line, [replace1, replace2]) => {
|
||||||
@ -580,7 +579,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
|||||||
|> lineTo([6.14 + 0, 3.14 + 0], %)
|
|> lineTo([6.14 + 0, 3.14 + 0], %)
|
||||||
|> xLineTo(8 + 0, %)
|
|> xLineTo(8 + 0, %)
|
||||||
|> yLineTo(5 + 0, %)
|
|> yLineTo(5 + 0, %)
|
||||||
|> yLine(3.14 + 0, %, $a)
|
|> yLine(3.14 + 0, %, 'a')
|
||||||
|> xLine(3.14 + 0, %)
|
|> xLine(3.14 + 0, %)
|
||||||
|> angledLineOfXLength({ angle: 3 + 0, length: 3.14 + 0 }, %)
|
|> angledLineOfXLength({ angle: 3 + 0, length: 3.14 + 0 }, %)
|
||||||
|> angledLineOfYLength({ angle: 30 + 0, length: 3 + 0 }, %)
|
|> angledLineOfYLength({ angle: 30 + 0, length: 3 + 0 }, %)
|
||||||
@ -588,7 +587,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
|||||||
|> angledLineToY({ angle: 30 + 0, to: 10.14 + 0 }, %)
|
|> angledLineToY({ angle: 30 + 0, to: 10.14 + 0 }, %)
|
||||||
|> angledLineThatIntersects({
|
|> angledLineThatIntersects({
|
||||||
angle: 3.14 + 0,
|
angle: 3.14 + 0,
|
||||||
intersectTag: a,
|
intersectTag: 'a',
|
||||||
offset: 0 + 0
|
offset: 0 + 0
|
||||||
}, %)
|
}, %)
|
||||||
|> tangentialArcTo([3.14 + 0, 13.14 + 0], %)`
|
|> tangentialArcTo([3.14 + 0, 13.14 + 0], %)`
|
||||||
@ -602,7 +601,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
|||||||
['lineTo([6.14, 3.14 + 0], %)', 'arrayIndex', 0],
|
['lineTo([6.14, 3.14 + 0], %)', 'arrayIndex', 0],
|
||||||
['xLineTo(8, %)', '', ''],
|
['xLineTo(8, %)', '', ''],
|
||||||
['yLineTo(5, %)', '', ''],
|
['yLineTo(5, %)', '', ''],
|
||||||
['yLine(3.14, %, $a)', '', ''],
|
["yLine(3.14, %, 'a')", '', ''],
|
||||||
['xLine(3.14, %)', '', ''],
|
['xLine(3.14, %)', '', ''],
|
||||||
[
|
[
|
||||||
'angledLineOfXLength({ angle: 3, length: 3.14 + 0 }, %)',
|
'angledLineOfXLength({ angle: 3, length: 3.14 + 0 }, %)',
|
||||||
@ -628,7 +627,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
|||||||
`angledLineThatIntersects({
|
`angledLineThatIntersects({
|
||||||
angle: 3.14 + 0,
|
angle: 3.14 + 0,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
intersectTag: a
|
intersectTag: 'a'
|
||||||
}, %)`,
|
}, %)`,
|
||||||
'objectProperty',
|
'objectProperty',
|
||||||
'offset',
|
'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,
|
PathToNode,
|
||||||
ProgramMemory,
|
ProgramMemory,
|
||||||
SourceRange,
|
SourceRange,
|
||||||
SketchGroup,
|
|
||||||
} from './wasm'
|
} from './wasm'
|
||||||
import {
|
import {
|
||||||
isNodeSafeToReplacePath,
|
isNodeSafeToReplacePath,
|
||||||
@ -26,7 +25,6 @@ import {
|
|||||||
getNodeFromPath,
|
getNodeFromPath,
|
||||||
getNodePathFromSourceRange,
|
getNodePathFromSourceRange,
|
||||||
isNodeSafeToReplace,
|
isNodeSafeToReplace,
|
||||||
traverse,
|
|
||||||
} from './queryAst'
|
} from './queryAst'
|
||||||
import { addTagForSketchOnFace, getConstraintInfo } from './std/sketch'
|
import { addTagForSketchOnFace, getConstraintInfo } from './std/sketch'
|
||||||
import {
|
import {
|
||||||
@ -39,8 +37,6 @@ import { DefaultPlaneStr } from 'clientSideScene/sceneEntities'
|
|||||||
import { isOverlap, roundOff } from 'lib/utils'
|
import { isOverlap, roundOff } from 'lib/utils'
|
||||||
import { KCL_DEFAULT_CONSTANT_PREFIXES } from 'lib/constants'
|
import { KCL_DEFAULT_CONSTANT_PREFIXES } from 'lib/constants'
|
||||||
import { ConstrainInfo } from './std/stdTypes'
|
import { ConstrainInfo } from './std/stdTypes'
|
||||||
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
|
|
||||||
import { Models } from '@kittycad/lib'
|
|
||||||
|
|
||||||
export function startSketchOnDefault(
|
export function startSketchOnDefault(
|
||||||
node: Program,
|
node: Program,
|
||||||
@ -383,7 +379,7 @@ export function sketchOnExtrudedFace(
|
|||||||
const { node: extrudeVarDec } = _node3
|
const { node: extrudeVarDec } = _node3
|
||||||
const extrudeName = extrudeVarDec.id?.name
|
const extrudeName = extrudeVarDec.id?.name
|
||||||
|
|
||||||
let _tag = null
|
let _tag = ''
|
||||||
if (cap === 'none') {
|
if (cap === 'none') {
|
||||||
const __tag = addTagForSketchOnFace(
|
const __tag = addTagForSketchOnFace(
|
||||||
{
|
{
|
||||||
@ -395,17 +391,17 @@ export function sketchOnExtrudedFace(
|
|||||||
)
|
)
|
||||||
if (err(__tag)) return __tag
|
if (err(__tag)) return __tag
|
||||||
const { modifiedAst, tag } = __tag
|
const { modifiedAst, tag } = __tag
|
||||||
_tag = createIdentifier(tag)
|
_tag = tag
|
||||||
_node = modifiedAst
|
_node = modifiedAst
|
||||||
} else {
|
} else {
|
||||||
_tag = createLiteral(cap.toUpperCase())
|
_tag = cap.toUpperCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
const newSketch = createVariableDeclaration(
|
const newSketch = createVariableDeclaration(
|
||||||
newSketchName,
|
newSketchName,
|
||||||
createCallExpressionStdLib('startSketchOn', [
|
createCallExpressionStdLib('startSketchOn', [
|
||||||
createIdentifier(extrudeName ? extrudeName : oldSketchName),
|
createIdentifier(extrudeName ? extrudeName : oldSketchName),
|
||||||
_tag,
|
createLiteral(_tag),
|
||||||
]),
|
]),
|
||||||
'const'
|
'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 {
|
export function createIdentifier(name: string): Identifier {
|
||||||
return {
|
return {
|
||||||
type: 'Identifier',
|
type: 'Identifier',
|
||||||
@ -670,18 +657,17 @@ export function giveSketchFnCallTag(
|
|||||||
// Tag is always 3rd expression now, using arg index feels brittle
|
// Tag is always 3rd expression now, using arg index feels brittle
|
||||||
// but we can come up with a better way to identify tag later.
|
// but we can come up with a better way to identify tag later.
|
||||||
const thirdArg = primaryCallExp.arguments?.[2]
|
const thirdArg = primaryCallExp.arguments?.[2]
|
||||||
const tagDeclarator =
|
const tagLiteral =
|
||||||
thirdArg ||
|
thirdArg || (createLiteral(tag || findUniqueName(ast, 'seg', 2)) as Literal)
|
||||||
(createTagDeclarator(tag || findUniqueName(ast, 'seg', 2)) as TagDeclarator)
|
|
||||||
const isTagExisting = !!thirdArg
|
const isTagExisting = !!thirdArg
|
||||||
if (!isTagExisting) {
|
if (!isTagExisting) {
|
||||||
primaryCallExp.arguments[2] = tagDeclarator
|
primaryCallExp.arguments[2] = tagLiteral
|
||||||
}
|
}
|
||||||
if ('value' in tagDeclarator) {
|
if ('value' in tagLiteral) {
|
||||||
// Now TypeScript knows tagDeclarator has a value property
|
// Now TypeScript knows tagLiteral has a value property
|
||||||
return {
|
return {
|
||||||
modifiedAst: ast,
|
modifiedAst: ast,
|
||||||
tag: String(tagDeclarator.value),
|
tag: String(tagLiteral.value),
|
||||||
isTagExisting,
|
isTagExisting,
|
||||||
pathToNode: path,
|
pathToNode: path,
|
||||||
}
|
}
|
||||||
@ -710,7 +696,7 @@ export function moveValueIntoNewVariablePath(
|
|||||||
programMemory,
|
programMemory,
|
||||||
pathToNode
|
pathToNode
|
||||||
)
|
)
|
||||||
let _node = ast
|
let _node = JSON.parse(JSON.stringify(ast))
|
||||||
const boop = replacer(_node, variableName)
|
const boop = replacer(_node, variableName)
|
||||||
if (trap(boop)) return { modifiedAst: ast }
|
if (trap(boop)) return { modifiedAst: ast }
|
||||||
|
|
||||||
@ -742,7 +728,7 @@ export function moveValueIntoNewVariable(
|
|||||||
programMemory,
|
programMemory,
|
||||||
sourceRange
|
sourceRange
|
||||||
)
|
)
|
||||||
let _node = ast
|
let _node = JSON.parse(JSON.stringify(ast))
|
||||||
const replaced = replacer(_node, variableName)
|
const replaced = replacer(_node, variableName)
|
||||||
if (trap(replaced)) return { modifiedAst: ast }
|
if (trap(replaced)) return { modifiedAst: ast }
|
||||||
|
|
||||||
@ -767,7 +753,7 @@ export function deleteSegmentFromPipeExpression(
|
|||||||
code: string,
|
code: string,
|
||||||
pathToNode: PathToNode
|
pathToNode: PathToNode
|
||||||
): Program | Error {
|
): Program | Error {
|
||||||
let _modifiedAst: Program = modifiedAst
|
let _modifiedAst: Program = JSON.parse(JSON.stringify(modifiedAst))
|
||||||
|
|
||||||
dependentRanges.forEach((range) => {
|
dependentRanges.forEach((range) => {
|
||||||
const path = getNodePathFromSourceRange(_modifiedAst, range)
|
const path = getNodePathFromSourceRange(_modifiedAst, range)
|
||||||
@ -876,175 +862,3 @@ export function removeSingleConstraintInfo(
|
|||||||
if (err(retval)) return false
|
if (err(retval)) return false
|
||||||
return retval
|
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 {
|
import {
|
||||||
findAllPreviousVariables,
|
findAllPreviousVariables,
|
||||||
isNodeSafeToReplace,
|
isNodeSafeToReplace,
|
||||||
@ -9,7 +9,6 @@ import {
|
|||||||
findUsesOfTagInPipe,
|
findUsesOfTagInPipe,
|
||||||
hasSketchPipeBeenExtruded,
|
hasSketchPipeBeenExtruded,
|
||||||
hasExtrudableGeometry,
|
hasExtrudableGeometry,
|
||||||
traverse,
|
|
||||||
} from './queryAst'
|
} from './queryAst'
|
||||||
import { enginelessExecutor } from '../lib/testHelpers'
|
import { enginelessExecutor } from '../lib/testHelpers'
|
||||||
import {
|
import {
|
||||||
@ -19,7 +18,6 @@ import {
|
|||||||
createPipeSubstitution,
|
createPipeSubstitution,
|
||||||
} from './modifyAst'
|
} from './modifyAst'
|
||||||
import { err } from 'lib/trap'
|
import { err } from 'lib/trap'
|
||||||
import { warn } from 'node:console'
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await initPromise
|
await initPromise
|
||||||
@ -87,7 +85,10 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
expect(result.isSafe).toBe(true)
|
expect(result.isSafe).toBe(true)
|
||||||
expect(result.value?.type).toBe('BinaryExpression')
|
expect(result.value?.type).toBe('BinaryExpression')
|
||||||
expect(code.slice(result.value.start, result.value.end)).toBe('100 + 100')
|
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
|
if (err(replaced)) throw replaced
|
||||||
const outCode = recast(replaced.modifiedAst)
|
const outCode = recast(replaced.modifiedAst)
|
||||||
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
|
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
|
||||||
@ -111,7 +112,10 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
expect(result.isSafe).toBe(true)
|
expect(result.isSafe).toBe(true)
|
||||||
expect(result.value?.type).toBe('CallExpression')
|
expect(result.value?.type).toBe('CallExpression')
|
||||||
expect(code.slice(result.value.start, result.value.end)).toBe("def('yo')")
|
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
|
if (err(replaced)) throw replaced
|
||||||
const outCode = recast(replaced.modifiedAst)
|
const outCode = recast(replaced.modifiedAst)
|
||||||
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
|
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
|
||||||
@ -148,7 +152,10 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
expect(result.isSafe).toBe(true)
|
expect(result.isSafe).toBe(true)
|
||||||
expect(result.value?.type).toBe('BinaryExpression')
|
expect(result.value?.type).toBe('BinaryExpression')
|
||||||
expect(code.slice(result.value.start, result.value.end)).toBe('5 + 6')
|
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
|
if (err(replaced)) throw replaced
|
||||||
const outCode = recast(replaced.modifiedAst)
|
const outCode = recast(replaced.modifiedAst)
|
||||||
expect(outCode).toContain(`const yo = replaceName`)
|
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(
|
expect(code.slice(result.value.start, result.value.end)).toBe(
|
||||||
"jkl('yo') + 2"
|
"jkl('yo') + 2"
|
||||||
)
|
)
|
||||||
const replaced = result.replacer(ast, 'replaceName')
|
const replaced = result.replacer(
|
||||||
|
JSON.parse(JSON.stringify(ast)),
|
||||||
|
'replaceName'
|
||||||
|
)
|
||||||
if (err(replaced)) throw replaced
|
if (err(replaced)) throw replaced
|
||||||
const { modifiedAst } = replaced
|
const { modifiedAst } = replaced
|
||||||
const outCode = recast(modifiedAst)
|
const outCode = recast(modifiedAst)
|
||||||
@ -183,7 +193,10 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
expect(code.slice(result.value.start, result.value.end)).toBe(
|
expect(code.slice(result.value.start, result.value.end)).toBe(
|
||||||
'identifierGuy + 5'
|
'identifierGuy + 5'
|
||||||
)
|
)
|
||||||
const replaced = result.replacer(ast, 'replaceName')
|
const replaced = result.replacer(
|
||||||
|
JSON.parse(JSON.stringify(ast)),
|
||||||
|
'replaceName'
|
||||||
|
)
|
||||||
if (err(replaced)) throw replaced
|
if (err(replaced)) throw replaced
|
||||||
const { modifiedAst } = replaced
|
const { modifiedAst } = replaced
|
||||||
const outCode = recast(modifiedAst)
|
const outCode = recast(modifiedAst)
|
||||||
@ -398,15 +411,15 @@ describe('Testing findUsesOfTagInPipe', () => {
|
|||||||
const exampleCode = `const part001 = startSketchOn('-XZ')
|
const exampleCode = `const part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([68.12, 156.65], %)
|
|> startProfileAt([68.12, 156.65], %)
|
||||||
|> line([306.21, 198.82], %)
|
|> line([306.21, 198.82], %)
|
||||||
|> line([306.21, 198.85], %, $seg01)
|
|> line([306.21, 198.85], %, 'seg01')
|
||||||
|> angledLine([-65, segLen(seg01, %)], %)
|
|> angledLine([-65, segLen('seg01', %)], %)
|
||||||
|> line([306.21, 198.87], %)
|
|> line([306.21, 198.87], %)
|
||||||
|> angledLine([65, segLen(seg01, %)], %)`
|
|> angledLine([65, segLen('seg01', %)], %)`
|
||||||
it('finds the current segment', async () => {
|
it('finds the current segment', async () => {
|
||||||
const ast = parse(exampleCode)
|
const ast = parse(exampleCode)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
|
|
||||||
const lineOfInterest = `198.85], %, $seg01`
|
const lineOfInterest = `198.85], %, 'seg01'`
|
||||||
const characterIndex =
|
const characterIndex =
|
||||||
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
|
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
|
||||||
const pathToNode = getNodePathFromSourceRange(ast, [
|
const pathToNode = getNodePathFromSourceRange(ast, [
|
||||||
@ -441,7 +454,7 @@ describe('Testing hasSketchPipeBeenExtruded', () => {
|
|||||||
|> line([2.48, 2.44], %)
|
|> line([2.48, 2.44], %)
|
||||||
|> line([2.66, 1.17], %)
|
|> line([2.66, 1.17], %)
|
||||||
|> line([3.75, 0.46], %)
|
|> line([3.75, 0.46], %)
|
||||||
|> line([4.99, -0.46], %, $seg01)
|
|> line([4.99, -0.46], %, 'seg01')
|
||||||
|> line([3.3, -2.12], %)
|
|> line([3.3, -2.12], %)
|
||||||
|> line([2.16, -3.33], %)
|
|> line([2.16, -3.33], %)
|
||||||
|> line([0.85, -3.08], %)
|
|> line([0.85, -3.08], %)
|
||||||
@ -450,7 +463,7 @@ describe('Testing hasSketchPipeBeenExtruded', () => {
|
|||||||
|> line([-17.67, 0.85], %)
|
|> line([-17.67, 0.85], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(10, sketch001)
|
const extrude001 = extrude(10, sketch001)
|
||||||
const sketch002 = startSketchOn(extrude001, $seg01)
|
const sketch002 = startSketchOn(extrude001, 'seg01')
|
||||||
|> startProfileAt([-12.94, 6.6], %)
|
|> startProfileAt([-12.94, 6.6], %)
|
||||||
|> line([2.45, -0.2], %)
|
|> line([2.45, -0.2], %)
|
||||||
|> line([-2, -1.25], %)
|
|> line([-2, -1.25], %)
|
||||||
@ -460,7 +473,7 @@ const sketch002 = startSketchOn(extrude001, $seg01)
|
|||||||
it('finds sketch001 pipe to be extruded', async () => {
|
it('finds sketch001 pipe to be extruded', async () => {
|
||||||
const ast = parse(exampleCode)
|
const ast = parse(exampleCode)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const lineOfInterest = `line([4.99, -0.46], %, $seg01)`
|
const lineOfInterest = `line([4.99, -0.46], %, 'seg01')`
|
||||||
const characterIndex =
|
const characterIndex =
|
||||||
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
|
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
|
||||||
const extruded = hasSketchPipeBeenExtruded(
|
const extruded = hasSketchPipeBeenExtruded(
|
||||||
@ -498,7 +511,7 @@ describe('Testing hasExtrudableGeometry', () => {
|
|||||||
|> line([-17.67, 0.85], %)
|
|> line([-17.67, 0.85], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(10, sketch001)
|
const extrude001 = extrude(10, sketch001)
|
||||||
const sketch002 = startSketchOn(extrude001, $seg01)
|
const sketch002 = startSketchOn(extrude001, 'seg01')
|
||||||
|> startProfileAt([-12.94, 6.6], %)
|
|> startProfileAt([-12.94, 6.6], %)
|
||||||
|> line([2.45, -0.2], %)
|
|> line([2.45, -0.2], %)
|
||||||
|> line([-2, -1.25], %)
|
|> line([-2, -1.25], %)
|
||||||
@ -525,53 +538,3 @@ const extrude001 = extrude(10, sketch001)
|
|||||||
expect(extrudable).toBeFalsy()
|
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
|
if (_node.type === 'PipeSubstitution' && isInRange) return path
|
||||||
console.error('not implemented: ' + node.type)
|
console.error('not implemented: ' + node.type)
|
||||||
return path
|
return path
|
||||||
@ -319,89 +307,48 @@ type KCLNode =
|
|||||||
| ReturnStatement
|
| ReturnStatement
|
||||||
|
|
||||||
export function traverse(
|
export function traverse(
|
||||||
node: KCLNode | Program,
|
node: KCLNode,
|
||||||
option: {
|
option: {
|
||||||
enter?: (node: KCLNode, pathToNode: PathToNode) => void
|
enter?: (node: KCLNode) => void
|
||||||
leave?: (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> {
|
export interface PrevVariable<T> {
|
||||||
@ -520,8 +467,8 @@ export function isNodeSafeToReplacePath(
|
|||||||
const replaceNodeWithIdentifier: ReplacerFn = (_ast, varName) => {
|
const replaceNodeWithIdentifier: ReplacerFn = (_ast, varName) => {
|
||||||
const identifier = createIdentifier(varName)
|
const identifier = createIdentifier(varName)
|
||||||
const last = finPath[finPath.length - 1]
|
const last = finPath[finPath.length - 1]
|
||||||
const pathToReplaced = finPath
|
const pathToReplaced = JSON.parse(JSON.stringify(finPath))
|
||||||
pathToReplaced[1][0] = (pathToReplaced[1][0] as number) + 1
|
pathToReplaced[1][0] = pathToReplaced[1][0] + 1
|
||||||
const startPath = finPath.slice(0, -1)
|
const startPath = finPath.slice(0, -1)
|
||||||
const _nodeToReplace = getNodeFromPath(_ast, startPath)
|
const _nodeToReplace = getNodeFromPath(_ast, startPath)
|
||||||
if (err(_nodeToReplace)) return _nodeToReplace
|
if (err(_nodeToReplace)) return _nodeToReplace
|
||||||
@ -787,14 +734,8 @@ export function findUsesOfTagInPipe(
|
|||||||
if (node.type !== 'CallExpression') return []
|
if (node.type !== 'CallExpression') return []
|
||||||
const tagIndex = node.callee.name === 'close' ? 1 : 2
|
const tagIndex = node.callee.name === 'close' ? 1 : 2
|
||||||
const thirdParam = node.arguments[tagIndex]
|
const thirdParam = node.arguments[tagIndex]
|
||||||
if (
|
if (thirdParam?.type !== 'Literal') return []
|
||||||
!(thirdParam?.type === 'TagDeclarator' || thirdParam?.type === 'Identifier')
|
const tag = String(thirdParam.value)
|
||||||
)
|
|
||||||
return []
|
|
||||||
const tag =
|
|
||||||
thirdParam?.type === 'TagDeclarator'
|
|
||||||
? String(thirdParam.value)
|
|
||||||
: thirdParam.name
|
|
||||||
|
|
||||||
const varDec = getNodeFromPath<VariableDeclaration>(
|
const varDec = getNodeFromPath<VariableDeclaration>(
|
||||||
ast,
|
ast,
|
||||||
@ -815,11 +756,9 @@ export function findUsesOfTagInPipe(
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
const tagArg = node.arguments[0]
|
const tagArg = node.arguments[0]
|
||||||
if (!(tagArg.type === 'TagDeclarator' || tagArg.type === 'Identifier'))
|
if (tagArg.type !== 'Literal') return
|
||||||
return
|
if (String(tagArg.value) === tag)
|
||||||
const tagArgValue =
|
dependentRanges.push([node.start, node.end])
|
||||||
tagArg.type === 'TagDeclarator' ? String(tagArg.value) : tagArg.name
|
|
||||||
if (tagArgValue === tag) dependentRanges.push([node.start, node.end])
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return dependentRanges
|
return dependentRanges
|
||||||
|
@ -76,9 +76,9 @@ log(5, myVar)
|
|||||||
})
|
})
|
||||||
it('recast sketch declaration', () => {
|
it('recast sketch declaration', () => {
|
||||||
let code = `const mySketch = startSketchAt([0, 0])
|
let code = `const mySketch = startSketchAt([0, 0])
|
||||||
|> lineTo([0, 1], %, $myPath)
|
|> lineTo([0, 1], %, "myPath")
|
||||||
|> lineTo([1, 1], %)
|
|> lineTo([1, 1], %)
|
||||||
|> lineTo([1, 0], %, $rightPath)
|
|> lineTo([1, 0], %, "rightPath")
|
||||||
|> close(%)
|
|> close(%)
|
||||||
`
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
@ -90,7 +90,7 @@ log(5, myVar)
|
|||||||
const code = [
|
const code = [
|
||||||
'const mySk1 = startSketchAt([0, 0])',
|
'const mySk1 = startSketchAt([0, 0])',
|
||||||
' |> lineTo([1, 1], %)',
|
' |> lineTo([1, 1], %)',
|
||||||
' |> lineTo([0, 1], %, $myTag)',
|
' |> lineTo([0, 1], %, "myTag")',
|
||||||
' |> lineTo([1, 1], %)',
|
' |> lineTo([1, 1], %)',
|
||||||
' |> rx(90, %)',
|
' |> rx(90, %)',
|
||||||
].join('\n')
|
].join('\n')
|
||||||
@ -266,7 +266,7 @@ const key = 'c'
|
|||||||
const code = [
|
const code = [
|
||||||
'const mySk1 = startSketchAt([0, 0])',
|
'const mySk1 = startSketchAt([0, 0])',
|
||||||
' |> lineTo([1, 1], %)',
|
' |> lineTo([1, 1], %)',
|
||||||
' |> lineTo([0, 1], %, $myTag)',
|
' |> lineTo([0, 1], %, "myTag")',
|
||||||
' |> lineTo([1, 1], %)',
|
' |> lineTo([1, 1], %)',
|
||||||
' // a comment',
|
' // a comment',
|
||||||
' |> rx(90, %)',
|
' |> rx(90, %)',
|
||||||
@ -283,7 +283,7 @@ const key = 'c'
|
|||||||
const mySk1 = startSketchAt([0, 0])
|
const mySk1 = startSketchAt([0, 0])
|
||||||
|> lineTo([1, 1], %)
|
|> lineTo([1, 1], %)
|
||||||
// comment here
|
// comment here
|
||||||
|> lineTo([0, 1], %, $myTag)
|
|> lineTo([0, 1], %, 'myTag')
|
||||||
|> lineTo([1, 1], %) /* and
|
|> lineTo([1, 1], %) /* and
|
||||||
here
|
here
|
||||||
*/
|
*/
|
||||||
@ -306,7 +306,7 @@ one more for good measure
|
|||||||
const mySk1 = startSketchAt([0, 0])
|
const mySk1 = startSketchAt([0, 0])
|
||||||
|> lineTo([1, 1], %)
|
|> lineTo([1, 1], %)
|
||||||
// comment here
|
// comment here
|
||||||
|> lineTo([0, 1], %, $myTag)
|
|> lineTo([0, 1], %, 'myTag')
|
||||||
|> lineTo([1, 1], %) /* and
|
|> lineTo([1, 1], %) /* and
|
||||||
here */
|
here */
|
||||||
// a comment between pipe expression statements
|
// 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', () => {
|
describe('it recasts wrapped object expressions in pipe bodies with correct indentation', () => {
|
||||||
it('with a single line', () => {
|
it('with a single line', () => {
|
||||||
const code = `const part001 = startSketchAt([-0.01, -0.08])
|
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], %)
|
|> line([2.77, -1.24], %)
|
||||||
|> angledLineThatIntersects({
|
|> angledLineThatIntersects({
|
||||||
angle: 201,
|
angle: 201,
|
||||||
offset: -1.35,
|
offset: -1.35,
|
||||||
intersectTag: $seg01
|
intersectTag: 'seg01'
|
||||||
}, %)
|
}, %)
|
||||||
|> line([-0.42, -1.72], %)
|
|> line([-0.42, -1.72], %)
|
||||||
`
|
`
|
||||||
@ -374,7 +374,7 @@ describe('it recasts wrapped object expressions in pipe bodies with correct inde
|
|||||||
const code = `angledLineThatIntersects({
|
const code = `angledLineThatIntersects({
|
||||||
angle: 201,
|
angle: 201,
|
||||||
offset: -1.35,
|
offset: -1.35,
|
||||||
intersectTag: $seg01
|
intersectTag: 'seg01'
|
||||||
}, %)
|
}, %)
|
||||||
`
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
|
@ -1249,29 +1249,6 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.initPlanes().then(async () => {
|
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()
|
this.resolveReady()
|
||||||
setIsStreamReady(true)
|
setIsStreamReady(true)
|
||||||
await executeCode()
|
await executeCode()
|
||||||
|
@ -230,7 +230,7 @@ describe('testing addTagForSketchOnFace', () => {
|
|||||||
if (err(sketchOnFaceRetVal)) return sketchOnFaceRetVal
|
if (err(sketchOnFaceRetVal)) return sketchOnFaceRetVal
|
||||||
|
|
||||||
const { modifiedAst } = 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)
|
expect(recast(modifiedAst)).toBe(expectedCode)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -11,7 +11,6 @@ import {
|
|||||||
Value,
|
Value,
|
||||||
Literal,
|
Literal,
|
||||||
VariableDeclaration,
|
VariableDeclaration,
|
||||||
Identifier,
|
|
||||||
} from 'lang/wasm'
|
} from 'lang/wasm'
|
||||||
import {
|
import {
|
||||||
getNodeFromPath,
|
getNodeFromPath,
|
||||||
@ -41,7 +40,6 @@ import {
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
createLiteral,
|
createLiteral,
|
||||||
createTagDeclarator,
|
|
||||||
createCallExpression,
|
createCallExpression,
|
||||||
createArrayExpression,
|
createArrayExpression,
|
||||||
createPipeSubstitution,
|
createPipeSubstitution,
|
||||||
@ -53,7 +51,6 @@ import {
|
|||||||
import { roundOff, getLength, getAngle } from 'lib/utils'
|
import { roundOff, getLength, getAngle } from 'lib/utils'
|
||||||
import { err } from 'lib/trap'
|
import { err } from 'lib/trap'
|
||||||
import { perpendicularDistance } from 'sketch-helpers'
|
import { perpendicularDistance } from 'sketch-helpers'
|
||||||
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
|
|
||||||
|
|
||||||
export type Coords2d = [number, number]
|
export type Coords2d = [number, number]
|
||||||
|
|
||||||
@ -1409,7 +1406,7 @@ export const angledLineThatIntersects: SketchLineHelper = {
|
|||||||
?.value || createLiteral('')
|
?.value || createLiteral('')
|
||||||
: createLiteral('')
|
: createLiteral('')
|
||||||
const intersectTagName =
|
const intersectTagName =
|
||||||
intersectTag.type === 'Identifier' ? intersectTag.name : ''
|
intersectTag.type === 'Literal' ? intersectTag.value : ''
|
||||||
const nodeMeta2 = getNodeFromPath<VariableDeclaration>(
|
const nodeMeta2 = getNodeFromPath<VariableDeclaration>(
|
||||||
_node,
|
_node,
|
||||||
pathToNode,
|
pathToNode,
|
||||||
@ -1500,23 +1497,23 @@ export const angledLineThatIntersects: SketchLineHelper = {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (intersectTag !== -1) {
|
if (intersectTag !== -1) {
|
||||||
const tag = firstArg.properties[intersectTag]?.value as Identifier
|
const tag = firstArg.properties[intersectTag]?.value
|
||||||
const pathToTagProp: PathToNode = [
|
const pathToTagProp: PathToNode = [
|
||||||
...pathToObjectExp,
|
...pathToObjectExp,
|
||||||
[intersectTag, 'index'],
|
[intersectTag, 'index'],
|
||||||
['value', 'Property'],
|
['value', 'Property'],
|
||||||
]
|
]
|
||||||
const info = constrainInfo(
|
returnVal.push(
|
||||||
'intersectionTag',
|
constrainInfo(
|
||||||
// This will always be a tag identifier.
|
'intersectionTag',
|
||||||
false,
|
isNotLiteralArrayOrStatic(tag),
|
||||||
code.slice(tag.start, tag.end),
|
code.slice(tag.start, tag.end),
|
||||||
'angledLineThatIntersects',
|
'angledLineThatIntersects',
|
||||||
'intersectTag',
|
'intersectTag',
|
||||||
[tag.start, tag.end],
|
[tag.start, tag.end],
|
||||||
pathToTagProp
|
pathToTagProp
|
||||||
|
)
|
||||||
)
|
)
|
||||||
returnVal.push(info)
|
|
||||||
}
|
}
|
||||||
return returnVal
|
return returnVal
|
||||||
},
|
},
|
||||||
@ -1833,18 +1830,17 @@ function addTag(tagIndex = 2): addTagFn {
|
|||||||
// Tag is always 3rd expression now, using arg index feels brittle
|
// Tag is always 3rd expression now, using arg index feels brittle
|
||||||
// but we can come up with a better way to identify tag later.
|
// but we can come up with a better way to identify tag later.
|
||||||
const thirdArg = primaryCallExp.arguments?.[tagIndex]
|
const thirdArg = primaryCallExp.arguments?.[tagIndex]
|
||||||
const tagDeclarator =
|
const tagLiteral =
|
||||||
thirdArg ||
|
thirdArg || (createLiteral(findUniqueName(_node, 'seg', 2)) as Literal)
|
||||||
(createTagDeclarator(findUniqueName(_node, 'seg', 2)) as TagDeclarator)
|
|
||||||
const isTagExisting = !!thirdArg
|
const isTagExisting = !!thirdArg
|
||||||
if (!isTagExisting) {
|
if (!isTagExisting) {
|
||||||
primaryCallExp.arguments[tagIndex] = tagDeclarator
|
primaryCallExp.arguments[tagIndex] = tagLiteral
|
||||||
}
|
}
|
||||||
if ('value' in tagDeclarator) {
|
if ('value' in tagLiteral) {
|
||||||
// Now TypeScript knows tagDeclarator has a value property
|
// Now TypeScript knows tagLiteral has a value property
|
||||||
return {
|
return {
|
||||||
modifiedAst: _node,
|
modifiedAst: _node,
|
||||||
tag: String(tagDeclarator.value),
|
tag: String(tagLiteral.value),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return new Error('Unable to assign tag without value')
|
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 bigExampleArr = [
|
||||||
`const part001 = startSketchOn('XY')`,
|
`const part001 = startSketchOn('XY')`,
|
||||||
` |> startProfileAt([0, 0], %)`,
|
` |> startProfileAt([0, 0], %)`,
|
||||||
` |> lineTo([1, 1], %, $abc1)`,
|
` |> lineTo([1, 1], %, 'abc1')`,
|
||||||
` |> line([-2.04, -0.7], %, $abc2)`,
|
` |> line([-2.04, -0.7], %, 'abc2')`,
|
||||||
` |> angledLine({ angle: 157, length: 1.69 }, %, $abc3)`,
|
` |> angledLine({ angle: 157, length: 1.69 }, %, 'abc3')`,
|
||||||
` |> angledLineOfXLength({ angle: 217, length: 0.86 }, %, $abc4)`,
|
` |> angledLineOfXLength({ angle: 217, length: 0.86 }, %, 'abc4')`,
|
||||||
` |> angledLineOfYLength({ angle: 104, length: 1.58 }, %, $abc5)`,
|
` |> angledLineOfYLength({ angle: 104, length: 1.58 }, %, 'abc5')`,
|
||||||
` |> angledLineToX({ angle: 55, to: -2.89 }, %, $abc6)`,
|
` |> angledLineToX({ angle: 55, to: -2.89 }, %, 'abc6')`,
|
||||||
` |> angledLineToY({ angle: 330, to: 2.53 }, %, $abc7)`,
|
` |> angledLineToY({ angle: 330, to: 2.53 }, %, 'abc7')`,
|
||||||
` |> xLine(1.47, %, $abc8)`,
|
` |> xLine(1.47, %, 'abc8')`,
|
||||||
` |> yLine(1.57, %, $abc9)`,
|
` |> yLine(1.57, %, 'abc9')`,
|
||||||
` |> xLineTo(1.49, %, $abc10)`,
|
` |> xLineTo(1.49, %, 'abc10')`,
|
||||||
` |> yLineTo(2.64, %, $abc11)`,
|
` |> yLineTo(2.64, %, 'abc11')`,
|
||||||
` |> lineTo([2.55, 3.58], %) // lineTo`,
|
` |> lineTo([2.55, 3.58], %) // lineTo`,
|
||||||
` |> line([0.73, -0.75], %)`,
|
` |> line([0.73, -0.75], %)`,
|
||||||
` |> angledLine([63, 1.38], %) // angledLine`,
|
` |> angledLine([63, 1.38], %) // angledLine`,
|
||||||
@ -90,8 +90,8 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
|
|||||||
]
|
]
|
||||||
const bigExample = bigExampleArr.join('\n')
|
const bigExample = bigExampleArr.join('\n')
|
||||||
it('line with tag converts to xLine', async () => {
|
it('line with tag converts to xLine', async () => {
|
||||||
const callToSwap = 'line([-2.04, -0.7], %, $abc2)'
|
const callToSwap = "line([-2.04, -0.7], %, 'abc2')"
|
||||||
const expectedLine = 'xLine(-2.04, %, $abc2)'
|
const expectedLine = "xLine(-2.04, %, 'abc2')"
|
||||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||||
inputCode: bigExample,
|
inputCode: bigExample,
|
||||||
callToSwap,
|
callToSwap,
|
||||||
@ -116,10 +116,10 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
|
|||||||
it('lineTo with tag converts to xLineTo', async () => {
|
it('lineTo with tag converts to xLineTo', async () => {
|
||||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||||
inputCode: bigExample,
|
inputCode: bigExample,
|
||||||
callToSwap: 'lineTo([1, 1], %, $abc1)',
|
callToSwap: "lineTo([1, 1], %, 'abc1')",
|
||||||
constraintType: 'horizontal',
|
constraintType: 'horizontal',
|
||||||
})
|
})
|
||||||
const expectedLine = 'xLineTo(1, %, $abc1)'
|
const expectedLine = "xLineTo(1, %, 'abc1')"
|
||||||
expect(newCode).toContain(expectedLine)
|
expect(newCode).toContain(expectedLine)
|
||||||
// new line should start at the same place as the old line
|
// new line should start at the same place as the old line
|
||||||
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
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 () => {
|
it('angledLine with tag converts to xLine', async () => {
|
||||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||||
inputCode: bigExample,
|
inputCode: bigExample,
|
||||||
callToSwap: 'angledLine({ angle: 157, length: 1.69 }, %, $abc3)',
|
callToSwap: "angledLine({ angle: 157, length: 1.69 }, %, 'abc3')",
|
||||||
constraintType: 'horizontal',
|
constraintType: 'horizontal',
|
||||||
})
|
})
|
||||||
const expectedLine = 'xLine(-1.56, %, $abc3)'
|
const expectedLine = "xLine(-1.56, %, 'abc3')"
|
||||||
console.log(newCode)
|
console.log(newCode)
|
||||||
expect(newCode).toContain(expectedLine)
|
expect(newCode).toContain(expectedLine)
|
||||||
// new line should start at the same place as the old line
|
// 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 () => {
|
it('angledLineOfXLength with tag converts to xLine', async () => {
|
||||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||||
inputCode: bigExample,
|
inputCode: bigExample,
|
||||||
callToSwap: 'angledLineOfXLength({ angle: 217, length: 0.86 }, %, $abc4)',
|
callToSwap:
|
||||||
|
"angledLineOfXLength({ angle: 217, length: 0.86 }, %, 'abc4')",
|
||||||
constraintType: 'horizontal',
|
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`
|
// hmm "-0.86" is correct since the angle is 104, but need to make sure this is compatible `-myVar`
|
||||||
expect(newCode).toContain(expectedLine)
|
expect(newCode).toContain(expectedLine)
|
||||||
// new line should start at the same place as the old line
|
// 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 () => {
|
it('angledLineOfYLength with tag converts to yLine', async () => {
|
||||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||||
inputCode: bigExample,
|
inputCode: bigExample,
|
||||||
callToSwap: 'angledLineOfYLength({ angle: 104, length: 1.58 }, %, $abc5)',
|
callToSwap:
|
||||||
|
"angledLineOfYLength({ angle: 104, length: 1.58 }, %, 'abc5')",
|
||||||
constraintType: 'vertical',
|
constraintType: 'vertical',
|
||||||
})
|
})
|
||||||
const expectedLine = 'yLine(1.58, %, $abc5)'
|
const expectedLine = "yLine(1.58, %, 'abc5')"
|
||||||
expect(newCode).toContain(expectedLine)
|
expect(newCode).toContain(expectedLine)
|
||||||
// new line should start at the same place as the old line
|
// new line should start at the same place as the old line
|
||||||
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
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 () => {
|
it('angledLineToX with tag converts to xLineTo', async () => {
|
||||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||||
inputCode: bigExample,
|
inputCode: bigExample,
|
||||||
callToSwap: 'angledLineToX({ angle: 55, to: -2.89 }, %, $abc6)',
|
callToSwap: "angledLineToX({ angle: 55, to: -2.89 }, %, 'abc6')",
|
||||||
constraintType: 'horizontal',
|
constraintType: 'horizontal',
|
||||||
})
|
})
|
||||||
const expectedLine = 'xLineTo(-2.89, %, $abc6)'
|
const expectedLine = "xLineTo(-2.89, %, 'abc6')"
|
||||||
expect(newCode).toContain(expectedLine)
|
expect(newCode).toContain(expectedLine)
|
||||||
// new line should start at the same place as the old line
|
// new line should start at the same place as the old line
|
||||||
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
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 () => {
|
it('angledLineToY with tag converts to yLineTo', async () => {
|
||||||
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
||||||
inputCode: bigExample,
|
inputCode: bigExample,
|
||||||
callToSwap: 'angledLineToY({ angle: 330, to: 2.53 }, %, $abc7)',
|
callToSwap: "angledLineToY({ angle: 330, to: 2.53 }, %, 'abc7')",
|
||||||
constraintType: 'vertical',
|
constraintType: 'vertical',
|
||||||
})
|
})
|
||||||
const expectedLine = 'yLineTo(2.53, %, $abc7)'
|
const expectedLine = "yLineTo(2.53, %, 'abc7')"
|
||||||
expect(newCode).toContain(expectedLine)
|
expect(newCode).toContain(expectedLine)
|
||||||
// new line should start at the same place as the old line
|
// new line should start at the same place as the old line
|
||||||
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
||||||
|
@ -139,70 +139,70 @@ const myAng = 40
|
|||||||
const myAng2 = 134
|
const myAng2 = 134
|
||||||
const part001 = startSketchOn('XY')
|
const part001 = startSketchOn('XY')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([1, 3.82], %, $seg01) // ln-should-get-tag
|
|> line([1, 3.82], %, 'seg01') // ln-should-get-tag
|
||||||
|> angledLineToX([
|
|> angledLineToX([
|
||||||
-angleToMatchLengthX(seg01, myVar, %),
|
-angleToMatchLengthX('seg01', myVar, %),
|
||||||
myVar
|
myVar
|
||||||
], %) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|
], %) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|
||||||
|> angledLineToY([
|
|> angledLineToY([
|
||||||
-angleToMatchLengthY(seg01, myVar, %),
|
-angleToMatchLengthY('seg01', myVar, %),
|
||||||
myVar
|
myVar
|
||||||
], %) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper
|
], %) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper
|
||||||
|> angledLine([45, segLen(seg01, %)], %) // ln-lineTo-free should become angledLine
|
|> angledLine([45, segLen('seg01', %)], %) // ln-lineTo-free should become angledLine
|
||||||
|> angledLine([45, segLen(seg01, %)], %) // ln-angledLineToX-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([myAng, segLen('seg01', %)], %) // ln-angledLineToX-angle should become angledLine
|
||||||
|> angledLineToX([
|
|> angledLineToX([
|
||||||
angleToMatchLengthX(seg01, myVar2, %),
|
angleToMatchLengthX('seg01', myVar2, %),
|
||||||
myVar2
|
myVar2
|
||||||
], %) // ln-angledLineToX-xAbsolute should use angleToMatchLengthX to get angle
|
], %) // ln-angledLineToX-xAbsolute should use angleToMatchLengthX to get angle
|
||||||
|> angledLine([-45, segLen(seg01, %)], %) // ln-angledLineToY-free should become angledLine
|
|> angledLine([-45, segLen('seg01', %)], %) // ln-angledLineToY-free should become angledLine
|
||||||
|> angledLine([myAng2, segLen(seg01, %)], %) // ln-angledLineToY-angle should become angledLine
|
|> angledLine([myAng2, segLen('seg01', %)], %) // ln-angledLineToY-angle should become angledLine
|
||||||
|> angledLineToY([
|
|> angledLineToY([
|
||||||
angleToMatchLengthY(seg01, myVar3, %),
|
angleToMatchLengthY('seg01', myVar3, %),
|
||||||
myVar3
|
myVar3
|
||||||
], %) // ln-angledLineToY-yAbsolute should use angleToMatchLengthY to get angle
|
], %) // ln-angledLineToY-yAbsolute should use angleToMatchLengthY to get angle
|
||||||
|> line([
|
|> line([
|
||||||
min(segLen(seg01, %), myVar),
|
min(segLen('seg01', %), myVar),
|
||||||
legLen(segLen(seg01, %), myVar)
|
legLen(segLen('seg01', %), myVar)
|
||||||
], %) // ln-should use legLen for y
|
], %) // ln-should use legLen for y
|
||||||
|> line([
|
|> line([
|
||||||
min(segLen(seg01, %), myVar),
|
min(segLen('seg01', %), myVar),
|
||||||
-legLen(segLen(seg01, %), myVar)
|
-legLen(segLen('seg01', %), myVar)
|
||||||
], %) // ln-legLen but negative
|
], %) // ln-legLen but negative
|
||||||
|> angledLine([-112, segLen(seg01, %)], %) // ln-should become angledLine
|
|> angledLine([-112, segLen('seg01', %)], %) // ln-should become angledLine
|
||||||
|> angledLine([myVar, segLen(seg01, %)], %) // ln-use segLen for second arg
|
|> angledLine([myVar, segLen('seg01', %)], %) // ln-use segLen for second arg
|
||||||
|> angledLine([45, segLen(seg01, %)], %) // ln-segLen again
|
|> angledLine([45, segLen('seg01', %)], %) // ln-segLen again
|
||||||
|> angledLine([54, segLen(seg01, %)], %) // ln-should be transformed to angledLine
|
|> angledLine([54, segLen('seg01', %)], %) // ln-should be transformed to angledLine
|
||||||
|> angledLineOfXLength([
|
|> angledLineOfXLength([
|
||||||
legAngX(segLen(seg01, %), myVar),
|
legAngX(segLen('seg01', %), myVar),
|
||||||
min(segLen(seg01, %), myVar)
|
min(segLen('seg01', %), myVar)
|
||||||
], %) // ln-should use legAngX to calculate angle
|
], %) // ln-should use legAngX to calculate angle
|
||||||
|> angledLineOfXLength([
|
|> angledLineOfXLength([
|
||||||
180 + legAngX(segLen(seg01, %), myVar),
|
180 + legAngX(segLen('seg01', %), myVar),
|
||||||
min(segLen(seg01, %), myVar)
|
min(segLen('seg01', %), myVar)
|
||||||
], %) // ln-same as above but should have + 180 to match original quadrant
|
], %) // ln-same as above but should have + 180 to match original quadrant
|
||||||
|> line([
|
|> line([
|
||||||
legLen(segLen(seg01, %), myVar),
|
legLen(segLen('seg01', %), myVar),
|
||||||
min(segLen(seg01, %), myVar)
|
min(segLen('seg01', %), myVar)
|
||||||
], %) // ln-legLen again but yRelative
|
], %) // ln-legLen again but yRelative
|
||||||
|> line([
|
|> line([
|
||||||
-legLen(segLen(seg01, %), myVar),
|
-legLen(segLen('seg01', %), myVar),
|
||||||
min(segLen(seg01, %), myVar)
|
min(segLen('seg01', %), myVar)
|
||||||
], %) // ln-negative legLen yRelative
|
], %) // ln-negative legLen yRelative
|
||||||
|> angledLine([58, segLen(seg01, %)], %) // ln-angledLineOfYLength-free should become angledLine
|
|> angledLine([58, segLen('seg01', %)], %) // ln-angledLineOfYLength-free should become angledLine
|
||||||
|> angledLine([myAng, segLen(seg01, %)], %) // ln-angledLineOfYLength-angle should become angledLine
|
|> angledLine([myAng, segLen('seg01', %)], %) // ln-angledLineOfYLength-angle should become angledLine
|
||||||
|> angledLineOfXLength([
|
|> angledLineOfXLength([
|
||||||
legAngY(segLen(seg01, %), myVar),
|
legAngY(segLen('seg01', %), myVar),
|
||||||
min(segLen(seg01, %), myVar)
|
min(segLen('seg01', %), myVar)
|
||||||
], %) // ln-angledLineOfYLength-yRelative use legAngY
|
], %) // ln-angledLineOfYLength-yRelative use legAngY
|
||||||
|> angledLineOfXLength([
|
|> angledLineOfXLength([
|
||||||
270 + legAngY(segLen(seg01, %), myVar),
|
270 + legAngY(segLen('seg01', %), myVar),
|
||||||
min(segLen(seg01, %), myVar)
|
min(segLen('seg01', %), myVar)
|
||||||
], %) // ln-angledLineOfYLength-yRelative with angle > 90 use binExp
|
], %) // ln-angledLineOfYLength-yRelative with angle > 90 use binExp
|
||||||
|> xLine(segLen(seg01, %), %) // ln-xLine-free should sub in segLen
|
|> xLine(segLen('seg01', %), %) // ln-xLine-free should sub in segLen
|
||||||
|> yLine(segLen(seg01, %), %) // ln-yLine-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
|
|> xLine(segLen('seg01', %), %) // ln-xLineTo-free should convert to xLine
|
||||||
|> yLine(segLen(seg01, %), %) // ln-yLineTo-free should convert to yLine
|
|> yLine(segLen('seg01', %), %) // ln-yLineTo-free should convert to yLine
|
||||||
`
|
`
|
||||||
it('should transform the ast', async () => {
|
it('should transform the ast', async () => {
|
||||||
const ast = parse(inputScript)
|
const ast = parse(inputScript)
|
||||||
@ -417,10 +417,10 @@ const part001 = startSketchOn('XY')
|
|||||||
'setVertDistance'
|
'setVertDistance'
|
||||||
)
|
)
|
||||||
expect(expectedHorizontalCode).toContain(
|
expect(expectedHorizontalCode).toContain(
|
||||||
`lineTo([segEndX(seg01, %) + 0.9, 4.59], %) // free`
|
`lineTo([segEndX('seg01', %) + 0.9, 4.59], %) // free`
|
||||||
)
|
)
|
||||||
expect(expectedVerticalCode).toContain(
|
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 () => {
|
it('testing for xRelative to vertical distance', async () => {
|
||||||
@ -431,7 +431,7 @@ const part001 = startSketchOn('XY')
|
|||||||
)
|
)
|
||||||
expect(expectedCode).toContain(`|> lineTo([
|
expect(expectedCode).toContain(`|> lineTo([
|
||||||
lastSegX(%) + myVar,
|
lastSegX(%) + myVar,
|
||||||
segEndY(seg01, %) + 2.93
|
segEndY('seg01', %) + 2.93
|
||||||
], %) // xRelative`)
|
], %) // xRelative`)
|
||||||
})
|
})
|
||||||
it('testing for yRelative to horizontal distance', async () => {
|
it('testing for yRelative to horizontal distance', async () => {
|
||||||
@ -441,7 +441,7 @@ const part001 = startSketchOn('XY')
|
|||||||
'setHorzDistance'
|
'setHorzDistance'
|
||||||
)
|
)
|
||||||
expect(expectedCode).toContain(`|> lineTo([
|
expect(expectedCode).toContain(`|> lineTo([
|
||||||
segEndX(seg01, %) + 2.6,
|
segEndX('seg01', %) + 2.6,
|
||||||
lastSegY(%) + myVar
|
lastSegY(%) + myVar
|
||||||
], %) // yRelative`)
|
], %) // yRelative`)
|
||||||
})
|
})
|
||||||
|
@ -462,7 +462,7 @@ const setAngledIntersectLineForLines: TransformInfo['createNode'] =
|
|||||||
angleVal,
|
angleVal,
|
||||||
offsetVal:
|
offsetVal:
|
||||||
forceValueUsedInTransform || createLiteral(valueUsedInTransform),
|
forceValueUsedInTransform || createLiteral(valueUsedInTransform),
|
||||||
intersectTag: createIdentifier(referenceSegName),
|
intersectTag: createLiteral(referenceSegName),
|
||||||
tag,
|
tag,
|
||||||
valueUsedInTransform,
|
valueUsedInTransform,
|
||||||
})
|
})
|
||||||
@ -481,7 +481,7 @@ const setAngledIntersectForAngledLines: TransformInfo['createNode'] =
|
|||||||
angleVal: varValA,
|
angleVal: varValA,
|
||||||
offsetVal:
|
offsetVal:
|
||||||
forceValueUsedInTransform || createLiteral(valueUsedInTransform),
|
forceValueUsedInTransform || createLiteral(valueUsedInTransform),
|
||||||
intersectTag: createIdentifier(referenceSegName),
|
intersectTag: createLiteral(referenceSegName),
|
||||||
tag,
|
tag,
|
||||||
valueUsedInTransform,
|
valueUsedInTransform,
|
||||||
})
|
})
|
||||||
@ -675,7 +675,7 @@ const transformMap: TransformMap = {
|
|||||||
const angleToMatchLengthXCall = createCallExpression(
|
const angleToMatchLengthXCall = createCallExpression(
|
||||||
'angleToMatchLengthX',
|
'angleToMatchLengthX',
|
||||||
[
|
[
|
||||||
createIdentifier(referenceSegName),
|
createLiteral(referenceSegName),
|
||||||
varValA,
|
varValA,
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
]
|
]
|
||||||
@ -708,7 +708,7 @@ const transformMap: TransformMap = {
|
|||||||
const angleToMatchLengthYCall = createCallExpression(
|
const angleToMatchLengthYCall = createCallExpression(
|
||||||
'angleToMatchLengthY',
|
'angleToMatchLengthY',
|
||||||
[
|
[
|
||||||
createIdentifier(referenceSegName),
|
createLiteral(referenceSegName),
|
||||||
varValB,
|
varValB,
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
]
|
]
|
||||||
@ -973,7 +973,7 @@ const transformMap: TransformMap = {
|
|||||||
const angleToMatchLengthXCall = createCallExpression(
|
const angleToMatchLengthXCall = createCallExpression(
|
||||||
'angleToMatchLengthX',
|
'angleToMatchLengthX',
|
||||||
[
|
[
|
||||||
createIdentifier(referenceSegName),
|
createLiteral(referenceSegName),
|
||||||
varValB,
|
varValB,
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
]
|
]
|
||||||
@ -1023,7 +1023,7 @@ const transformMap: TransformMap = {
|
|||||||
const angleToMatchLengthXCall = createCallExpression(
|
const angleToMatchLengthXCall = createCallExpression(
|
||||||
'angleToMatchLengthY',
|
'angleToMatchLengthY',
|
||||||
[
|
[
|
||||||
createIdentifier(referenceSegName),
|
createLiteral(referenceSegName),
|
||||||
varValB,
|
varValB,
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
]
|
]
|
||||||
@ -1174,7 +1174,7 @@ export function getRemoveConstraintsTransform(
|
|||||||
// fnName: name,
|
// fnName: name,
|
||||||
// angleVal: args[0],
|
// angleVal: args[0],
|
||||||
// offsetVal: args[1],
|
// offsetVal: args[1],
|
||||||
// intersectTag: createIdentifier(referenceSegName),
|
// intersectTag: createLiteral(referenceSegName),
|
||||||
// tag,
|
// tag,
|
||||||
// })
|
// })
|
||||||
// }
|
// }
|
||||||
@ -1496,7 +1496,7 @@ export function transformSecondarySketchLinesTagFirst({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
| Error {
|
| Error {
|
||||||
// let node = ast
|
// let node = JSON.parse(JSON.stringify(ast))
|
||||||
const primarySelection = selectionRanges.codeBasedSelections[0].range
|
const primarySelection = selectionRanges.codeBasedSelections[0].range
|
||||||
|
|
||||||
const _tag = giveSketchFnCallTag(ast, primarySelection, forceSegName)
|
const _tag = giveSketchFnCallTag(ast, primarySelection, forceSegName)
|
||||||
@ -1565,7 +1565,7 @@ export function transformAstSketchLines({
|
|||||||
}
|
}
|
||||||
| Error {
|
| Error {
|
||||||
// deep clone since we are mutating in a loop, of which any could fail
|
// 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?
|
let _valueUsedInTransform // TODO should this be an array?
|
||||||
const pathToNodeMap: PathToNodeMap = {}
|
const pathToNodeMap: PathToNodeMap = {}
|
||||||
|
|
||||||
@ -1593,8 +1593,8 @@ export function transformAstSketchLines({
|
|||||||
const _referencedSegmentName =
|
const _referencedSegmentName =
|
||||||
referenceSegName ||
|
referenceSegName ||
|
||||||
(_referencedSegmentNameVal &&
|
(_referencedSegmentNameVal &&
|
||||||
_referencedSegmentNameVal.type === 'Identifier' &&
|
_referencedSegmentNameVal.type === 'Literal' &&
|
||||||
String(_referencedSegmentNameVal.name)) ||
|
String(_referencedSegmentNameVal.value)) ||
|
||||||
''
|
''
|
||||||
const { val } = firstArg
|
const { val } = firstArg
|
||||||
const [varValA, varValB] = Array.isArray(val) ? val : [val, val]
|
const [varValA, varValB] = Array.isArray(val) ? val : [val, val]
|
||||||
@ -1714,21 +1714,21 @@ export function transformAstSketchLines({
|
|||||||
|
|
||||||
function createSegLen(referenceSegName: string): Value {
|
function createSegLen(referenceSegName: string): Value {
|
||||||
return createCallExpression('segLen', [
|
return createCallExpression('segLen', [
|
||||||
createIdentifier(referenceSegName),
|
createLiteral(referenceSegName),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSegAngle(referenceSegName: string): Value {
|
function createSegAngle(referenceSegName: string): Value {
|
||||||
return createCallExpression('segAng', [
|
return createCallExpression('segAng', [
|
||||||
createIdentifier(referenceSegName),
|
createLiteral(referenceSegName),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSegEnd(referenceSegName: string, isX: boolean): CallExpression {
|
function createSegEnd(referenceSegName: string, isX: boolean): CallExpression {
|
||||||
return createCallExpression(isX ? 'segEndX' : 'segEndY', [
|
return createCallExpression(isX ? 'segEndX' : 'segEndY', [
|
||||||
createIdentifier(referenceSegName),
|
createLiteral(referenceSegName),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ export function updatePathToNodeFromMap(
|
|||||||
oldPath: PathToNode,
|
oldPath: PathToNode,
|
||||||
pathToNodeMap: { [key: number]: PathToNode }
|
pathToNodeMap: { [key: number]: PathToNode }
|
||||||
): PathToNode {
|
): PathToNode {
|
||||||
const updatedPathToNode = oldPath
|
const updatedPathToNode = JSON.parse(JSON.stringify(oldPath))
|
||||||
let max = 0
|
let max = 0
|
||||||
Object.values(pathToNodeMap).forEach((path) => {
|
Object.values(pathToNodeMap).forEach((path) => {
|
||||||
const index = Number(path[1][0])
|
const index = Number(path[1][0])
|
||||||
|
@ -2,7 +2,6 @@ import init, {
|
|||||||
parse_wasm,
|
parse_wasm,
|
||||||
recast_wasm,
|
recast_wasm,
|
||||||
execute_wasm,
|
execute_wasm,
|
||||||
kcl_lint,
|
|
||||||
lexer_wasm,
|
lexer_wasm,
|
||||||
modify_ast_for_sketch_wasm,
|
modify_ast_for_sketch_wasm,
|
||||||
is_points_ccw,
|
is_points_ccw,
|
||||||
@ -21,7 +20,6 @@ import { KCLError } from './errors'
|
|||||||
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
|
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
|
||||||
import { EngineCommandManager } from './std/engineConnection'
|
import { EngineCommandManager } from './std/engineConnection'
|
||||||
import { ProgramReturn } from '../wasm-lib/kcl/bindings/ProgramReturn'
|
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 { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
|
||||||
import type { Program } from '../wasm-lib/kcl/bindings/Program'
|
import type { Program } from '../wasm-lib/kcl/bindings/Program'
|
||||||
import type { Token } from '../wasm-lib/kcl/bindings/Token'
|
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 => {
|
export const recast = (ast: Program): string | Error => {
|
||||||
return recast_wasm(JSON.stringify(ast))
|
return recast_wasm(JSON.stringify(ast))
|
||||||
}
|
}
|
||||||
@ -334,7 +321,6 @@ export async function coreDump(
|
|||||||
openGithubIssue: boolean = false
|
openGithubIssue: boolean = false
|
||||||
): Promise<CoreDumpInfo> {
|
): Promise<CoreDumpInfo> {
|
||||||
try {
|
try {
|
||||||
console.warn('CoreDump: Initializing core dump')
|
|
||||||
const dump: CoreDumpInfo = await coredump(coreDumpManager)
|
const dump: CoreDumpInfo = await coredump(coreDumpManager)
|
||||||
/* NOTE: this console output of the coredump should include the field
|
/* NOTE: this console output of the coredump should include the field
|
||||||
`github_issue_url` which is not in the uploaded coredump file.
|
`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 React from 'react'
|
||||||
import { VITE_KC_API_BASE_URL } from 'env'
|
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
|
* CoreDumpManager module
|
||||||
* - for getting all the values from the JS world to pass to the Rust world for a core dump.
|
* - 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
|
// 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
|
// 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
|
// them to so the toast handler in ModelingMachineProvider can show the user an error message toast
|
||||||
// TODO: Throw more
|
|
||||||
export class CoreDumpManager {
|
export class CoreDumpManager {
|
||||||
engineCommandManager: EngineCommandManager
|
engineCommandManager: EngineCommandManager
|
||||||
htmlRef: React.RefObject<HTMLDivElement> | null
|
htmlRef: React.RefObject<HTMLDivElement> | null
|
||||||
|
@ -9,12 +9,12 @@ const wallMountL = 6 // the length of the bracket
|
|||||||
const sigmaAllow = 35000 // psi
|
const sigmaAllow = 35000 // psi
|
||||||
const width = 6 // inch
|
const width = 6 // inch
|
||||||
const p = 300 // Force on shelf - lbs
|
const p = 300 // Force on shelf - lbs
|
||||||
const shelfLength = 12 // inches
|
const L = 12 // inches
|
||||||
const moment = shelfLength * p / 2 // Moment experienced at fixed end of bracket
|
const M = L * p / 2 // Moment experienced at fixed end of bracket
|
||||||
const factorOfSafety = 2 // Factor of safety of 2 to be conservative
|
const FOS = 2 // Factor of safety of 2 to be conservative
|
||||||
|
|
||||||
// Calculate the thickness off the bending stress and factor of safety
|
// 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
|
// 0.25 inch fillet radius
|
||||||
const filletR = 0.25
|
const filletR = 0.25
|
||||||
@ -22,20 +22,20 @@ const filletR = 0.25
|
|||||||
// Sketch the bracket and extrude with fillets
|
// Sketch the bracket and extrude with fillets
|
||||||
const bracket = startSketchOn('XY')
|
const bracket = startSketchOn('XY')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([0, wallMountL], %, $outerEdge)
|
|> line([0, wallMountL], %, 'outerEdge')
|
||||||
|> line([-shelfMountL, 0], %)
|
|> line([-shelfMountL, 0], %)
|
||||||
|> line([0, -thickness], %)
|
|> line([0, -thickness], %)
|
||||||
|> line([shelfMountL - thickness, 0], %, $innerEdge)
|
|> line([shelfMountL - thickness, 0], %, 'innerEdge')
|
||||||
|> line([0, -wallMountL + thickness], %)
|
|> line([0, -wallMountL + thickness], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|> extrude(width, %)
|
|> extrude(width, %)
|
||||||
|> fillet({
|
|> fillet({
|
||||||
radius: filletR,
|
radius: filletR,
|
||||||
tags: [getPreviousAdjacentEdge(innerEdge, %)]
|
tags: [getPreviousAdjacentEdge('innerEdge', %)]
|
||||||
}, %)
|
}, %)
|
||||||
|> fillet({
|
|> fillet({
|
||||||
radius: filletR + thickness,
|
radius: filletR + thickness,
|
||||||
tags: [getPreviousAdjacentEdge(outerEdge, %)]
|
tags: [getPreviousAdjacentEdge('outerEdge', %)]
|
||||||
}, %)`
|
}, %)`
|
||||||
|
|
||||||
function findLineInExampleCode({
|
function findLineInExampleCode({
|
||||||
|
@ -2,10 +2,8 @@ import {
|
|||||||
createArrayExpression,
|
createArrayExpression,
|
||||||
createBinaryExpression,
|
createBinaryExpression,
|
||||||
createCallExpressionStdLib,
|
createCallExpressionStdLib,
|
||||||
createIdentifier,
|
|
||||||
createLiteral,
|
createLiteral,
|
||||||
createPipeSubstitution,
|
createPipeSubstitution,
|
||||||
createTagDeclarator,
|
|
||||||
createUnaryExpression,
|
createUnaryExpression,
|
||||||
} from 'lang/modifyAst'
|
} from 'lang/modifyAst'
|
||||||
import { roundOff } from './utils'
|
import { roundOff } from './utils'
|
||||||
@ -37,13 +35,13 @@ export const getRectangleCallExpressions = (
|
|||||||
createLiteral(0), // This will be the width of the rectangle
|
createLiteral(0), // This will be the width of the rectangle
|
||||||
]),
|
]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
createTagDeclarator(tags[0]),
|
createLiteral(tags[0]),
|
||||||
]),
|
]),
|
||||||
createCallExpressionStdLib('angledLine', [
|
createCallExpressionStdLib('angledLine', [
|
||||||
createArrayExpression([
|
createArrayExpression([
|
||||||
createBinaryExpression([
|
createBinaryExpression([
|
||||||
createCallExpressionStdLib('segAng', [
|
createCallExpressionStdLib('segAng', [
|
||||||
createIdentifier(tags[0]),
|
createLiteral(tags[0]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
]),
|
]),
|
||||||
'+',
|
'+',
|
||||||
@ -52,24 +50,24 @@ export const getRectangleCallExpressions = (
|
|||||||
createLiteral(0), // This will be the height of the rectangle
|
createLiteral(0), // This will be the height of the rectangle
|
||||||
]),
|
]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
createTagDeclarator(tags[1]),
|
createLiteral(tags[1]),
|
||||||
]),
|
]),
|
||||||
createCallExpressionStdLib('angledLine', [
|
createCallExpressionStdLib('angledLine', [
|
||||||
createArrayExpression([
|
createArrayExpression([
|
||||||
createCallExpressionStdLib('segAng', [
|
createCallExpressionStdLib('segAng', [
|
||||||
createIdentifier(tags[0]),
|
createLiteral(tags[0]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
]), // same angle as the first line
|
]), // same angle as the first line
|
||||||
createUnaryExpression(
|
createUnaryExpression(
|
||||||
createCallExpressionStdLib('segLen', [
|
createCallExpressionStdLib('segLen', [
|
||||||
createIdentifier(tags[0]),
|
createLiteral(tags[0]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
]),
|
]),
|
||||||
'-'
|
'-'
|
||||||
), // negative height
|
), // negative height
|
||||||
]),
|
]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
createTagDeclarator(tags[2]),
|
createLiteral(tags[2]),
|
||||||
]),
|
]),
|
||||||
createCallExpressionStdLib('lineTo', [
|
createCallExpressionStdLib('lineTo', [
|
||||||
createArrayExpression([
|
createArrayExpression([
|
||||||
@ -103,7 +101,7 @@ export function updateRectangleSketch(
|
|||||||
.arguments[0] as ArrayExpression) = createArrayExpression([
|
.arguments[0] as ArrayExpression) = createArrayExpression([
|
||||||
createBinaryExpression([
|
createBinaryExpression([
|
||||||
createCallExpressionStdLib('segAng', [
|
createCallExpressionStdLib('segAng', [
|
||||||
createIdentifier(tag),
|
createLiteral(tag),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
]),
|
]),
|
||||||
Math.sign(y) === Math.sign(x) ? '+' : '-',
|
Math.sign(y) === Math.sign(x) ? '+' : '-',
|
||||||
|
@ -29,10 +29,7 @@ export function cleanErrs<T>(
|
|||||||
return [argsWOutErr.length !== value.length, argsWOutErr, argsWErr]
|
return [argsWOutErr.length !== value.length, argsWOutErr, argsWErr]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Used to report errors to user at a certain point in execution
|
||||||
* Used to report errors to user at a certain point in execution
|
|
||||||
* @returns boolean
|
|
||||||
*/
|
|
||||||
export function trap<T>(
|
export function trap<T>(
|
||||||
value: ExcludeErr<T> | Error,
|
value: ExcludeErr<T> | Error,
|
||||||
opts?: {
|
opts?: {
|
||||||
@ -46,8 +43,6 @@ export function trap<T>(
|
|||||||
|
|
||||||
console.error(value)
|
console.error(value)
|
||||||
opts?.suppress ||
|
opts?.suppress ||
|
||||||
toast.error((opts?.altErr ?? value ?? new Error('Unknown')).toString(), {
|
toast.error((opts?.altErr ?? value ?? new Error('Unknown')).toString())
|
||||||
id: 'error',
|
|
||||||
})
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,9 @@ export function useCalculateKclExpression({
|
|||||||
ast,
|
ast,
|
||||||
engineCommandManager,
|
engineCommandManager,
|
||||||
useFakeExecutor: true,
|
useFakeExecutor: true,
|
||||||
programMemoryOverride: kclManager.programMemory,
|
programMemoryOverride: JSON.parse(
|
||||||
|
JSON.stringify(kclManager.programMemory)
|
||||||
|
),
|
||||||
})
|
})
|
||||||
const resultDeclaration = ast.body.find(
|
const resultDeclaration = ast.body.find(
|
||||||
(a) =>
|
(a) =>
|
||||||
|
@ -26,11 +26,7 @@ import {
|
|||||||
applyConstraintEqualLength,
|
applyConstraintEqualLength,
|
||||||
setEqualLengthInfo,
|
setEqualLengthInfo,
|
||||||
} from 'components/Toolbar/EqualLength'
|
} from 'components/Toolbar/EqualLength'
|
||||||
import {
|
import { addStartProfileAt, extrudeSketch } from 'lang/modifyAst'
|
||||||
addStartProfileAt,
|
|
||||||
deleteFromSelection,
|
|
||||||
extrudeSketch,
|
|
||||||
} from 'lang/modifyAst'
|
|
||||||
import { getNodeFromPath } from '../lang/queryAst'
|
import { getNodeFromPath } from '../lang/queryAst'
|
||||||
import {
|
import {
|
||||||
applyConstraintEqualAngle,
|
applyConstraintEqualAngle,
|
||||||
@ -48,14 +44,12 @@ import {
|
|||||||
import { Models } from '@kittycad/lib/dist/types/src'
|
import { Models } from '@kittycad/lib/dist/types/src'
|
||||||
import { ModelingCommandSchema } from 'lib/commandBarConfigs/modelingCommandConfig'
|
import { ModelingCommandSchema } from 'lib/commandBarConfigs/modelingCommandConfig'
|
||||||
import { err, trap } from 'lib/trap'
|
import { err, trap } from 'lib/trap'
|
||||||
import { DefaultPlaneStr, getFaceDetails } from 'clientSideScene/sceneEntities'
|
import { DefaultPlaneStr } from 'clientSideScene/sceneEntities'
|
||||||
import { Vector3 } from 'three'
|
import { Vector3 } from 'three'
|
||||||
import { quaternionFromUpNForward } from 'clientSideScene/helpers'
|
import { quaternionFromUpNForward } from 'clientSideScene/helpers'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { uuidv4 } from 'lib/utils'
|
||||||
import { Coords2d } from 'lang/std/sketch'
|
import { Coords2d } from 'lang/std/sketch'
|
||||||
import { deleteSegment } from 'clientSideScene/ClientSideSceneComp'
|
import { deleteSegment } from 'clientSideScene/ClientSideSceneComp'
|
||||||
import { executeAst } from 'useStore'
|
|
||||||
import toast from 'react-hot-toast'
|
|
||||||
|
|
||||||
export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY'
|
export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY'
|
||||||
|
|
||||||
@ -163,9 +157,6 @@ export type ModelingMachineEvent =
|
|||||||
type: 'Set selection'
|
type: 'Set selection'
|
||||||
data: SetSelections
|
data: SetSelections
|
||||||
}
|
}
|
||||||
| {
|
|
||||||
type: 'Delete selection'
|
|
||||||
}
|
|
||||||
| { type: 'Sketch no face' }
|
| { type: 'Sketch no face' }
|
||||||
| { type: 'Toggle gui mode' }
|
| { type: 'Toggle gui mode' }
|
||||||
| { type: 'Cancel' }
|
| { type: 'Cancel' }
|
||||||
@ -282,13 +273,6 @@ export const modelingMachine = createMachine(
|
|||||||
cond: 'Has exportable geometry',
|
cond: 'Has exportable geometry',
|
||||||
actions: 'Engine export',
|
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',
|
entry: 'reset client scene mouse handlers',
|
||||||
@ -979,42 +963,6 @@ export const modelingMachine = createMachine(
|
|||||||
editorManager.selectRange(updatedAst?.selections)
|
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 }) => {
|
'conditionally equip line tool': (_, { type }) => {
|
||||||
if (type === 'done.invoke.animate-to-face') {
|
if (type === 'done.invoke.animate-to-face') {
|
||||||
sceneInfra.modelingSend('Equip Line tool')
|
sceneInfra.modelingSend('Equip Line tool')
|
||||||
|
@ -19,12 +19,8 @@ export default function UserMenu() {
|
|||||||
'[data-testid="user-sidebar-toggle"] img'
|
'[data-testid="user-sidebar-toggle"] img'
|
||||||
)
|
)
|
||||||
|
|
||||||
const onError = () => setAvatarErrored(true)
|
|
||||||
if (element?.tagName === 'IMG') {
|
if (element?.tagName === 'IMG') {
|
||||||
element?.addEventListener('error', onError)
|
element.addEventListener('error', () => setAvatarErrored(true))
|
||||||
}
|
|
||||||
return () => {
|
|
||||||
element?.removeEventListener('error', onError)
|
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
@ -5,13 +5,11 @@ import {
|
|||||||
_executor,
|
_executor,
|
||||||
ProgramMemory,
|
ProgramMemory,
|
||||||
programMemoryInit,
|
programMemoryInit,
|
||||||
kclLint,
|
|
||||||
} from './lang/wasm'
|
} from './lang/wasm'
|
||||||
import { enginelessExecutor } from './lib/testHelpers'
|
import { enginelessExecutor } from './lib/testHelpers'
|
||||||
import { EngineCommandManager } from './lang/std/engineConnection'
|
import { EngineCommandManager } from './lang/std/engineConnection'
|
||||||
import { KCLError } from './lang/errors'
|
import { KCLError } from './lang/errors'
|
||||||
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
|
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
|
||||||
import { Diagnostic } from '@codemirror/lint'
|
|
||||||
|
|
||||||
export type ToolTip =
|
export type ToolTip =
|
||||||
| 'lineTo'
|
| '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",
|
"syn 2.0.68",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "auto_impl"
|
name = "auto_impl"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@ -533,7 +539,6 @@ dependencies = [
|
|||||||
"ciborium",
|
"ciborium",
|
||||||
"clap",
|
"clap",
|
||||||
"criterion-plot",
|
"criterion-plot",
|
||||||
"futures",
|
|
||||||
"is-terminal",
|
"is-terminal",
|
||||||
"itertools 0.10.5",
|
"itertools 0.10.5",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
@ -546,7 +551,6 @@ dependencies = [
|
|||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tinytemplate",
|
"tinytemplate",
|
||||||
"tokio",
|
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -658,20 +662,6 @@ dependencies = [
|
|||||||
"parking_lot_core 0.9.9",
|
"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]]
|
[[package]]
|
||||||
name = "data-encoding"
|
name = "data-encoding"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
@ -712,7 +702,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive-docs"
|
name = "derive-docs"
|
||||||
version = "0.1.19"
|
version = "0.1.18"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Inflector",
|
"Inflector",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -1385,7 +1375,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.1.68"
|
version = "0.1.66"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"approx",
|
"approx",
|
||||||
@ -1397,7 +1387,7 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"convert_case",
|
"convert_case",
|
||||||
"criterion",
|
"criterion",
|
||||||
"dashmap 6.0.1",
|
"dashmap",
|
||||||
"databake",
|
"databake",
|
||||||
"derive-docs",
|
"derive-docs",
|
||||||
"expectorate",
|
"expectorate",
|
||||||
@ -1996,15 +1986,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyo3"
|
name = "pyo3"
|
||||||
version = "0.22.0"
|
version = "0.21.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1962a33ed2a201c637fc14a4e0fd4e06e6edfdeee6a5fede0dab55507ad74cf7"
|
checksum = "a5e00b96a521718e08e03b1a622f01c8a8deb50719335de3f60b3b3950f069d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"indoc",
|
"indoc",
|
||||||
"libc",
|
"libc",
|
||||||
"memoffset",
|
"memoffset",
|
||||||
"once_cell",
|
"parking_lot 0.12.1",
|
||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
"pyo3-build-config",
|
"pyo3-build-config",
|
||||||
"pyo3-ffi",
|
"pyo3-ffi",
|
||||||
@ -2014,9 +2004,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyo3-build-config"
|
name = "pyo3-build-config"
|
||||||
version = "0.22.0"
|
version = "0.21.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab7164b2202753bd33afc7f90a10355a719aa973d1f94502c50d06f3488bc420"
|
checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
@ -2024,9 +2014,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyo3-ffi"
|
name = "pyo3-ffi"
|
||||||
version = "0.22.0"
|
version = "0.21.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c6424906ca49013c0829c5c1ed405e20e2da2dc78b82d198564880a704e6a7b7"
|
checksum = "01be5843dc60b916ab4dad1dca6d20b9b4e6ddc8e15f50c47fe6d85f1fb97403"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"pyo3-build-config",
|
"pyo3-build-config",
|
||||||
@ -2034,9 +2024,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyo3-macros"
|
name = "pyo3-macros"
|
||||||
version = "0.22.0"
|
version = "0.21.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "82b2f19e153122d64afd8ce7aaa72f06a00f52e34e1d1e74b6d71baea396460a"
|
checksum = "77b34069fc0682e11b31dbd10321cbf94808394c56fd996796ce45217dfac53c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"pyo3-macros-backend",
|
"pyo3-macros-backend",
|
||||||
@ -2046,11 +2036,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyo3-macros-backend"
|
name = "pyo3-macros-backend"
|
||||||
version = "0.22.0"
|
version = "0.21.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd698c04cac17cf0fe63d47790ab311b8b25542f5cb976b65c374035c50f1eef"
|
checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.5.0",
|
"heck 0.4.1",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"pyo3-build-config",
|
"pyo3-build-config",
|
||||||
"quote",
|
"quote",
|
||||||
@ -2606,9 +2596,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.118"
|
version = "1.0.117"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
|
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.2.5",
|
"indexmap 2.2.5",
|
||||||
"itoa",
|
"itoa",
|
||||||
@ -3170,7 +3160,7 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"auto_impl",
|
"auto_impl",
|
||||||
"bytes",
|
"bytes",
|
||||||
"dashmap 5.5.3",
|
"dashmap",
|
||||||
"futures",
|
"futures",
|
||||||
"httparse",
|
"httparse",
|
||||||
"lsp-types",
|
"lsp-types",
|
||||||
@ -3277,9 +3267,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ts-rs"
|
name = "ts-rs"
|
||||||
version = "9.0.1"
|
version = "9.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b44017f9f875786e543595076374b9ef7d13465a518dd93d6ccdbf5b432dde8c"
|
checksum = "5e2dcf58e612adda9a83800731e8e4aba04d8a302b9029617b0b6e4b021d5357"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -3291,9 +3281,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ts-rs-macros"
|
name = "ts-rs-macros"
|
||||||
version = "9.0.1"
|
version = "9.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c88cc88fd23b5a04528f3a8436024f20010a16ec18eb23c164b1242f65860130"
|
checksum = "cbdee324e50a7402416d9c25270d3df4241ed528af5d36dda18b6f219551c577"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -3419,10 +3409,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.9.1"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439"
|
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"atomic",
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"serde",
|
"serde",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
@ -15,10 +15,10 @@ clap = "4.5.7"
|
|||||||
gloo-utils = "0.2.0"
|
gloo-utils = "0.2.0"
|
||||||
kcl-lib = { path = "kcl" }
|
kcl-lib = { path = "kcl" }
|
||||||
kittycad.workspace = true
|
kittycad.workspace = true
|
||||||
serde_json = "1.0.118"
|
serde_json = "1.0.116"
|
||||||
tokio = { version = "1.38.0", features = ["sync"] }
|
tokio = { version = "1.38.0", features = ["sync"] }
|
||||||
toml = "0.8.14"
|
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 = "0.2.91"
|
||||||
wasm-bindgen-futures = "0.4.42"
|
wasm-bindgen-futures = "0.4.42"
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ pretty_assertions = "1.4.0"
|
|||||||
reqwest = { version = "0.11.26", default-features = false }
|
reqwest = { version = "0.11.26", default-features = false }
|
||||||
tokio = { version = "1.38.0", features = ["rt-multi-thread", "macros", "time"] }
|
tokio = { version = "1.38.0", features = ["rt-multi-thread", "macros", "time"] }
|
||||||
twenty-twenty = "0.8"
|
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]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
console_error_panic_hook = "0.1.7"
|
console_error_panic_hook = "0.1.7"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "derive-docs"
|
name = "derive-docs"
|
||||||
description = "A tool for generating documentation from Rust derive macros"
|
description = "A tool for generating documentation from Rust derive macros"
|
||||||
version = "0.1.19"
|
version = "0.1.18"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
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.is_empty() {
|
||||||
if ast.sig.generics.params.iter().any(|generic_type| match generic_type {
|
errors.push(Error::new_spanned(
|
||||||
syn::GenericParam::Lifetime(_) => false,
|
&ast.sig.generics,
|
||||||
syn::GenericParam::Type(_) => true,
|
"generics are not permitted for stdlib functions",
|
||||||
syn::GenericParam::Const(_) => true,
|
));
|
||||||
}) {
|
|
||||||
errors.push(Error::new_spanned(
|
|
||||||
&ast.sig.generics,
|
|
||||||
"Stdlib functions may not be generic over types or constants, only lifetimes.",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ast.sig.variadic.is_some() {
|
if ast.sig.variadic.is_some() {
|
||||||
@ -656,12 +650,7 @@ impl Parse for ItemFnForSignature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn clean_ty_string(t: &str) -> (String, proc_macro2::TokenStream) {
|
fn clean_ty_string(t: &str) -> (String, proc_macro2::TokenStream) {
|
||||||
let mut ty_string = t
|
let mut ty_string = t.replace('&', "").replace("mut", "").replace(' ', "");
|
||||||
.replace("& 'a", "")
|
|
||||||
.replace('&', "")
|
|
||||||
.replace("mut", "")
|
|
||||||
.replace("< 'a >", "")
|
|
||||||
.replace(' ', "");
|
|
||||||
if ty_string.starts_with("Args") {
|
if ty_string.starts_with("Args") {
|
||||||
ty_string = "Args".to_string();
|
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,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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 program = parser.ast().unwrap();
|
||||||
let ctx = crate::executor::ExecutorContext::new(&client, Default::default()).await.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.
|
// Zoom to fit.
|
||||||
ctx.engine
|
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]
|
#[test]
|
||||||
fn test_stdlib_line_to() {
|
fn test_stdlib_line_to() {
|
||||||
let (item, errors) = do_stdlib(
|
let (item, errors) = do_stdlib(
|
||||||
@ -114,6 +64,7 @@ fn test_stdlib_line_to() {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let _expected = quote! {};
|
||||||
|
|
||||||
assert!(errors.is_empty());
|
assert!(errors.is_empty());
|
||||||
expectorate::assert_contents("tests/lineTo.gen", &get_text_fmt(&item).unwrap());
|
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(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
@ -106,7 +106,7 @@ mod test_examples_show {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
|
@ -16,7 +16,7 @@ mod test_examples_show {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
|
@ -17,7 +17,7 @@ mod test_examples_my_func {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
@ -108,7 +108,7 @@ mod test_examples_my_func {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
|
@ -17,7 +17,7 @@ mod test_examples_line_to {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
@ -108,7 +108,7 @@ mod test_examples_line_to {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
|
@ -16,7 +16,7 @@ mod test_examples_min {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
@ -106,7 +106,7 @@ mod test_examples_min {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
|
@ -16,7 +16,7 @@ mod test_examples_show {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
|
@ -16,7 +16,7 @@ mod test_examples_import {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
|
@ -16,7 +16,7 @@ mod test_examples_import {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
|
@ -16,7 +16,7 @@ mod test_examples_import {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
|
@ -16,7 +16,7 @@ mod test_examples_show {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[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())
|
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.run(&program, None).await.unwrap();
|
ctx.run(program, None).await.unwrap();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
|