Compare commits

..

6 Commits

Author SHA1 Message Date
826e9d8f4a again 2024-06-24 22:40:16 -04:00
7097aae0c6 yes 2024-06-24 22:38:49 -04:00
f165de6b1c again 2024-06-24 22:13:04 -04:00
deeec5f2bc again 2024-06-24 22:09:01 -04:00
0a665816d9 Add backslashes 2024-06-24 21:56:16 -04:00
0c1bf86222 Change cargo name 2024-06-24 21:55:11 -04:00
148 changed files with 2190 additions and 9996 deletions

View File

@ -38,7 +38,5 @@ jobs:
- name: Benchmark kcl library
shell: bash
run: |-
cd src/wasm-lib/kcl; cargo bench --all-features -- iai
env:
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}
cd src/wasm-lib/kcl; cargo bench -- iai

View File

@ -107,7 +107,7 @@ jobs:
'.plugins.updater.endpoints[]=$url' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
echo "$(jq --arg id 'dev.zoo.modeling-app-nightly' \
'.identifier=$id' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
echo "$(jq --arg name 'Zoo Modeling App (Nightly)' \
echo "$(jq --arg name 'zoo-modeling-app-nightly' \
'.productName=$name' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
- uses: actions/upload-artifact@v3
@ -286,9 +286,9 @@ jobs:
yarn tauri build --target "${target}" --verbose --config src-tauri/tauri.app-store.conf.json
app_path="src-tauri/target/${target}/release/bundle/macos/Zoo Modeling App.app"
build_name="src-tauri/target/${target}/release/bundle/macos/Zoo Modeling App.pkg"
cp_dir="src-tauri/target/${target}/release/bundle/macos/Zoo Modeling App.app/Contents/embedded.provisionprofile"
app_path="src-tauri/target/${target}/release/bundle/macos/zoo-modeling-app.app"
build_name="src-tauri/target/${target}/release/bundle/macos/zoo-modeling-app.pkg"
cp_dir="src-tauri/target/${target}/release/bundle/macos/zoo-modeling-app.app/Contents/embedded.provisionprofile"
entitlements="src-tauri/entitlements/app-store.entitlements"
cp "${profile}" "${cp_dir}"
@ -312,7 +312,7 @@ jobs:
uses: apple-actions/upload-testflight-build@v1
if: ${{ github.event_name == 'schedule' && matrix.os == 'macos-14' }}
with:
app-path: 'src-tauri/target/universal-apple-darwin/release/bundle/macos/Zoo Modeling App.pkg'
app-path: 'src-tauri/target/universal-apple-darwin/release/bundle/macos/zoo-modeling-app.pkg'
issuer-id: ${{ secrets.APPLE_STORE_ISSUER_ID }}
api-key-id: ${{ secrets.APPLE_STORE_API_KEY_ID }}
api-private-key: ${{ secrets.APPLE_STORE_API_PRIVATE_KEY }}
@ -367,7 +367,7 @@ jobs:
export VITE_KC_API_BASE_URL
xvfb-run yarn test:e2e:tauri
env:
E2E_APPLICATION: "./src-tauri/target/${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}/app"
E2E_APPLICATION: "./src-tauri/target/${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}/zoo-modeling-app"
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
- name: Run e2e tests (windows only)
@ -376,7 +376,7 @@ jobs:
cargo install tauri-driver --force
yarn wdio run wdio.conf.ts
env:
E2E_APPLICATION: ".\\src-tauri\\target\\${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}\\app.exe"
E2E_APPLICATION: ".\\src-tauri\\target\\${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}\\zoo-modeling-app.exe"
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
VITE_KC_API_BASE_URL: ${{ env.BUILD_RELEASE == 'true' && 'https://api.zoo.dev' || 'https://api.dev.zoo.dev' }}
E2E_TAURI_ENABLED: true

View File

@ -38,8 +38,6 @@ jobs:
runs-on: ubuntu-latest-8-cores
needs: check-rust-changes
steps:
- name: Tune GitHub-hosted runner network
uses: smorimoto/tune-github-hosted-runner-network@v1
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
@ -92,17 +90,11 @@ jobs:
- name: build web
run: yarn build:local
- name: Run ubuntu/chrome snapshots
continue-on-error: true
run: |
yarn playwright test --project="Google Chrome" --update-snapshots e2e/playwright/snapshot-tests.spec.ts
run: yarn playwright test --project="Google Chrome" --update-snapshots e2e/playwright/snapshot-tests.spec.ts
env:
CI: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
- name: Clean up test-results
if: always()
continue-on-error: true
run: rm -r test-results
- name: check for changes
id: git-check
run: |
@ -129,7 +121,7 @@ jobs:
- uses: actions/upload-artifact@v4
if: steps.git-check.outputs.modified == 'true'
with:
name: playwright-report-ubuntu-${{ github.sha }}
name: playwright-report
path: playwright-report/
retention-days: 30
# if have previous run results, use them
@ -137,18 +129,16 @@ jobs:
if: always()
continue-on-error: true
with:
name: test-results-ubuntu-${{ github.sha }}
name: test-results
path: test-results/
- name: Run ubuntu/chrome flow retry failures
id: retry
if: always()
run: |
if [[ -d "test-results" ]];
then if [[ $(ls -1 "test-results" | wc -l) != "0" ]];
then echo "retried=true" >> $GITHUB_OUTPUT;
else echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
fi;
else echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
ls -1 "test-results"
if [[ $(ls -1 "test-results" | wc -l) == "0" ]];
then echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
else echo "retried=true" >> $GITHUB_OUTPUT;
fi;
yarn playwright test --project="Google Chrome" --last-failed e2e/playwright/flow-tests.spec.ts
env:
@ -163,25 +153,23 @@ jobs:
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-ubuntu-${{ github.sha }}
name: test-results
path: test-results/
retention-days: 30
overwrite: true
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report-ubuntu-${{ github.sha }}
name: playwright-report
path: playwright-report/
retention-days: 30
overwrite: true
playwright-macos:
timeout-minutes: 60
runs-on: macos-14-large
runs-on: macos-14
needs: check-rust-changes
steps:
- name: Tune GitHub-hosted runner network
uses: smorimoto/tune-github-hosted-runner-network@v1
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
@ -239,25 +227,23 @@ jobs:
if: ${{ always() }}
continue-on-error: true
with:
name: test-results-macos-${{ github.sha }}
name: test-results
path: test-results/
- name: Run macos/safari flow retry failures
id: retry
if: always()
continue-on-error: true
if: ${{ success() }}
run: |
if [[ -d "test-results" ]];
then if [[ $(ls -1 "test-results" | wc -l) != "0" ]];
then echo "retried=true" >> $GITHUB_OUTPUT;
else echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
fi;
else echo "retried=false" >> $GITHUB_OUTPUT; exit 0;
if [ -d "test-results" ];
then echo "retried=true" >> $GITHUB_OUTPUT;
else echo "retried=false" >> $GITHUB_OUTPUT;
fi;
yarn playwright test --project="webkit" --last-failed e2e/playwright/flow-tests.spec.ts
env:
CI: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
- name: Run macos/safari flow
if: steps.retry.outputs.retried == 'false'
if: ${{ steps.retry.outputs.retried != 'true' }}
# webkit doesn't work on Ubuntu because of the same reason tauri doesn't (webRTC issues)
# TODO remove this and the matrix and run all tests on ubuntu when this is fixed
run: yarn playwright test --project="webkit" e2e/playwright/flow-tests.spec.ts
@ -267,14 +253,14 @@ jobs:
- uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: test-results-macos-${{ github.sha }}
name: test-results
path: test-results/
retention-days: 30
overwrite: true
- uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: playwright-report-macos-${{ github.sha }}
name: playwright-report
path: playwright-report/
retention-days: 30
overwrite: true

View File

@ -17,8 +17,11 @@ angleToMatchLengthX(segment_name: TagIdentifier, to: number, sketch_group: Sketc
```js
const sketch001 = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([2, 5], %, $seg01)
|> angledLineToX([-angleToMatchLengthX(seg01, 7, %), 10], %)
|> line([2, 5], %, 'seg01')
|> angledLineToX([
-angleToMatchLengthX('seg01', 7, %),
10
], %)
|> close(%)
const extrusion = extrude(5, sketch001)

View File

@ -17,9 +17,9 @@ angleToMatchLengthY(segment_name: TagIdentifier, to: number, sketch_group: Sketc
```js
const sketch001 = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([1, 2], %, $seg01)
|> line([1, 2], %, 'seg01')
|> angledLine({
angle: angleToMatchLengthY(seg01, 15, %),
angle: angleToMatchLengthY('seg01', 15, %),
length: 5
}, %)
|> yLineTo(0, %)

View File

@ -17,10 +17,10 @@ angledLineOfXLength(data: AngledLineData, sketch_group: SketchGroup, tag?: TagDe
```js
const sketch001 = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> angledLineOfXLength({ angle: 45, length: 10 }, %, $edge1)
|> angledLineOfXLength({ angle: -15, length: 20 }, %, $edge2)
|> angledLineOfXLength({ angle: 45, length: 10 }, %, "edge1")
|> angledLineOfXLength({ angle: -15, length: 20 }, %, "edge2")
|> line([0, -5], %)
|> close(%, $edge3)
|> close(%, "edge3")
const extrusion = extrude(10, sketch001)
```

View File

@ -18,7 +18,7 @@ angledLineThatIntersects(data: AngledLineThatIntersectsData, sketch_group: Sketc
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> lineTo([5, 10], %)
|> lineTo([-10, 10], %, $lineToIntersect)
|> lineTo([-10, 10], %, "lineToIntersect")
|> lineTo([0, 20], %)
|> angledLineThatIntersects({
angle: 80,

View File

@ -22,19 +22,19 @@ const chamferLength = 2
const mountingPlateSketch = startSketchOn("XY")
|> startProfileAt([-width / 2, -length / 2], %)
|> lineTo([width / 2, -length / 2], %, $edge1)
|> lineTo([width / 2, length / 2], %, $edge2)
|> lineTo([-width / 2, length / 2], %, $edge3)
|> close(%, $edge4)
|> lineTo([width / 2, -length / 2], %, 'edge1')
|> lineTo([width / 2, length / 2], %, 'edge2')
|> lineTo([-width / 2, length / 2], %, 'edge3')
|> close(%, 'edge4')
const mountingPlate = extrude(thickness, mountingPlateSketch)
|> chamfer({
length: chamferLength,
tags: [
getNextAdjacentEdge(edge1, %),
getNextAdjacentEdge(edge2, %),
getNextAdjacentEdge(edge3, %),
getNextAdjacentEdge(edge4, %)
getNextAdjacentEdge('edge1', %),
getNextAdjacentEdge('edge2', %),
getNextAdjacentEdge('edge3', %),
getNextAdjacentEdge('edge4', %)
]
}, %)
```

View File

@ -9,7 +9,7 @@ Sketch a circle.
```js
circle(center: [number], radius: number, sketch_surface_or_group: SketchSurfaceOrGroup, tag?: TagDeclarator) -> SketchGroup
circle(center: [number], radius: number, tag?: TagDeclarator, sketch_surface_or_group: SketchSurfaceOrGroup) -> SketchGroup
```
### Examples
@ -41,6 +41,14 @@ const example = extrude(5, exampleSketch)
* `center`: `[number]` (REQUIRED)
* `radius`: `number` (REQUIRED)
* `tag`: `TagDeclarator` (OPTIONAL)
```js
{
end: number,
start: number,
value: string,
}
```
* `sketch_surface_or_group`: `SketchSurfaceOrGroup` - A sketch surface or a sketch group. (REQUIRED)
```js
{
@ -502,14 +510,6 @@ const example = extrude(5, exampleSketch)
}],
}
```
* `tag`: `TagDeclarator` (OPTIONAL)
```js
{
end: number,
start: number,
value: string,
}
```
### Returns

View File

@ -22,19 +22,19 @@ const filletRadius = 2
const mountingPlateSketch = startSketchOn("XY")
|> startProfileAt([-width / 2, -length / 2], %)
|> lineTo([width / 2, -length / 2], %, $edge1)
|> lineTo([width / 2, length / 2], %, $edge2)
|> lineTo([-width / 2, length / 2], %, $edge3)
|> close(%, $edge4)
|> lineTo([width / 2, -length / 2], %, 'edge1')
|> lineTo([width / 2, length / 2], %, 'edge2')
|> lineTo([-width / 2, length / 2], %, 'edge3')
|> close(%, 'edge4')
const mountingPlate = extrude(thickness, mountingPlateSketch)
|> fillet({
radius: filletRadius,
tags: [
getNextAdjacentEdge(edge1, %),
getNextAdjacentEdge(edge2, %),
getNextAdjacentEdge(edge3, %),
getNextAdjacentEdge(edge4, %)
getNextAdjacentEdge('edge1', %),
getNextAdjacentEdge('edge2', %),
getNextAdjacentEdge('edge3', %),
getNextAdjacentEdge('edge4', %)
]
}, %)
```

View File

@ -17,7 +17,7 @@ getEdge(tag: TagIdentifier, extrude_group: ExtrudeGroup) -> Uuid
```js
const box = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([0, 10], %, $revolveAxis)
|> line([0, 10], %, 'revolveAxis')
|> line([10, 0], %)
|> line([0, -10], %)
|> close(%)
@ -30,7 +30,7 @@ const revolution = startSketchOn(box, "revolveAxis")
|> line([0, -10], %)
|> close(%)
|> revolve({
axis: getEdge(revolveAxis, box),
axis: getEdge('revolveAxis', box),
angle: 90
}, %)
```

View File

@ -21,13 +21,15 @@ const exampleSketch = startSketchOn('XZ')
|> angledLine({ angle: 60, length: 10 }, %)
|> angledLine({ angle: 120, length: 10 }, %)
|> line([-10, 0], %)
|> angledLine({ angle: 240, length: 10 }, %, $referenceEdge)
|> angledLine({ angle: 240, length: 10 }, %, 'referenceEdge')
|> close(%)
const example = extrude(5, exampleSketch)
|> fillet({
radius: 3,
tags: [getNextAdjacentEdge(referenceEdge, %)]
tags: [
getNextAdjacentEdge("referenceEdge", %)
]
}, %)
```

View File

@ -21,13 +21,13 @@ const exampleSketch = startSketchOn('XZ')
|> angledLine({ angle: 60, length: 10 }, %)
|> angledLine({ angle: 120, length: 10 }, %)
|> line([-10, 0], %)
|> angledLine({ angle: 240, length: 10 }, %, $referenceEdge)
|> angledLine({ angle: 240, length: 10 }, %, 'referenceEdge')
|> close(%)
const example = extrude(5, exampleSketch)
|> fillet({
radius: 3,
tags: [getOppositeEdge(referenceEdge, %)]
tags: [getOppositeEdge("referenceEdge", %)]
}, %)
```

View File

@ -21,14 +21,14 @@ const exampleSketch = startSketchOn('XZ')
|> angledLine({ angle: 60, length: 10 }, %)
|> angledLine({ angle: 120, length: 10 }, %)
|> line([-10, 0], %)
|> angledLine({ angle: 240, length: 10 }, %, $referenceEdge)
|> angledLine({ angle: 240, length: 10 }, %, 'referenceEdge')
|> close(%)
const example = extrude(5, exampleSketch)
|> fillet({
radius: 3,
tags: [
getPreviousAdjacentEdge(referenceEdge, %)
getPreviousAdjacentEdge("referenceEdge", %)
]
}, %)
```

View File

@ -55,7 +55,6 @@ layout: manual
* [`patternCircular3d`](kcl/patternCircular3d)
* [`patternLinear2d`](kcl/patternLinear2d)
* [`patternLinear3d`](kcl/patternLinear3d)
* [`patternTransform`](kcl/patternTransform)
* [`pi`](kcl/pi)
* [`pow`](kcl/pow)
* [`profileStart`](kcl/profileStart)

File diff suppressed because one or more lines are too long

View File

@ -17,9 +17,9 @@ profileStart(sketch_group: SketchGroup) -> [number]
```js
const sketch001 = startSketchOn('XY')
|> startProfileAt([5, 2], %)
|> angledLine({ angle: 120, length: 50 }, %, $seg01)
|> angledLine({ angle: 120, length: 50 }, %, 'seg01')
|> angledLine({
angle: segAng(seg01, %) + 120,
angle: segAng('seg01', %) + 120,
length: 50
}, %)
|> lineTo(profileStart(%), %)

View File

@ -99,7 +99,7 @@ const box = startSketchOn('XY')
|> startProfileAt([0, 0], %)
|> line([0, 20], %)
|> line([20, 0], %)
|> line([0, -20], %, $revolveAxis)
|> line([0, -20], %, 'revolveAxis')
|> close(%)
|> extrude(20, %)
@ -107,7 +107,7 @@ const sketch001 = startSketchOn(box, "END")
|> circle([10, 10], 4, %)
|> revolve({
angle: 90,
axis: getOppositeEdge(revolveAxis, box)
axis: getOppositeEdge('revolveAxis', box)
}, %)
```

View File

@ -18,11 +18,11 @@ segAng(segment_name: TagIdentifier, sketch_group: SketchGroup) -> number
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([10, 0], %)
|> line([5, 10], %, $seg01)
|> line([5, 10], %, 'seg01')
|> line([-10, 0], %)
|> angledLine([segAng(seg01, %), 10], %)
|> angledLine([segAng('seg01', %), 10], %)
|> line([-10, 0], %)
|> angledLine([segAng(seg01, %), -15], %)
|> angledLine([segAng('seg01', %), -15], %)
|> close(%)
const example = extrude(4, exampleSketch)

View File

@ -17,9 +17,9 @@ segEndX(segment_name: TagIdentifier, sketch_group: SketchGroup) -> number
```js
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([20, 0], %, $thing)
|> line([20, 0], %, "thing")
|> line([0, 5], %)
|> line([segEndX(thing, %), 0], %)
|> line([segEndX("thing", %), 0], %)
|> line([-20, 10], %)
|> close(%)

View File

@ -18,9 +18,9 @@ segEndY(segment_name: TagIdentifier, sketch_group: SketchGroup) -> number
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([20, 0], %)
|> line([0, 3], %, $thing)
|> line([0, 3], %, "thing")
|> line([-10, 0], %)
|> line([0, segEndY(thing, %)], %)
|> line([0, segEndY("thing", %)], %)
|> line([-10, 0], %)
|> close(%)

View File

@ -17,9 +17,12 @@ segLen(segment_name: TagIdentifier, sketch_group: SketchGroup) -> number
```js
const exampleSketch = startSketchOn("XZ")
|> startProfileAt([0, 0], %)
|> angledLine({ angle: 60, length: 10 }, %, $thing)
|> angledLine({ angle: 60, length: 10 }, %, "thing")
|> tangentialArc({ offset: -120, radius: 5 }, %)
|> angledLine({ angle: -60, length: segLen(thing, %) }, %)
|> angledLine({
angle: -60,
length: segLen("thing", %)
}, %)
|> close(%)
const example = extrude(5, exampleSketch)

View File

@ -49,7 +49,7 @@ const example003 = extrude(5, exampleSketch003)
const exampleSketch = startSketchOn("XY")
|> startProfileAt([0, 0], %)
|> line([10, 0], %)
|> line([0, 10], %, $sketchingFace)
|> line([0, 10], %, 'sketchingFace')
|> line([-10, 0], %)
|> close(%)
@ -60,7 +60,7 @@ const exampleSketch002 = startSketchOn(example, 'sketchingFace')
|> line([8, 0], %)
|> line([0, 8], %)
|> line([-8, 0], %)
|> close(%, $sketchingFace002)
|> close(%, 'sketchingFace002')
const example002 = extrude(10, exampleSketch002)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -45,8 +45,8 @@ async function clearCommandLogs(page: Page) {
await page.getByTestId('clear-commands').click()
}
async function expectCmdLog(page: Page, locatorStr: string, timeout = 5000) {
await expect(page.locator(locatorStr).last()).toBeVisible({ timeout })
async function expectCmdLog(page: Page, locatorStr: string) {
await expect(page.locator(locatorStr).last()).toBeVisible()
}
async function waitForDefaultPlanesToBeVisible(page: Page) {
@ -228,8 +228,7 @@ export async function getUtils(page: Page) {
await fillInput('z', xyz[2])
},
clearCommandLogs: () => clearCommandLogs(page),
expectCmdLog: (locatorStr: string, timeout = 5000) =>
expectCmdLog(page, locatorStr, timeout),
expectCmdLog: (locatorStr: string) => expectCmdLog(page, locatorStr),
openKclCodePanel: () => openKclCodePanel(page),
closeKclCodePanel: () => closeKclCodePanel(page),
openDebugPanel: () => openDebugPanel(page),
@ -301,19 +300,11 @@ export async function getUtils(page: Page) {
(screenshot.width * coords.y * pixMultiplier +
coords.x * pixMultiplier) *
4 // rbga is 4 channels
const maxDiff = Math.max(
return Math.max(
Math.abs(screenshot.data[index] - expected[0]),
Math.abs(screenshot.data[index + 1] - expected[1]),
Math.abs(screenshot.data[index + 2] - expected[2])
)
if (maxDiff > 4) {
console.log(
`Expected: ${expected} Actual: [${screenshot.data[index]}, ${
screenshot.data[index + 1]
}, ${screenshot.data[index + 2]}]`
)
}
return maxDiff
},
doAndWaitForImageDiff: (fn: () => Promise<any>, diffCount = 200) =>
new Promise(async (resolve) => {

View File

@ -89,7 +89,7 @@
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e",
"fetch:wasm": "./get-latest-wasm-bundle.sh",
"build:wasm-dev": "(cd src/wasm-lib && wasm-pack build --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt",
"build:wasm": "(cd src/wasm-lib && wasm-pack build --release --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt",
"build:wasm": "(cd src/wasm-lib && wasm-pack build --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt",
"build:wasm-clean": "yarn wasm-prep && yarn build:wasm",
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\" || echo \"sed for both mac and linux\"",
"wasm-prep": "rm -rf src/wasm-lib/pkg && mkdir src/wasm-lib/pkg && rm -rf src/wasm-lib/kcl/bindings",

View File

@ -12,13 +12,13 @@ import { defineConfig, devices } from '@playwright/test'
export default defineConfig({
testDir: './e2e/playwright',
/* Run tests in files in parallel */
fullyParallel: true,
fullyParallel: false,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 3 : 0,
/* Different amount of parallelism on CI and local. */
workers: process.env.CI ? 4 : 4,
workers: process.env.CI ? 1 : 4,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

35
src-tauri/Cargo.lock generated
View File

@ -405,6 +405,12 @@ dependencies = [
"system-deps",
]
[[package]]
name = "atomic"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba"
[[package]]
name = "atomic-waker"
version = "1.1.2"
@ -1140,20 +1146,6 @@ dependencies = [
"parking_lot_core 0.9.9",
]
[[package]]
name = "dashmap"
version = "6.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "804c8821570c3f8b70230c2ba75ffa5c0f9a4189b9a432b6656c536712acae28"
dependencies = [
"cfg-if",
"crossbeam-utils",
"hashbrown 0.14.3",
"lock_api",
"once_cell",
"parking_lot_core 0.9.9",
]
[[package]]
name = "data-encoding"
version = "2.5.0"
@ -2576,7 +2568,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.1.67"
version = "0.1.65"
dependencies = [
"anyhow",
"approx",
@ -2586,7 +2578,7 @@ dependencies = [
"bson",
"chrono",
"clap",
"dashmap 6.0.1",
"dashmap",
"databake",
"derive-docs",
"form_urlencoded",
@ -4546,9 +4538,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.118"
version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
dependencies = [
"indexmap 2.2.6",
"itoa 1.0.11",
@ -5874,7 +5866,7 @@ dependencies = [
"async-trait",
"auto_impl",
"bytes",
"dashmap 5.5.3",
"dashmap",
"futures",
"httparse",
"lsp-types",
@ -6224,10 +6216,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "uuid"
version = "1.9.1"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439"
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
dependencies = [
"atomic",
"getrandom 0.2.14",
"serde",
"wasm-bindgen",

View File

@ -1,5 +1,5 @@
[package]
name = "app"
name = "zoo-modeling-app"
version = "0.1.0"
description = "The Zoo Modeling App"
authors = ["Zoo Engineers <eng@zoo.dev>"]

View File

@ -73,6 +73,6 @@
"open": true
}
},
"productName": "Zoo Modeling App",
"productName": "zoo-modeling-app",
"version": "0.22.6"
}

View File

@ -25,7 +25,6 @@ import { LowerRightControls } from 'components/LowerRightControls'
import ModalContainer from 'react-modal-promise'
import useHotkeyWrapper from 'lib/hotkeyWrapper'
import Gizmo from 'components/Gizmo'
import { CoreDumpManager } from 'lib/coredump'
export function App() {
useRefreshSettings(paths.FILE + 'SETTINGS')
@ -56,11 +55,7 @@ export function App() {
setHtmlRef(ref)
}, [ref])
const { auth, settings } = useSettingsAuthContext()
const token = auth?.context?.token
const coreDumpManager = new CoreDumpManager(engineCommandManager, ref, token)
const { settings } = useSettingsAuthContext()
const {
app: { onboardingStatus },
} = settings.context
@ -134,7 +129,7 @@ export function App() {
<ModelingSidebar paneOpacity={paneOpacity} />
<Stream />
{/* <CamToggle /> */}
<LowerRightControls coreDumpManager={coreDumpManager}>
<LowerRightControls>
<Gizmo />
</LowerRightControls>
</div>

View File

@ -534,7 +534,7 @@ export class SceneEntities {
segmentName: 'line' | 'tangentialArcTo' = 'line',
shouldTearDown = true
) => {
const _ast = kclManager.ast
const _ast = JSON.parse(JSON.stringify(kclManager.ast))
const _node1 = getNodeFromPath<VariableDeclaration>(
_ast,
@ -692,7 +692,7 @@ export class SceneEntities {
sketchOrigin: [number, number, number],
rectangleOrigin: [x: number, y: number]
) => {
let _ast = kclManager.ast
let _ast = JSON.parse(JSON.stringify(kclManager.ast))
const _node1 = getNodeFromPath<VariableDeclaration>(
_ast,
@ -723,9 +723,7 @@ export class SceneEntities {
...getRectangleCallExpressions(rectangleOrigin, tags),
])
let result = parse(recast(_ast))
if (trap(result)) return Promise.reject(result)
_ast = result
_ast = parse(recast(_ast))
const { programMemoryOverride, truncatedAst } = await this.setupSketch({
sketchPathToNode,
@ -739,7 +737,7 @@ export class SceneEntities {
sceneInfra.setCallbacks({
onMove: async (args) => {
// Update the width and height of the draft rectangle
const pathToNodeTwo = sketchPathToNode
const pathToNodeTwo = JSON.parse(JSON.stringify(sketchPathToNode))
pathToNodeTwo[1][0] = 0
const _node = getNodeFromPath<VariableDeclaration>(
@ -801,9 +799,7 @@ export class SceneEntities {
if (sketchInit.type === 'PipeExpression') {
updateRectangleSketch(sketchInit, x, y, tags[0])
let result = parse(recast(_ast))
if (trap(result)) return Promise.reject(result)
_ast = result
_ast = parse(recast(_ast))
// Update the primary AST and unequip the rectangle tool
await kclManager.executeAstMock(_ast)
@ -1007,8 +1003,10 @@ export class SceneEntities {
PROFILE_START,
])
if (!group) return
const pathToNode: PathToNode = group.userData.pathToNode
const varDecIndex: number = pathToNode[1][0] as number
const pathToNode: PathToNode = JSON.parse(
JSON.stringify(group.userData.pathToNode)
)
const varDecIndex = JSON.parse(JSON.stringify(pathToNode[1][0]))
if (draftInfo) {
pathToNode[1][0] = 0
}
@ -1721,7 +1719,7 @@ function prepareTruncatedMemoryAndAst(
}
| Error {
const bodyIndex = Number(sketchPathToNode?.[1]?.[0]) || 0
const _ast = ast
const _ast = JSON.parse(JSON.stringify(ast))
const _node = getNodeFromPath<VariableDeclaration>(
_ast,
@ -1780,36 +1778,11 @@ function prepareTruncatedMemoryAndAst(
}
const truncatedAst: Program = {
..._ast,
body: [_ast.body[bodyIndex]],
body: [JSON.parse(JSON.stringify(_ast.body[bodyIndex]))],
}
const programMemoryOverride = programMemoryInit()
if (err(programMemoryOverride)) return programMemoryOverride
// Grab all the TagDeclarators and TagIdentifiers from memory.
let start = _node.node.start
for (const key in programMemory.root) {
const value = programMemory.root[key]
if (!('__meta' in value)) {
continue
}
if (
value.__meta === undefined ||
value.__meta.length === 0 ||
value.__meta[0].sourceRange === undefined
) {
continue
}
if (value.__meta[0].sourceRange[0] >= start) {
// We only want things before our start point.
continue
}
if (value.type === 'TagIdentifier') {
programMemoryOverride.root[key] = value
}
}
for (let i = 0; i < bodyIndex; i++) {
const node = _ast.body[i]
if (node.type !== 'VariableDeclaration') {
@ -1821,7 +1794,7 @@ function prepareTruncatedMemoryAndAst(
if (!memoryItem) {
continue
}
programMemoryOverride.root[name] = memoryItem
programMemoryOverride.root[name] = JSON.parse(JSON.stringify(memoryItem))
}
return {
truncatedAst,
@ -1969,9 +1942,9 @@ export async function getSketchOrientationDetails(
* @param entityId - The ID of the entity for which orientation details are being fetched.
* @returns A promise that resolves with the orientation details of the face.
*/
export async function getFaceDetails(
async function getFaceDetails(
entityId: string
): Promise<Models['GetSketchModePlane_type']> {
): Promise<Models['FaceIsPlanar_type']> {
// TODO mode engine connection to allow batching returns and batch the following
await engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
@ -1984,7 +1957,8 @@ export async function getFaceDetails(
entity_id: entityId,
},
})
const faceInfo: Models['GetSketchModePlane_type'] = (
// TODO change typing to get_sketch_mode_plane once lib is updated
const faceInfo: Models['FaceIsPlanar_type'] = (
await engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),

View File

@ -151,7 +151,9 @@ export function useCalc({
ast,
engineCommandManager,
useFakeExecutor: true,
programMemoryOverride: kclManager.programMemory,
programMemoryOverride: JSON.parse(
JSON.stringify(kclManager.programMemory)
),
}).then(({ programMemory }) => {
const resultDeclaration = ast.body.find(
(a) =>

View File

@ -6,18 +6,8 @@ import { NetworkHealthIndicator } from 'components/NetworkHealthIndicator'
import { HelpMenu } from './HelpMenu'
import { Link, useLocation } from 'react-router-dom'
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
import { coreDump } from 'lang/wasm'
import toast from 'react-hot-toast'
import { CoreDumpManager } from 'lib/coredump'
import openWindow from 'lib/openWindow'
export function LowerRightControls({
children,
coreDumpManager,
}: {
children?: React.ReactNode
coreDumpManager?: CoreDumpManager
}) {
export function LowerRightControls(props: React.PropsWithChildren) {
const location = useLocation()
const filePath = useAbsoluteFilePath()
const linkOverrideClassName =
@ -25,42 +15,9 @@ export function LowerRightControls({
const isPlayWright = window?.localStorage.getItem('playwright') === 'true'
async function reportbug(event: { preventDefault: () => void }) {
event?.preventDefault()
if (!coreDumpManager) {
// open default reporting option
openWindow('https://github.com/KittyCAD/modeling-app/issues/new/choose')
} else {
toast
.promise(
coreDump(coreDumpManager, true),
{
loading: 'Preparing bug report...',
success: 'Bug report opened in new window',
error: 'Unable to export a core dump. Using default reporting.',
},
{
success: {
// Note: this extended duration is especially important for Playwright e2e testing
// default duration is 2000 - https://react-hot-toast.com/docs/toast#default-durations
duration: 6000,
},
}
)
.catch((err: Error) => {
if (err) {
openWindow(
'https://github.com/KittyCAD/modeling-app/issues/new/choose'
)
}
})
}
}
return (
<section className="fixed bottom-2 right-2 flex flex-col items-end gap-3 pointer-events-none">
{children}
{props.children}
<menu className="flex items-center justify-end gap-3 pointer-events-auto">
<a
href={`https://github.com/KittyCAD/modeling-app/releases/tag/v${APP_VERSION}`}
@ -71,7 +28,6 @@ export function LowerRightControls({
v{isPlayWright ? '11.22.33' : APP_VERSION}
</a>
<a
onClick={reportbug}
href="https://github.com/KittyCAD/modeling-app/issues/new/choose"
target="_blank"
rel="noopener noreferrer"

View File

@ -30,7 +30,7 @@ import { wasmUrl } from 'lang/wasm'
import { PROJECT_ENTRYPOINT } from 'lib/constants'
import { useNetworkContext } from 'hooks/useNetworkContext'
import { NetworkHealthState } from 'hooks/useNetworkStatus'
import { err } from 'lib/trap'
import { err, trap } from 'lib/trap'
function getWorkspaceFolders(): LSP.WorkspaceFolder[] {
return []

View File

@ -23,7 +23,6 @@ import {
editorManager,
sceneEntitiesManager,
} from 'lib/singletons'
import { useHotkeys } from 'react-hotkeys-hook'
import { applyConstraintHorzVertDistance } from './Toolbar/SetHorzVertDistance'
import {
angleBetweenInfo,
@ -79,7 +78,6 @@ import { getVarNameModal } from 'hooks/useToolbarGuards'
import useHotkeyWrapper from 'lib/hotkeyWrapper'
import { uuidv4 } from 'lib/utils'
import { err, trap } from 'lib/trap'
import { useCommandsContext } from 'hooks/useCommandsContext'
type MachineContext<T extends AnyStateMachine> = {
state: StateFrom<T>
@ -126,6 +124,7 @@ export const ModelingMachineProvider = ({
token
)
useHotkeyWrapper(['meta + shift + .'], () => {
console.warn('CoreDump: Initializing core dump')
toast.promise(
coreDump(coreDumpManager, true),
{
@ -142,7 +141,6 @@ export const ModelingMachineProvider = ({
}
)
})
const { commandBarState } = useCommandsContext()
// Settings machine setup
// const retrievedSettings = useRef(
@ -328,11 +326,6 @@ export const ModelingMachineProvider = ({
)
updateSceneObjectColors()
// side effect to stop code mirror from updating the same selections again
editorManager.lastSelection = selections.codeBasedSelections
.map(({ range }) => `${range[1]}->${range[1]}`)
.join('&')
return {
selectionRanges: selections,
}
@ -467,11 +460,6 @@ export const ModelingMachineProvider = ({
return canExtrudeSelection(selectionRanges)
},
'has valid selection for deletion': ({ selectionRanges }) => {
if (!commandBarState.matches('Closed')) return false
if (selectionRanges.codeBasedSelections.length <= 0) return false
return true
},
'Sketch is empty': ({ sketchDetails }) => {
const node = getNodeFromPath<VariableDeclaration>(
kclManager.ast,
@ -513,7 +501,7 @@ export const ModelingMachineProvider = ({
services: {
'AST-undo-startSketchOn': async ({ sketchDetails }) => {
if (!sketchDetails) return
const newAst: Program = kclManager.ast
const newAst: Program = JSON.parse(JSON.stringify(kclManager.ast))
const varDecIndex = sketchDetails.sketchPathToNode[1][0]
// remove body item at varDecIndex
newAst.body = newAst.body.filter((_, i) => i !== varDecIndex)
@ -935,11 +923,6 @@ export const ModelingMachineProvider = ({
}
}, [modelingSend])
// Allow using the delete key to delete solids
useHotkeys(['backspace', 'delete', 'del'], () => {
modelingSend({ type: 'Delete selection' })
})
useStateMachineCommands({
machineId: 'modeling',
state: modelingState,

View File

@ -1,25 +1,7 @@
import { coreDump } from 'lang/wasm'
import { CoreDumpManager } from 'lib/coredump'
import { CustomIcon } from './CustomIcon'
import { engineCommandManager } from 'lib/singletons'
import React from 'react'
import toast from 'react-hot-toast'
import Tooltip from './Tooltip'
import { useStore } from 'useStore'
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
export const RefreshButton = ({ children }: React.PropsWithChildren) => {
const { auth } = useSettingsAuthContext()
const token = auth?.context?.token
const { htmlRef } = useStore((s) => ({
htmlRef: s.htmlRef,
}))
const coreDumpManager = new CoreDumpManager(
engineCommandManager,
htmlRef,
token
)
export function RefreshButton() {
async function refresh() {
if (window && 'plausible' in window) {
const p = window.plausible as (
@ -35,26 +17,8 @@ export const RefreshButton = ({ children }: React.PropsWithChildren) => {
})
}
toast
.promise(
coreDump(coreDumpManager, true),
{
loading: 'Starting core dump...',
success: 'Core dump completed successfully',
error: 'Error while exporting core dump',
},
{
success: {
// Note: this extended duration is especially important for Playwright e2e testing
// default duration is 2000 - https://react-hot-toast.com/docs/toast#default-durations
duration: 6000,
},
}
)
.then(() => {
// Window may not be available in some environments
window?.location.reload()
})
// Window may not be available in some environments
window?.location.reload()
}
return (

View File

@ -83,7 +83,6 @@ export const Stream = ({ className = '' }: { className?: string }) => {
if (!videoRef.current) return
if (state.matches('Sketch')) return
if (state.matches('Sketch no face')) return
const { x, y } = getNormalisedCoordinates({
clientX: e.clientX,
clientY: e.clientY,
@ -128,7 +127,6 @@ export const Stream = ({ className = '' }: { className?: string }) => {
return (
<div
className="absolute inset-0 z-0"
id="stream"
data-testid="stream"
onMouseUp={handleMouseUp}
onMouseDown={handleMouseDown}

View File

@ -145,7 +145,7 @@ export async function applyConstraintIntersect({
const { transforms, forcedSelectionRanges } = info
const transform1 = transformSecondarySketchLinesTagFirst({
ast: kclManager.ast,
ast: JSON.parse(JSON.stringify(kclManager.ast)),
selectionRanges: forcedSelectionRanges,
transformInfos: transforms,
programMemory: kclManager.programMemory,

View File

@ -106,7 +106,7 @@ export async function applyConstraintAbsDistance({
const transformInfos = info.transforms
const transform1 = transformAstSketchLines({
ast: kclManager.ast,
ast: JSON.parse(JSON.stringify(kclManager.ast)),
selectionRanges: selectionRanges,
transformInfos,
programMemory: kclManager.programMemory,
@ -128,7 +128,7 @@ export async function applyConstraintAbsDistance({
)
const transform2 = transformAstSketchLines({
ast: kclManager.ast,
ast: JSON.parse(JSON.stringify(kclManager.ast)),
selectionRanges: selectionRanges,
transformInfos,
programMemory: kclManager.programMemory,
@ -176,7 +176,7 @@ export function applyConstraintAxisAlign({
let finalValue = createIdentifier('ZERO')
return transformAstSketchLines({
ast: kclManager.ast,
ast: JSON.parse(JSON.stringify(kclManager.ast)),
selectionRanges: selectionRanges,
transformInfos,
programMemory: kclManager.programMemory,

View File

@ -100,7 +100,7 @@ export async function applyConstraintAngleBetween({
const transformInfos = info.transforms
const transformed1 = transformSecondarySketchLinesTagFirst({
ast: kclManager.ast,
ast: JSON.parse(JSON.stringify(kclManager.ast)),
selectionRanges,
transformInfos,
programMemory: kclManager.programMemory,

View File

@ -108,7 +108,7 @@ export async function applyConstraintHorzVertDistance({
if (err(info)) return Promise.reject(info)
const transformInfos = info.transforms
const transformed = transformSecondarySketchLinesTagFirst({
ast: kclManager.ast,
ast: JSON.parse(JSON.stringify(kclManager.ast)),
selectionRanges,
transformInfos,
programMemory: kclManager.programMemory,

View File

@ -84,7 +84,7 @@ export async function applyConstraintAngleLength({
const { transforms } = angleLength
const sketched = transformAstSketchLines({
ast: kclManager.ast,
ast: JSON.parse(JSON.stringify(kclManager.ast)),
selectionRanges,
transformInfos: transforms,
programMemory: kclManager.programMemory,
@ -139,7 +139,7 @@ export async function applyConstraintAngleLength({
}
const retval = transformAstSketchLines({
ast: kclManager.ast,
ast: JSON.parse(JSON.stringify(kclManager.ast)),
selectionRanges,
transformInfos: transforms,
programMemory: kclManager.programMemory,

View File

@ -20,12 +20,6 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
const navigate = useNavigate()
const send = useSettingsAuthContext()?.auth?.send
// This image host goes down sometimes. We will instead rewrite the
// resource to be a local one.
if (user?.image === 'https://placekitten.com/200/200') {
user.image = '/cat.jpg'
}
// Fallback logic for displaying user's "name":
// 1. user.name
// 2. user.first_name + ' ' + user.last_name

View File

@ -23,7 +23,7 @@ export default class EditorManager {
}
private _lastSelectionEvent: number | null = null
lastSelection: string = ''
private _lastSelection: string = ''
private _lastEvent: { event: string; time: number } | null = null
private _modelingSend: (eventInfo: ModelingMachineEvent) => void = () => {}
@ -199,14 +199,12 @@ export default class EditorManager {
viewUpdate?.state?.selection?.ranges || []
)
if (selString === this.lastSelection) {
if (selString === this._lastSelection) {
// onUpdate is noisy and is fired a lot by extensions
// since we're only interested in selections changes we can ignore most of these.
return
}
// note this is also set from the "Set selection" action to stop code mirror from updating selections right after
// selections are made from the scene
this.lastSelection = selString
this._lastSelection = selString
if (
this._lastSelectionEvent &&

View File

@ -42,8 +42,9 @@ function registerServerCapability(
serverCapabilities: ServerCapabilities,
registration: Registration
): ServerCapabilities | Error {
const serverCapabilitiesCopy =
serverCapabilities as IFlexibleServerCapabilities
const serverCapabilitiesCopy = JSON.parse(
JSON.stringify(serverCapabilities)
) as IFlexibleServerCapabilities
const { method, registerOptions } = registration
const providerName = ServerCapabilitiesProviders[method]
@ -51,7 +52,10 @@ function registerServerCapability(
if (!registerOptions) {
serverCapabilitiesCopy[providerName] = true
} else {
serverCapabilitiesCopy[providerName] = Object.assign({}, registerOptions)
serverCapabilitiesCopy[providerName] = Object.assign(
{},
JSON.parse(JSON.stringify(registerOptions))
)
}
} else {
return new Error('Could not register server capability.')
@ -64,8 +68,9 @@ function unregisterServerCapability(
serverCapabilities: ServerCapabilities,
unregistration: Unregistration
): ServerCapabilities {
const serverCapabilitiesCopy =
serverCapabilities as IFlexibleServerCapabilities
const serverCapabilitiesCopy = JSON.parse(
JSON.stringify(serverCapabilities)
) as IFlexibleServerCapabilities
const { method } = unregistration
const providerName = ServerCapabilitiesProviders[method]

View File

@ -1,4 +1,4 @@
import { executeAst, lintAst } from 'useStore'
import { executeAst } from 'useStore'
import { Selections } from 'lib/selections'
import { KCLError, kclErrorsToDiagnostics } from './errors'
import { uuidv4 } from 'lib/utils'
@ -211,9 +211,6 @@ export class KclManager {
ast,
engineCommandManager: this.engineCommandManager,
})
editorManager.addDiagnostics(await lintAst({ ast: ast }))
sceneInfra.modelingSend({ type: 'code edit during sketch' })
defaultSelectionFilter(programMemory, this.engineCommandManager)
@ -264,10 +261,7 @@ export class KclManager {
return
}
const newAst = this.safeParse(newCode)
if (!newAst) {
this.clearAst()
return
}
if (!newAst) return
codeManager.updateCodeEditor(newCode)
// Write the file to disk.
await codeManager.writeToFile()
@ -284,9 +278,6 @@ export class KclManager {
engineCommandManager: this.engineCommandManager,
useFakeExecutor: true,
})
editorManager.addDiagnostics(await lintAst({ ast: ast }))
this._logs = logs
this._kclErrors = errors
this._programMemory = programMemory

View File

@ -502,10 +502,11 @@ describe('testing pipe operator special', () => {
},
{ type: 'PipeSubstitution', start: 82, end: 83 },
{
type: 'TagDeclarator',
type: 'Literal',
start: 85,
end: 93,
value: 'myPath',
raw: '"myPath"',
},
],
optional: false,
@ -1656,10 +1657,11 @@ describe('should recognise callExpresions in binaryExpressions', () => {
callee: { type: 'Identifier', start: 8, end: 15, name: 'segEndX' },
arguments: [
{
type: 'Identifier',
type: 'Literal',
start: 16,
end: 23,
name: 'seg02',
value: 'seg02',
raw: "'seg02'",
},
{ type: 'PipeSubstitution', start: 25, end: 26 },
],

View File

@ -128,7 +128,7 @@ const mySketch001 = startSketchOn('XY')
const sk1 = startSketchOn('XY')
|> startProfileAt([0, 0], %)
|> lineTo([-2.5, 0], %)
|> lineTo([0, 10], %, $p)
|> lineTo([0, 10], %, "p")
|> lineTo([2.5, 0], %)
// |> rx(45, %)
// |> translate([1,0,1], %)
@ -138,7 +138,7 @@ const theExtrude = extrude(2, sk1)
const sk2 = startSketchOn('XY')
|> startProfileAt([0, 0], %)
|> lineTo([-2.5, 0], %)
|> lineTo([0, 3], %, $o)
|> lineTo([0, 3], %, "p")
|> lineTo([2.5, 0], %)
// |> transform(theTransf, %)
|> extrude(2, %)
@ -163,20 +163,20 @@ const sk2 = startSketchOn('XY')
type: 'extrudePlane',
faceId: expect.any(String),
tag: {
end: 116,
end: 117,
start: 114,
type: 'TagDeclarator',
value: 'p',
},
id: expect.any(String),
sourceRange: [95, 117],
sourceRange: [95, 118],
},
{
type: 'extrudePlane',
faceId: expect.any(String),
tag: null,
id: expect.any(String),
sourceRange: [123, 142],
sourceRange: [124, 143],
},
],
sketchGroup: {
@ -201,14 +201,14 @@ const sk2 = startSketchOn('XY')
from: [-2.5, 0],
to: [0, 10],
tag: {
end: 116,
end: 117,
start: 114,
type: 'TagDeclarator',
value: 'p',
},
__geoMeta: {
id: expect.any(String),
sourceRange: [95, 117],
sourceRange: [95, 118],
},
},
{
@ -218,7 +218,7 @@ const sk2 = startSketchOn('XY')
tag: null,
__geoMeta: {
id: expect.any(String),
sourceRange: [123, 142],
sourceRange: [124, 143],
},
},
],
@ -237,26 +237,26 @@ const sk2 = startSketchOn('XY')
faceId: expect.any(String),
tag: null,
id: expect.any(String),
sourceRange: [373, 393],
sourceRange: [374, 394],
},
{
type: 'extrudePlane',
faceId: expect.any(String),
tag: {
end: 419,
start: 417,
end: 421,
start: 418,
type: 'TagDeclarator',
value: 'o',
value: 'p',
},
id: expect.any(String),
sourceRange: [399, 420],
sourceRange: [400, 422],
},
{
type: 'extrudePlane',
faceId: expect.any(String),
tag: null,
id: expect.any(String),
sourceRange: [426, 445],
sourceRange: [428, 447],
},
],
sketchGroup: {
@ -273,7 +273,7 @@ const sk2 = startSketchOn('XY')
tag: null,
__geoMeta: {
id: expect.any(String),
sourceRange: [373, 393],
sourceRange: [374, 394],
},
},
{
@ -281,14 +281,14 @@ const sk2 = startSketchOn('XY')
from: [-2.5, 0],
to: [0, 3],
tag: {
end: 419,
start: 417,
end: 421,
start: 418,
type: 'TagDeclarator',
value: 'o',
value: 'p',
},
__geoMeta: {
id: expect.any(String),
sourceRange: [399, 420],
sourceRange: [400, 422],
},
},
{
@ -298,7 +298,7 @@ const sk2 = startSketchOn('XY')
tag: null,
__geoMeta: {
id: expect.any(String),
sourceRange: [426, 445],
sourceRange: [428, 447],
},
},
],
@ -306,7 +306,7 @@ const sk2 = startSketchOn('XY')
height: 2,
startCapId: expect.any(String),
endCapId: expect.any(String),
__meta: [{ sourceRange: [342, 367] }],
__meta: [{ sourceRange: [343, 368] }],
},
])
})

View File

@ -15,7 +15,6 @@ import {
sketchOnExtrudedFace,
deleteSegmentFromPipeExpression,
removeSingleConstraintInfo,
deleteFromSelection,
} from './modifyAst'
import { enginelessExecutor } from '../lib/testHelpers'
import { findUsesOfTagInPipe, getNodePathFromSourceRange } from './queryAst'
@ -164,25 +163,25 @@ describe('Testing giveSketchFnCallTag', () => {
code,
'line([0, 0.83], %)'
)
expect(newCode).toContain('line([0, 0.83], %, $seg01)')
expect(newCode).toContain("line([0, 0.83], %, 'seg01')")
expect(tag).toBe('seg01')
expect(isTagExisting).toBe(false)
})
it('Should create a unique tag if seg01 already exists', () => {
let _code = code.replace(
'line([-2.57, -0.13], %)',
'line([-2.57, -0.13], %, $seg01)'
"line([-2.57, -0.13], %, 'seg01')"
)
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
_code,
'line([0, 0.83], %)'
)
expect(newCode).toContain('line([0, 0.83], %, $seg02)')
expect(newCode).toContain("line([0, 0.83], %, 'seg02')")
expect(tag).toBe('seg02')
expect(isTagExisting).toBe(false)
})
it('Should return existing tag if it already exists', () => {
const lineButWithTag = 'line([-2.57, -0.13], %, $butts)'
const lineButWithTag = "line([-2.57, -0.13], %, 'butts')"
let _code = code.replace('line([-2.57, -0.13], %)', lineButWithTag)
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
_code,
@ -329,11 +328,11 @@ describe('testing sketchOnExtrudedFace', () => {
const newCode = recast(modifiedAst)
expect(newCode).toContain(`const part001 = startSketchOn('-XZ')
|> startProfileAt([3.58, 2.06], %)
|> line([9.7, 9.19], %, $seg01)
|> line([9.7, 9.19], %, 'seg01')
|> line([8.62, -9.57], %)
|> close(%)
|> extrude(5 + 7, %)
const sketch001 = startSketchOn(part001, seg01)`)
const sketch001 = startSketchOn(part001, 'seg01')`)
})
test('it should be able to extrude on close segments', async () => {
const code = `const part001 = startSketchOn('-XZ')
@ -372,9 +371,9 @@ const sketch001 = startSketchOn(part001, seg01)`)
|> startProfileAt([3.58, 2.06], %)
|> line([9.7, 9.19], %)
|> line([8.62, -9.57], %)
|> close(%, $seg01)
|> close(%, 'seg01')
|> extrude(5 + 7, %)
const sketch001 = startSketchOn(part001, seg01)`)
const sketch001 = startSketchOn(part001, 'seg01')`)
})
test('it should be able to extrude on start-end caps', async () => {
const code = `const part001 = startSketchOn('-XZ')
@ -458,7 +457,7 @@ const sketch001 = startSketchOn(part001, 'END')`)
if (err(updatedAst)) throw updatedAst
const newCode = recast(updatedAst.modifiedAst)
expect(newCode).toContain(`const part001 = extrude(5 + 7, sketch001)
const sketch002 = startSketchOn(part001, seg01)`)
const sketch002 = startSketchOn(part001, 'seg01')`)
})
})
@ -500,49 +499,49 @@ describe('Testing deleteSegmentFromPipeExpression', () => {
replace2 = ''
) => `const part001 = startSketchOn('-XZ')
|> startProfileAt([54.78, -95.91], %)
|> line([306.21, 198.82], %, $b)
|> line([306.21, 198.82], %, 'b')
${!replace1 ? ` |> ${line}\n` : ''} |> angledLine([-65, ${
!replace1 ? 'segLen(a, %)' : replace1
!replace1 ? "segLen('a', %)" : replace1
}], %)
|> line([306.21, 198.87], %)
|> angledLine([65, ${!replace2 ? 'segAng(a, %)' : replace2}], %)
|> angledLine([65, ${!replace2 ? "segAng('a', %)" : replace2}], %)
|> line([-963.39, -154.67], %)
`
test.each([
['line', 'line([306.21, 198.85], %, $a)', ['365.11', '33']],
['lineTo', 'lineTo([306.21, 198.85], %, $a)', ['110.48', '119.73']],
['yLine', 'yLine(198.85, %, $a)', ['198.85', '90']],
['xLine', 'xLine(198.85, %, $a)', ['198.85', '0']],
['yLineTo', 'yLineTo(198.85, %, $a)', ['95.94', '90']],
['xLineTo', 'xLineTo(198.85, %, $a)', ['162.14', '180']],
['line', "line([306.21, 198.85], %, 'a')", ['365.11', '33']],
['lineTo', "lineTo([306.21, 198.85], %, 'a')", ['110.48', '119.73']],
['yLine', "yLine(198.85, %, 'a')", ['198.85', '90']],
['xLine', "xLine(198.85, %, 'a')", ['198.85', '0']],
['yLineTo', "yLineTo(198.85, %, 'a')", ['95.94', '90']],
['xLineTo', "xLineTo(198.85, %, 'a')", ['162.14', '180']],
[
'angledLine',
'angledLine({ angle: 45.5, length: 198.85 }, %, $a)',
"angledLine({ angle: 45.5, length: 198.85 }, %, 'a')",
['198.85', '45.5'],
],
[
'angledLineOfXLength',
'angledLineOfXLength({ angle: 45.5, length: 198.85 }, %, $a)',
"angledLineOfXLength({ angle: 45.5, length: 198.85 }, %, 'a')",
['283.7', '45.5'],
],
[
'angledLineOfYLength',
'angledLineOfYLength({ angle: 45.5, length: 198.85 }, %, $a)',
"angledLineOfYLength({ angle: 45.5, length: 198.85 }, %, 'a')",
['278.79', '45.5'],
],
[
'angledLineToX',
'angledLineToX({ angle: 45.5, to: 198.85 }, %, $a)',
"angledLineToX({ angle: 45.5, to: 198.85 }, %, 'a')",
['231.33', '134.5'],
],
[
'angledLineToY',
'angledLineToY({ angle: 45.5, to: 198.85 }, %, $a)',
"angledLineToY({ angle: 45.5, to: 198.85 }, %, 'a')",
['134.51', '45.5'],
],
[
'angledLineThatIntersects',
`angledLineThatIntersects({ angle: 45.5, intersectTag: b, offset: 198.85 }, %, $a)`,
`angledLineThatIntersects({ angle: 45.5, intersectTag: 'b', offset: 198.85 }, %, 'a')`,
['918.4', '45.5'],
],
])(`%s`, async (_, line, [replace1, replace2]) => {
@ -580,7 +579,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|> lineTo([6.14 + 0, 3.14 + 0], %)
|> xLineTo(8 + 0, %)
|> yLineTo(5 + 0, %)
|> yLine(3.14 + 0, %, $a)
|> yLine(3.14 + 0, %, 'a')
|> xLine(3.14 + 0, %)
|> angledLineOfXLength({ angle: 3 + 0, length: 3.14 + 0 }, %)
|> angledLineOfYLength({ angle: 30 + 0, length: 3 + 0 }, %)
@ -588,7 +587,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|> angledLineToY({ angle: 30 + 0, to: 10.14 + 0 }, %)
|> angledLineThatIntersects({
angle: 3.14 + 0,
intersectTag: a,
intersectTag: 'a',
offset: 0 + 0
}, %)
|> tangentialArcTo([3.14 + 0, 13.14 + 0], %)`
@ -602,7 +601,7 @@ describe('Testing removeSingleConstraintInfo', () => {
['lineTo([6.14, 3.14 + 0], %)', 'arrayIndex', 0],
['xLineTo(8, %)', '', ''],
['yLineTo(5, %)', '', ''],
['yLine(3.14, %, $a)', '', ''],
["yLine(3.14, %, 'a')", '', ''],
['xLine(3.14, %)', '', ''],
[
'angledLineOfXLength({ angle: 3, length: 3.14 + 0 }, %)',
@ -628,7 +627,7 @@ describe('Testing removeSingleConstraintInfo', () => {
`angledLineThatIntersects({
angle: 3.14 + 0,
offset: 0,
intersectTag: a
intersectTag: 'a'
}, %)`,
'objectProperty',
'offset',
@ -697,196 +696,3 @@ describe('Testing removeSingleConstraintInfo', () => {
})
})
})
describe('Testing deleteFromSelection', () => {
const cases = [
[
'basicCase',
{
codeBefore: `const myVar = 5
const sketch003 = startSketchOn('XZ')
|> startProfileAt([3.82, 13.6], %)
|> line([-2.94, 2.7], %)
|> line([7.7, 0.16], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)`,
codeAfter: `const myVar = 5\n`,
lineOfInterest: 'line([-2.94, 2.7], %)',
type: 'default',
},
],
[
'delete extrude',
{
codeBefore: `const sketch001 = startSketchOn('XZ')
|> startProfileAt([3.29, 7.86], %)
|> line([2.48, 2.44], %)
|> line([2.66, 1.17], %)
|> line([3.75, 0.46], %)
|> line([4.99, -0.46], %, $seg01)
|> line([-3.86, -2.73], %)
|> line([-17.67, 0.85], %)
|> close(%)
const extrude001 = extrude(10, sketch001)`,
codeAfter: `const sketch001 = startSketchOn('XZ')
|> startProfileAt([3.29, 7.86], %)
|> line([2.48, 2.44], %)
|> line([2.66, 1.17], %)
|> line([3.75, 0.46], %)
|> line([4.99, -0.46], %, $seg01)
|> line([-3.86, -2.73], %)
|> line([-17.67, 0.85], %)
|> close(%)\n`,
lineOfInterest: 'line([2.66, 1.17], %)',
type: 'extrude-wall',
},
],
[
'delete extrude with sketch on it',
{
codeBefore: `const myVar = 5
const sketch001 = startSketchOn('XZ')
|> startProfileAt([4.46, 5.12], %, $tag)
|> line([0.08, myVar], %)
|> line([13.03, 2.02], %, $seg01)
|> line([3.9, -7.6], %)
|> line([-11.18, -2.15], %)
|> line([5.41, -9.61], %)
|> line([-8.54, -2.51], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
const extrude001 = extrude(5, sketch001)
const sketch002 = startSketchOn(extrude001, seg01)
|> startProfileAt([-12.55, 2.89], %)
|> line([3.02, 1.9], %)
|> line([1.82, -1.49], %, $seg02)
|> angledLine([-86, segLen(seg02, %)], %)
|> line([-3.97, -0.53], %)
|> line([0.3, 0.84], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)`,
codeAfter: `const myVar = 5
const sketch001 = startSketchOn('XZ')
|> startProfileAt([4.46, 5.12], %, $tag)
|> line([0.08, myVar], %)
|> line([13.03, 2.02], %, $seg01)
|> line([3.9, -7.6], %)
|> line([-11.18, -2.15], %)
|> line([5.41, -9.61], %)
|> line([-8.54, -2.51], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
const sketch002 = startSketchOn({
plane: {
origin: { x: 1, y: 2, z: 3 },
x_axis: { x: 4, y: 5, z: 6 },
y_axis: { x: 7, y: 8, z: 9 },
z_axis: { x: 10, y: 11, z: 12 }
}
})
|> startProfileAt([-12.55, 2.89], %)
|> line([3.02, 1.9], %)
|> line([1.82, -1.49], %, $seg02)
|> angledLine([-86, segLen(seg02, %)], %)
|> line([-3.97, -0.53], %)
|> line([0.3, 0.84], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
`,
lineOfInterest: 'line([-11.18, -2.15], %)',
type: 'extrude-wall',
},
],
[
'delete extrude with sketch on it',
{
codeBefore: `const myVar = 5
const sketch001 = startSketchOn('XZ')
|> startProfileAt([4.46, 5.12], %, $tag)
|> line([0.08, myVar], %)
|> line([13.03, 2.02], %, $seg01)
|> line([3.9, -7.6], %)
|> line([-11.18, -2.15], %)
|> line([5.41, -9.61], %)
|> line([-8.54, -2.51], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
const extrude001 = extrude(5, sketch001)
const sketch002 = startSketchOn(extrude001, seg01)
|> startProfileAt([-12.55, 2.89], %)
|> line([3.02, 1.9], %)
|> line([1.82, -1.49], %, $seg02)
|> angledLine([-86, segLen(seg02, %)], %)
|> line([-3.97, -0.53], %)
|> line([0.3, 0.84], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)`,
codeAfter: `const myVar = 5
const sketch001 = startSketchOn('XZ')
|> startProfileAt([4.46, 5.12], %, $tag)
|> line([0.08, myVar], %)
|> line([13.03, 2.02], %, $seg01)
|> line([3.9, -7.6], %)
|> line([-11.18, -2.15], %)
|> line([5.41, -9.61], %)
|> line([-8.54, -2.51], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
const sketch002 = startSketchOn({
plane: {
origin: { x: 1, y: 2, z: 3 },
x_axis: { x: 4, y: 5, z: 6 },
y_axis: { x: 7, y: 8, z: 9 },
z_axis: { x: 10, y: 11, z: 12 }
}
})
|> startProfileAt([-12.55, 2.89], %)
|> line([3.02, 1.9], %)
|> line([1.82, -1.49], %, $seg02)
|> angledLine([-86, segLen(seg02, %)], %)
|> line([-3.97, -0.53], %)
|> line([0.3, 0.84], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
`,
lineOfInterest: 'startProfileAt([4.46, 5.12], %, $tag)',
type: 'end-cap',
},
],
] as const
test.each(cases)(
'%s',
async (name, { codeBefore, codeAfter, lineOfInterest, type }) => {
// const lineOfInterest = 'line([-2.94, 2.7], %)'
const ast = parse(codeBefore)
if (err(ast)) throw ast
const programMemory = await enginelessExecutor(ast)
// deleteFromSelection
const range: [number, number] = [
codeBefore.indexOf(lineOfInterest),
codeBefore.indexOf(lineOfInterest) + lineOfInterest.length,
]
const newAst = await deleteFromSelection(
ast,
{
range,
type,
},
programMemory,
async () => {
await new Promise((resolve) => setTimeout(resolve, 100))
return {
origin: { x: 1, y: 2, z: 3 },
x_axis: { x: 4, y: 5, z: 6 },
y_axis: { x: 7, y: 8, z: 9 },
z_axis: { x: 10, y: 11, z: 12 },
}
}
)
if (err(newAst)) throw newAst
const newCode = recast(newAst)
expect(newCode).toBe(codeAfter)
}
)
})

View File

@ -17,7 +17,6 @@ import {
PathToNode,
ProgramMemory,
SourceRange,
SketchGroup,
} from './wasm'
import {
isNodeSafeToReplacePath,
@ -26,7 +25,6 @@ import {
getNodeFromPath,
getNodePathFromSourceRange,
isNodeSafeToReplace,
traverse,
} from './queryAst'
import { addTagForSketchOnFace, getConstraintInfo } from './std/sketch'
import {
@ -39,8 +37,6 @@ import { DefaultPlaneStr } from 'clientSideScene/sceneEntities'
import { isOverlap, roundOff } from 'lib/utils'
import { KCL_DEFAULT_CONSTANT_PREFIXES } from 'lib/constants'
import { ConstrainInfo } from './std/stdTypes'
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
import { Models } from '@kittycad/lib'
export function startSketchOnDefault(
node: Program,
@ -383,7 +379,7 @@ export function sketchOnExtrudedFace(
const { node: extrudeVarDec } = _node3
const extrudeName = extrudeVarDec.id?.name
let _tag = null
let _tag = ''
if (cap === 'none') {
const __tag = addTagForSketchOnFace(
{
@ -395,17 +391,17 @@ export function sketchOnExtrudedFace(
)
if (err(__tag)) return __tag
const { modifiedAst, tag } = __tag
_tag = createIdentifier(tag)
_tag = tag
_node = modifiedAst
} else {
_tag = createLiteral(cap.toUpperCase())
_tag = cap.toUpperCase()
}
const newSketch = createVariableDeclaration(
newSketchName,
createCallExpressionStdLib('startSketchOn', [
createIdentifier(extrudeName ? extrudeName : oldSketchName),
_tag,
createLiteral(_tag),
]),
'const'
)
@ -487,15 +483,6 @@ export function createLiteral(value: string | number): Literal {
}
}
export function createTagDeclarator(value: string): TagDeclarator {
return {
type: 'TagDeclarator',
start: 0,
end: 0,
value,
}
}
export function createIdentifier(name: string): Identifier {
return {
type: 'Identifier',
@ -670,18 +657,17 @@ export function giveSketchFnCallTag(
// Tag is always 3rd expression now, using arg index feels brittle
// but we can come up with a better way to identify tag later.
const thirdArg = primaryCallExp.arguments?.[2]
const tagDeclarator =
thirdArg ||
(createTagDeclarator(tag || findUniqueName(ast, 'seg', 2)) as TagDeclarator)
const tagLiteral =
thirdArg || (createLiteral(tag || findUniqueName(ast, 'seg', 2)) as Literal)
const isTagExisting = !!thirdArg
if (!isTagExisting) {
primaryCallExp.arguments[2] = tagDeclarator
primaryCallExp.arguments[2] = tagLiteral
}
if ('value' in tagDeclarator) {
// Now TypeScript knows tagDeclarator has a value property
if ('value' in tagLiteral) {
// Now TypeScript knows tagLiteral has a value property
return {
modifiedAst: ast,
tag: String(tagDeclarator.value),
tag: String(tagLiteral.value),
isTagExisting,
pathToNode: path,
}
@ -710,7 +696,7 @@ export function moveValueIntoNewVariablePath(
programMemory,
pathToNode
)
let _node = ast
let _node = JSON.parse(JSON.stringify(ast))
const boop = replacer(_node, variableName)
if (trap(boop)) return { modifiedAst: ast }
@ -742,7 +728,7 @@ export function moveValueIntoNewVariable(
programMemory,
sourceRange
)
let _node = ast
let _node = JSON.parse(JSON.stringify(ast))
const replaced = replacer(_node, variableName)
if (trap(replaced)) return { modifiedAst: ast }
@ -767,7 +753,7 @@ export function deleteSegmentFromPipeExpression(
code: string,
pathToNode: PathToNode
): Program | Error {
let _modifiedAst: Program = modifiedAst
let _modifiedAst: Program = JSON.parse(JSON.stringify(modifiedAst))
dependentRanges.forEach((range) => {
const path = getNodePathFromSourceRange(_modifiedAst, range)
@ -876,175 +862,3 @@ export function removeSingleConstraintInfo(
if (err(retval)) return false
return retval
}
export async function deleteFromSelection(
ast: Program,
selection: Selection,
programMemory: ProgramMemory,
getFaceDetails: (id: string) => Promise<Models['FaceIsPlanar_type']> = () =>
({} as any)
): Promise<Program | Error> {
const astClone = ast
const range = selection.range
const path = getNodePathFromSourceRange(ast, range)
const varDec = getNodeFromPath<VariableDeclarator>(
ast,
path,
'VariableDeclarator'
)
if (err(varDec)) return varDec
if (
(selection.type === 'extrude-wall' ||
selection.type === 'end-cap' ||
selection.type === 'start-cap') &&
varDec.node.init.type === 'PipeExpression'
) {
const varDecName = varDec.node.id.name
let pathToNode: PathToNode | null = null
let extrudeNameToDelete = ''
traverse(astClone, {
enter: (node, path) => {
if (node.type === 'VariableDeclaration') {
const dec = node.declarations[0]
if (
dec.init.type === 'CallExpression' &&
(dec.init.callee.name === 'extrude' ||
dec.init.callee.name === 'revolve') &&
dec.init.arguments?.[1].type === 'Identifier' &&
dec.init.arguments?.[1].name === varDecName
) {
pathToNode = path
extrudeNameToDelete = dec.id.name
}
}
},
})
if (!pathToNode) return new Error('Could not find extrude variable')
const expressionIndex = pathToNode[1][0] as number
astClone.body.splice(expressionIndex, 1)
if (extrudeNameToDelete) {
await new Promise(async (resolve) => {
let currentVariableName = ''
const pathsDependingOnExtrude: Array<{
path: PathToNode
sketchName: string
}> = []
traverse(astClone, {
leave: (node) => {
if (node.type === 'VariableDeclaration') {
currentVariableName = ''
}
},
enter: async (node, path) => {
if (node.type === 'VariableDeclaration') {
currentVariableName = node.declarations[0].id.name
}
if (
// match startSketchOn(${extrudeNameToDelete})
node.type === 'CallExpression' &&
node.callee.name === 'startSketchOn' &&
node.arguments[0].type === 'Identifier' &&
node.arguments[0].name === extrudeNameToDelete
) {
pathsDependingOnExtrude.push({
path,
sketchName: currentVariableName,
})
}
},
})
const roundLiteral = (x: number) => createLiteral(roundOff(x))
const modificationDetails: {
parent: PipeExpression['body']
faceDetails: Models['FaceIsPlanar_type']
lastKey: number
}[] = []
for (const { path, sketchName } of pathsDependingOnExtrude) {
const parent = getNodeFromPath<PipeExpression['body']>(
astClone,
path.slice(0, -1)
)
if (err(parent)) {
return
}
const sketchToPreserve = programMemory.root[sketchName] as SketchGroup
console.log('sketchName', sketchName)
// Can't kick off multiple requests at once as getFaceDetails
// is three engine calls in one and they conflict
const faceDetails = await getFaceDetails(sketchToPreserve.on.id)
if (
!(
faceDetails.origin &&
faceDetails.x_axis &&
faceDetails.y_axis &&
faceDetails.z_axis
)
) {
return
}
const lastKey = Number(path.slice(-1)[0][0])
modificationDetails.push({
parent: parent.node,
faceDetails,
lastKey,
})
}
for (const { parent, faceDetails, lastKey } of modificationDetails) {
if (
!(
faceDetails.origin &&
faceDetails.x_axis &&
faceDetails.y_axis &&
faceDetails.z_axis
)
) {
continue
}
parent[lastKey] = createCallExpressionStdLib('startSketchOn', [
createObjectExpression({
plane: createObjectExpression({
origin: createObjectExpression({
x: roundLiteral(faceDetails.origin.x),
y: roundLiteral(faceDetails.origin.y),
z: roundLiteral(faceDetails.origin.z),
}),
x_axis: createObjectExpression({
x: roundLiteral(faceDetails.x_axis.x),
y: roundLiteral(faceDetails.x_axis.y),
z: roundLiteral(faceDetails.x_axis.z),
}),
y_axis: createObjectExpression({
x: roundLiteral(faceDetails.y_axis.x),
y: roundLiteral(faceDetails.y_axis.y),
z: roundLiteral(faceDetails.y_axis.z),
}),
z_axis: createObjectExpression({
x: roundLiteral(faceDetails.z_axis.x),
y: roundLiteral(faceDetails.z_axis.y),
z: roundLiteral(faceDetails.z_axis.z),
}),
}),
}),
])
}
resolve(true)
})
}
// await prom
return astClone
} else if (varDec.node.init.type === 'PipeExpression') {
const pipeBody = varDec.node.init.body
if (
pipeBody[0].type === 'CallExpression' &&
pipeBody[0].callee.name === 'startSketchOn'
) {
// remove varDec
const varDecIndex = varDec.shallowPath[1][0] as number
astClone.body.splice(varDecIndex, 1)
return astClone
}
}
return new Error('Selection not recognised, could not delete')
}

View File

@ -1,4 +1,4 @@
import { parse, recast, initPromise, PathToNode } from './wasm'
import { parse, recast, initPromise } from './wasm'
import {
findAllPreviousVariables,
isNodeSafeToReplace,
@ -9,7 +9,6 @@ import {
findUsesOfTagInPipe,
hasSketchPipeBeenExtruded,
hasExtrudableGeometry,
traverse,
} from './queryAst'
import { enginelessExecutor } from '../lib/testHelpers'
import {
@ -19,7 +18,6 @@ import {
createPipeSubstitution,
} from './modifyAst'
import { err } from 'lib/trap'
import { warn } from 'node:console'
beforeAll(async () => {
await initPromise
@ -87,7 +85,10 @@ const yo2 = hmm([identifierGuy + 5])`
expect(result.isSafe).toBe(true)
expect(result.value?.type).toBe('BinaryExpression')
expect(code.slice(result.value.start, result.value.end)).toBe('100 + 100')
const replaced = result.replacer(ast, 'replaceName')
const replaced = result.replacer(
JSON.parse(JSON.stringify(ast)),
'replaceName'
)
if (err(replaced)) throw replaced
const outCode = recast(replaced.modifiedAst)
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
@ -111,7 +112,10 @@ const yo2 = hmm([identifierGuy + 5])`
expect(result.isSafe).toBe(true)
expect(result.value?.type).toBe('CallExpression')
expect(code.slice(result.value.start, result.value.end)).toBe("def('yo')")
const replaced = result.replacer(ast, 'replaceName')
const replaced = result.replacer(
JSON.parse(JSON.stringify(ast)),
'replaceName'
)
if (err(replaced)) throw replaced
const outCode = recast(replaced.modifiedAst)
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
@ -148,7 +152,10 @@ const yo2 = hmm([identifierGuy + 5])`
expect(result.isSafe).toBe(true)
expect(result.value?.type).toBe('BinaryExpression')
expect(code.slice(result.value.start, result.value.end)).toBe('5 + 6')
const replaced = result.replacer(ast, 'replaceName')
const replaced = result.replacer(
JSON.parse(JSON.stringify(ast)),
'replaceName'
)
if (err(replaced)) throw replaced
const outCode = recast(replaced.modifiedAst)
expect(outCode).toContain(`const yo = replaceName`)
@ -164,7 +171,10 @@ const yo2 = hmm([identifierGuy + 5])`
expect(code.slice(result.value.start, result.value.end)).toBe(
"jkl('yo') + 2"
)
const replaced = result.replacer(ast, 'replaceName')
const replaced = result.replacer(
JSON.parse(JSON.stringify(ast)),
'replaceName'
)
if (err(replaced)) throw replaced
const { modifiedAst } = replaced
const outCode = recast(modifiedAst)
@ -183,7 +193,10 @@ const yo2 = hmm([identifierGuy + 5])`
expect(code.slice(result.value.start, result.value.end)).toBe(
'identifierGuy + 5'
)
const replaced = result.replacer(ast, 'replaceName')
const replaced = result.replacer(
JSON.parse(JSON.stringify(ast)),
'replaceName'
)
if (err(replaced)) throw replaced
const { modifiedAst } = replaced
const outCode = recast(modifiedAst)
@ -398,15 +411,15 @@ describe('Testing findUsesOfTagInPipe', () => {
const exampleCode = `const part001 = startSketchOn('-XZ')
|> startProfileAt([68.12, 156.65], %)
|> line([306.21, 198.82], %)
|> line([306.21, 198.85], %, $seg01)
|> angledLine([-65, segLen(seg01, %)], %)
|> line([306.21, 198.85], %, 'seg01')
|> angledLine([-65, segLen('seg01', %)], %)
|> line([306.21, 198.87], %)
|> angledLine([65, segLen(seg01, %)], %)`
|> angledLine([65, segLen('seg01', %)], %)`
it('finds the current segment', async () => {
const ast = parse(exampleCode)
if (err(ast)) throw ast
const lineOfInterest = `198.85], %, $seg01`
const lineOfInterest = `198.85], %, 'seg01'`
const characterIndex =
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
const pathToNode = getNodePathFromSourceRange(ast, [
@ -441,7 +454,7 @@ describe('Testing hasSketchPipeBeenExtruded', () => {
|> line([2.48, 2.44], %)
|> line([2.66, 1.17], %)
|> line([3.75, 0.46], %)
|> line([4.99, -0.46], %, $seg01)
|> line([4.99, -0.46], %, 'seg01')
|> line([3.3, -2.12], %)
|> line([2.16, -3.33], %)
|> line([0.85, -3.08], %)
@ -450,7 +463,7 @@ describe('Testing hasSketchPipeBeenExtruded', () => {
|> line([-17.67, 0.85], %)
|> close(%)
const extrude001 = extrude(10, sketch001)
const sketch002 = startSketchOn(extrude001, $seg01)
const sketch002 = startSketchOn(extrude001, 'seg01')
|> startProfileAt([-12.94, 6.6], %)
|> line([2.45, -0.2], %)
|> line([-2, -1.25], %)
@ -460,7 +473,7 @@ const sketch002 = startSketchOn(extrude001, $seg01)
it('finds sketch001 pipe to be extruded', async () => {
const ast = parse(exampleCode)
if (err(ast)) throw ast
const lineOfInterest = `line([4.99, -0.46], %, $seg01)`
const lineOfInterest = `line([4.99, -0.46], %, 'seg01')`
const characterIndex =
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
const extruded = hasSketchPipeBeenExtruded(
@ -498,7 +511,7 @@ describe('Testing hasExtrudableGeometry', () => {
|> line([-17.67, 0.85], %)
|> close(%)
const extrude001 = extrude(10, sketch001)
const sketch002 = startSketchOn(extrude001, $seg01)
const sketch002 = startSketchOn(extrude001, 'seg01')
|> startProfileAt([-12.94, 6.6], %)
|> line([2.45, -0.2], %)
|> line([-2, -1.25], %)
@ -525,53 +538,3 @@ const extrude001 = extrude(10, sketch001)
expect(extrudable).toBeFalsy()
})
})
describe('Testing traverse and pathToNode', () => {
it.each([
['basic', '2.73'],
[
'very nested, array, object, callExpression, array, memberExpression',
'.yo',
],
])('testing %s', async (testName, literalOfInterest) => {
const code = `const myVar = 5
const sketch001 = startSketchOn('XZ')
|> startProfileAt([3.29, 7.86], %)
|> line([2.48, 2.44], %)
|> line([-3.86, -2.73], %)
|> line([-17.67, 0.85], %)
|> close(%)
const bing = { yo: 55 }
const myNestedVar = [
{
prop: line([bing.yo, 21], sketch001)
}
]
`
const ast = parse(code)
if (err(ast)) throw ast
let pathToNode: PathToNode = []
traverse(ast, {
enter: (node, path) => {
if (
node.type === 'Literal' &&
String(node.value) === literalOfInterest
) {
pathToNode = path
} else if (
node.type === 'Identifier' &&
literalOfInterest.includes(node.name)
) {
pathToNode = path
}
},
})
const literalIndex = code.indexOf(literalOfInterest)
const pathToNode2 = getNodePathFromSourceRange(ast, [
literalIndex + 2,
literalIndex + 2,
])
expect(pathToNode).toEqual(pathToNode2)
})
})

View File

@ -270,18 +270,6 @@ function moreNodePathFromSourceRange(
}
}
}
if (_node.type === 'MemberExpression' && isInRange) {
const { object, property } = _node
if (object.start <= start && object.end >= end) {
path.push(['object', 'MemberExpression'])
return moreNodePathFromSourceRange(object, sourceRange, path)
}
if (property.start <= start && property.end >= end) {
path.push(['property', 'MemberExpression'])
return moreNodePathFromSourceRange(property, sourceRange, path)
}
return path
}
if (_node.type === 'PipeSubstitution' && isInRange) return path
console.error('not implemented: ' + node.type)
return path
@ -319,89 +307,48 @@ type KCLNode =
| ReturnStatement
export function traverse(
node: KCLNode | Program,
node: KCLNode,
option: {
enter?: (node: KCLNode, pathToNode: PathToNode) => void
enter?: (node: KCLNode) => void
leave?: (node: KCLNode) => void
},
pathToNode: PathToNode = []
) {
const _node = node as KCLNode
option?.enter?.(_node, pathToNode)
const _traverse = (node: KCLNode, pathToNode: PathToNode) =>
traverse(node, option, pathToNode)
if (_node.type === 'VariableDeclaration') {
_node.declarations.forEach((declaration, index) =>
_traverse(declaration, [
...pathToNode,
['declarations', 'VariableDeclaration'],
[index, 'index'],
])
)
} else if (_node.type === 'VariableDeclarator') {
_traverse(_node.init, [...pathToNode, ['init', '']])
} else if (_node.type === 'PipeExpression') {
_node.body.forEach((expression, index) =>
_traverse(expression, [
...pathToNode,
['body', 'PipeExpression'],
[index, 'index'],
])
)
} else if (_node.type === 'CallExpression') {
_traverse(_node.callee, [...pathToNode, ['callee', 'CallExpression']])
_node.arguments.forEach((arg, index) =>
_traverse(arg, [
...pathToNode,
['arguments', 'CallExpression'],
[index, 'index'],
])
)
} else if (_node.type === 'BinaryExpression') {
_traverse(_node.left, [...pathToNode, ['left', 'BinaryExpression']])
_traverse(_node.right, [...pathToNode, ['right', 'BinaryExpression']])
} else if (_node.type === 'Identifier') {
// do nothing
} else if (_node.type === 'Literal') {
// do nothing
} else if (_node.type === 'TagDeclarator') {
// do nothing
} else if (_node.type === 'ArrayExpression') {
_node.elements.forEach((el, index) =>
_traverse(el, [
...pathToNode,
['elements', 'ArrayExpression'],
[index, 'index'],
])
)
} else if (_node.type === 'ObjectExpression') {
_node.properties.forEach(({ key, value }, index) => {
_traverse(key, [
...pathToNode,
['properties', 'ObjectExpression'],
[index, 'index'],
['key', 'Property'],
])
_traverse(value, [
...pathToNode,
['properties', 'ObjectExpression'],
[index, 'index'],
['value', 'Property'],
])
})
} else if (_node.type === 'UnaryExpression') {
_traverse(_node.argument, [...pathToNode, ['argument', 'UnaryExpression']])
} else if (_node.type === 'MemberExpression') {
// hmm this smell
_traverse(_node.object, [...pathToNode, ['object', 'MemberExpression']])
_traverse(_node.property, [...pathToNode, ['property', 'MemberExpression']])
} else if ('body' in _node && Array.isArray(_node.body)) {
_node.body.forEach((expression, index) =>
_traverse(expression, [...pathToNode, ['body', ''], [index, 'index']])
)
}
option?.leave?.(_node)
) {
option?.enter?.(node)
const _traverse = (node: KCLNode) => traverse(node, option)
if (node.type === 'VariableDeclaration') {
node.declarations.forEach(_traverse)
} else if (node.type === 'VariableDeclarator') {
_traverse(node.init)
} else if (node.type === 'PipeExpression') {
node.body.forEach(_traverse)
} else if (node.type === 'CallExpression') {
_traverse(node.callee)
node.arguments.forEach(_traverse)
} else if (node.type === 'BinaryExpression') {
_traverse(node.left)
_traverse(node.right)
} else if (node.type === 'Identifier') {
// do nothing
} else if (node.type === 'Literal') {
// do nothing
} else if (node.type === 'ArrayExpression') {
node.elements.forEach(_traverse)
} else if (node.type === 'ObjectExpression') {
node.properties.forEach(({ key, value }) => {
_traverse(key)
_traverse(value)
})
} else if (node.type === 'UnaryExpression') {
_traverse(node.argument)
} else if (node.type === 'MemberExpression') {
// hmm this smell
_traverse(node.object)
_traverse(node.property)
} else if ('body' in node && Array.isArray(node.body)) {
node.body.forEach(_traverse)
}
option?.leave?.(node)
}
export interface PrevVariable<T> {
@ -520,8 +467,8 @@ export function isNodeSafeToReplacePath(
const replaceNodeWithIdentifier: ReplacerFn = (_ast, varName) => {
const identifier = createIdentifier(varName)
const last = finPath[finPath.length - 1]
const pathToReplaced = finPath
pathToReplaced[1][0] = (pathToReplaced[1][0] as number) + 1
const pathToReplaced = JSON.parse(JSON.stringify(finPath))
pathToReplaced[1][0] = pathToReplaced[1][0] + 1
const startPath = finPath.slice(0, -1)
const _nodeToReplace = getNodeFromPath(_ast, startPath)
if (err(_nodeToReplace)) return _nodeToReplace
@ -787,14 +734,8 @@ export function findUsesOfTagInPipe(
if (node.type !== 'CallExpression') return []
const tagIndex = node.callee.name === 'close' ? 1 : 2
const thirdParam = node.arguments[tagIndex]
if (
!(thirdParam?.type === 'TagDeclarator' || thirdParam?.type === 'Identifier')
)
return []
const tag =
thirdParam?.type === 'TagDeclarator'
? String(thirdParam.value)
: thirdParam.name
if (thirdParam?.type !== 'Literal') return []
const tag = String(thirdParam.value)
const varDec = getNodeFromPath<VariableDeclaration>(
ast,
@ -815,11 +756,9 @@ export function findUsesOfTagInPipe(
)
return
const tagArg = node.arguments[0]
if (!(tagArg.type === 'TagDeclarator' || tagArg.type === 'Identifier'))
return
const tagArgValue =
tagArg.type === 'TagDeclarator' ? String(tagArg.value) : tagArg.name
if (tagArgValue === tag) dependentRanges.push([node.start, node.end])
if (tagArg.type !== 'Literal') return
if (String(tagArg.value) === tag)
dependentRanges.push([node.start, node.end])
},
})
return dependentRanges

View File

@ -76,9 +76,9 @@ log(5, myVar)
})
it('recast sketch declaration', () => {
let code = `const mySketch = startSketchAt([0, 0])
|> lineTo([0, 1], %, $myPath)
|> lineTo([0, 1], %, "myPath")
|> lineTo([1, 1], %)
|> lineTo([1, 0], %, $rightPath)
|> lineTo([1, 0], %, "rightPath")
|> close(%)
`
const { ast } = code2ast(code)
@ -90,7 +90,7 @@ log(5, myVar)
const code = [
'const mySk1 = startSketchAt([0, 0])',
' |> lineTo([1, 1], %)',
' |> lineTo([0, 1], %, $myTag)',
' |> lineTo([0, 1], %, "myTag")',
' |> lineTo([1, 1], %)',
' |> rx(90, %)',
].join('\n')
@ -266,7 +266,7 @@ const key = 'c'
const code = [
'const mySk1 = startSketchAt([0, 0])',
' |> lineTo([1, 1], %)',
' |> lineTo([0, 1], %, $myTag)',
' |> lineTo([0, 1], %, "myTag")',
' |> lineTo([1, 1], %)',
' // a comment',
' |> rx(90, %)',
@ -283,7 +283,7 @@ const key = 'c'
const mySk1 = startSketchAt([0, 0])
|> lineTo([1, 1], %)
// comment here
|> lineTo([0, 1], %, $myTag)
|> lineTo([0, 1], %, 'myTag')
|> lineTo([1, 1], %) /* and
here
*/
@ -306,7 +306,7 @@ one more for good measure
const mySk1 = startSketchAt([0, 0])
|> lineTo([1, 1], %)
// comment here
|> lineTo([0, 1], %, $myTag)
|> lineTo([0, 1], %, 'myTag')
|> lineTo([1, 1], %) /* and
here */
// a comment between pipe expression statements
@ -356,12 +356,12 @@ describe('testing call Expressions in BinaryExpressions and UnaryExpressions', (
describe('it recasts wrapped object expressions in pipe bodies with correct indentation', () => {
it('with a single line', () => {
const code = `const part001 = startSketchAt([-0.01, -0.08])
|> line([0.62, 4.15], %, $seg01)
|> line([0.62, 4.15], %, 'seg01')
|> line([2.77, -1.24], %)
|> angledLineThatIntersects({
angle: 201,
offset: -1.35,
intersectTag: $seg01
intersectTag: 'seg01'
}, %)
|> line([-0.42, -1.72], %)
`
@ -374,7 +374,7 @@ describe('it recasts wrapped object expressions in pipe bodies with correct inde
const code = `angledLineThatIntersects({
angle: 201,
offset: -1.35,
intersectTag: $seg01
intersectTag: 'seg01'
}, %)
`
const { ast } = code2ast(code)

View File

@ -1249,29 +1249,6 @@ export class EngineCommandManager extends EventTarget {
})
this.initPlanes().then(async () => {
// Hide the grid and grid scale text.
this.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'object_visible' as any,
// Found in engine/constants.h
object_id: 'cfa78409-653d-4c26-96f1-7c45fb784840',
hidden: true,
},
})
this.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'object_visible' as any,
// Found in engine/constants.h
object_id: '10782f33-f588-4668-8bcd-040502d26590',
hidden: true,
},
})
this.resolveReady()
setIsStreamReady(true)
await executeCode()

View File

@ -230,7 +230,7 @@ describe('testing addTagForSketchOnFace', () => {
if (err(sketchOnFaceRetVal)) return sketchOnFaceRetVal
const { modifiedAst } = sketchOnFaceRetVal
const expectedCode = genCode('lineTo([-1.59, -1.54], %, $seg01)')
const expectedCode = genCode("lineTo([-1.59, -1.54], %, 'seg01')")
expect(recast(modifiedAst)).toBe(expectedCode)
})
})

View File

@ -11,7 +11,6 @@ import {
Value,
Literal,
VariableDeclaration,
Identifier,
} from 'lang/wasm'
import {
getNodeFromPath,
@ -41,7 +40,6 @@ import {
import {
createLiteral,
createTagDeclarator,
createCallExpression,
createArrayExpression,
createPipeSubstitution,
@ -53,7 +51,6 @@ import {
import { roundOff, getLength, getAngle } from 'lib/utils'
import { err } from 'lib/trap'
import { perpendicularDistance } from 'sketch-helpers'
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
export type Coords2d = [number, number]
@ -1409,7 +1406,7 @@ export const angledLineThatIntersects: SketchLineHelper = {
?.value || createLiteral('')
: createLiteral('')
const intersectTagName =
intersectTag.type === 'Identifier' ? intersectTag.name : ''
intersectTag.type === 'Literal' ? intersectTag.value : ''
const nodeMeta2 = getNodeFromPath<VariableDeclaration>(
_node,
pathToNode,
@ -1500,23 +1497,23 @@ export const angledLineThatIntersects: SketchLineHelper = {
)
}
if (intersectTag !== -1) {
const tag = firstArg.properties[intersectTag]?.value as Identifier
const tag = firstArg.properties[intersectTag]?.value
const pathToTagProp: PathToNode = [
...pathToObjectExp,
[intersectTag, 'index'],
['value', 'Property'],
]
const info = constrainInfo(
'intersectionTag',
// This will always be a tag identifier.
false,
code.slice(tag.start, tag.end),
'angledLineThatIntersects',
'intersectTag',
[tag.start, tag.end],
pathToTagProp
returnVal.push(
constrainInfo(
'intersectionTag',
isNotLiteralArrayOrStatic(tag),
code.slice(tag.start, tag.end),
'angledLineThatIntersects',
'intersectTag',
[tag.start, tag.end],
pathToTagProp
)
)
returnVal.push(info)
}
return returnVal
},
@ -1833,18 +1830,17 @@ function addTag(tagIndex = 2): addTagFn {
// Tag is always 3rd expression now, using arg index feels brittle
// but we can come up with a better way to identify tag later.
const thirdArg = primaryCallExp.arguments?.[tagIndex]
const tagDeclarator =
thirdArg ||
(createTagDeclarator(findUniqueName(_node, 'seg', 2)) as TagDeclarator)
const tagLiteral =
thirdArg || (createLiteral(findUniqueName(_node, 'seg', 2)) as Literal)
const isTagExisting = !!thirdArg
if (!isTagExisting) {
primaryCallExp.arguments[tagIndex] = tagDeclarator
primaryCallExp.arguments[tagIndex] = tagLiteral
}
if ('value' in tagDeclarator) {
// Now TypeScript knows tagDeclarator has a value property
if ('value' in tagLiteral) {
// Now TypeScript knows tagLiteral has a value property
return {
modifiedAst: _node,
tag: String(tagDeclarator.value),
tag: String(tagLiteral.value),
}
} else {
return new Error('Unable to assign tag without value')

View File

@ -65,17 +65,17 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
const bigExampleArr = [
`const part001 = startSketchOn('XY')`,
` |> startProfileAt([0, 0], %)`,
` |> lineTo([1, 1], %, $abc1)`,
` |> line([-2.04, -0.7], %, $abc2)`,
` |> angledLine({ angle: 157, length: 1.69 }, %, $abc3)`,
` |> angledLineOfXLength({ angle: 217, length: 0.86 }, %, $abc4)`,
` |> angledLineOfYLength({ angle: 104, length: 1.58 }, %, $abc5)`,
` |> angledLineToX({ angle: 55, to: -2.89 }, %, $abc6)`,
` |> angledLineToY({ angle: 330, to: 2.53 }, %, $abc7)`,
` |> xLine(1.47, %, $abc8)`,
` |> yLine(1.57, %, $abc9)`,
` |> xLineTo(1.49, %, $abc10)`,
` |> yLineTo(2.64, %, $abc11)`,
` |> lineTo([1, 1], %, 'abc1')`,
` |> line([-2.04, -0.7], %, 'abc2')`,
` |> angledLine({ angle: 157, length: 1.69 }, %, 'abc3')`,
` |> angledLineOfXLength({ angle: 217, length: 0.86 }, %, 'abc4')`,
` |> angledLineOfYLength({ angle: 104, length: 1.58 }, %, 'abc5')`,
` |> angledLineToX({ angle: 55, to: -2.89 }, %, 'abc6')`,
` |> angledLineToY({ angle: 330, to: 2.53 }, %, 'abc7')`,
` |> xLine(1.47, %, 'abc8')`,
` |> yLine(1.57, %, 'abc9')`,
` |> xLineTo(1.49, %, 'abc10')`,
` |> yLineTo(2.64, %, 'abc11')`,
` |> lineTo([2.55, 3.58], %) // lineTo`,
` |> line([0.73, -0.75], %)`,
` |> angledLine([63, 1.38], %) // angledLine`,
@ -90,8 +90,8 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
]
const bigExample = bigExampleArr.join('\n')
it('line with tag converts to xLine', async () => {
const callToSwap = 'line([-2.04, -0.7], %, $abc2)'
const expectedLine = 'xLine(-2.04, %, $abc2)'
const callToSwap = "line([-2.04, -0.7], %, 'abc2')"
const expectedLine = "xLine(-2.04, %, 'abc2')"
const { newCode, originalRange } = await testingSwapSketchFnCall({
inputCode: bigExample,
callToSwap,
@ -116,10 +116,10 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
it('lineTo with tag converts to xLineTo', async () => {
const { newCode, originalRange } = await testingSwapSketchFnCall({
inputCode: bigExample,
callToSwap: 'lineTo([1, 1], %, $abc1)',
callToSwap: "lineTo([1, 1], %, 'abc1')",
constraintType: 'horizontal',
})
const expectedLine = 'xLineTo(1, %, $abc1)'
const expectedLine = "xLineTo(1, %, 'abc1')"
expect(newCode).toContain(expectedLine)
// new line should start at the same place as the old line
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
@ -138,10 +138,10 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
it('angledLine with tag converts to xLine', async () => {
const { newCode, originalRange } = await testingSwapSketchFnCall({
inputCode: bigExample,
callToSwap: 'angledLine({ angle: 157, length: 1.69 }, %, $abc3)',
callToSwap: "angledLine({ angle: 157, length: 1.69 }, %, 'abc3')",
constraintType: 'horizontal',
})
const expectedLine = 'xLine(-1.56, %, $abc3)'
const expectedLine = "xLine(-1.56, %, 'abc3')"
console.log(newCode)
expect(newCode).toContain(expectedLine)
// new line should start at the same place as the old line
@ -161,10 +161,11 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
it('angledLineOfXLength with tag converts to xLine', async () => {
const { newCode, originalRange } = await testingSwapSketchFnCall({
inputCode: bigExample,
callToSwap: 'angledLineOfXLength({ angle: 217, length: 0.86 }, %, $abc4)',
callToSwap:
"angledLineOfXLength({ angle: 217, length: 0.86 }, %, 'abc4')",
constraintType: 'horizontal',
})
const expectedLine = 'xLine(-0.86, %, $abc4)'
const expectedLine = "xLine(-0.86, %, 'abc4')"
// hmm "-0.86" is correct since the angle is 104, but need to make sure this is compatible `-myVar`
expect(newCode).toContain(expectedLine)
// new line should start at the same place as the old line
@ -184,10 +185,11 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
it('angledLineOfYLength with tag converts to yLine', async () => {
const { newCode, originalRange } = await testingSwapSketchFnCall({
inputCode: bigExample,
callToSwap: 'angledLineOfYLength({ angle: 104, length: 1.58 }, %, $abc5)',
callToSwap:
"angledLineOfYLength({ angle: 104, length: 1.58 }, %, 'abc5')",
constraintType: 'vertical',
})
const expectedLine = 'yLine(1.58, %, $abc5)'
const expectedLine = "yLine(1.58, %, 'abc5')"
expect(newCode).toContain(expectedLine)
// new line should start at the same place as the old line
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
@ -206,10 +208,10 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
it('angledLineToX with tag converts to xLineTo', async () => {
const { newCode, originalRange } = await testingSwapSketchFnCall({
inputCode: bigExample,
callToSwap: 'angledLineToX({ angle: 55, to: -2.89 }, %, $abc6)',
callToSwap: "angledLineToX({ angle: 55, to: -2.89 }, %, 'abc6')",
constraintType: 'horizontal',
})
const expectedLine = 'xLineTo(-2.89, %, $abc6)'
const expectedLine = "xLineTo(-2.89, %, 'abc6')"
expect(newCode).toContain(expectedLine)
// new line should start at the same place as the old line
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
@ -228,10 +230,10 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => {
it('angledLineToY with tag converts to yLineTo', async () => {
const { newCode, originalRange } = await testingSwapSketchFnCall({
inputCode: bigExample,
callToSwap: 'angledLineToY({ angle: 330, to: 2.53 }, %, $abc7)',
callToSwap: "angledLineToY({ angle: 330, to: 2.53 }, %, 'abc7')",
constraintType: 'vertical',
})
const expectedLine = 'yLineTo(2.53, %, $abc7)'
const expectedLine = "yLineTo(2.53, %, 'abc7')"
expect(newCode).toContain(expectedLine)
// new line should start at the same place as the old line
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))

View File

@ -139,70 +139,70 @@ const myAng = 40
const myAng2 = 134
const part001 = startSketchOn('XY')
|> startProfileAt([0, 0], %)
|> line([1, 3.82], %, $seg01) // ln-should-get-tag
|> line([1, 3.82], %, 'seg01') // ln-should-get-tag
|> angledLineToX([
-angleToMatchLengthX(seg01, myVar, %),
-angleToMatchLengthX('seg01', myVar, %),
myVar
], %) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|> angledLineToY([
-angleToMatchLengthY(seg01, myVar, %),
-angleToMatchLengthY('seg01', myVar, %),
myVar
], %) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper
|> angledLine([45, segLen(seg01, %)], %) // ln-lineTo-free should become angledLine
|> angledLine([45, segLen(seg01, %)], %) // ln-angledLineToX-free should become angledLine
|> angledLine([myAng, segLen(seg01, %)], %) // ln-angledLineToX-angle should become angledLine
|> angledLine([45, segLen('seg01', %)], %) // ln-lineTo-free should become angledLine
|> angledLine([45, segLen('seg01', %)], %) // ln-angledLineToX-free should become angledLine
|> angledLine([myAng, segLen('seg01', %)], %) // ln-angledLineToX-angle should become angledLine
|> angledLineToX([
angleToMatchLengthX(seg01, myVar2, %),
angleToMatchLengthX('seg01', myVar2, %),
myVar2
], %) // ln-angledLineToX-xAbsolute should use angleToMatchLengthX to get angle
|> angledLine([-45, segLen(seg01, %)], %) // ln-angledLineToY-free should become angledLine
|> angledLine([myAng2, segLen(seg01, %)], %) // ln-angledLineToY-angle should become angledLine
|> angledLine([-45, segLen('seg01', %)], %) // ln-angledLineToY-free should become angledLine
|> angledLine([myAng2, segLen('seg01', %)], %) // ln-angledLineToY-angle should become angledLine
|> angledLineToY([
angleToMatchLengthY(seg01, myVar3, %),
angleToMatchLengthY('seg01', myVar3, %),
myVar3
], %) // ln-angledLineToY-yAbsolute should use angleToMatchLengthY to get angle
|> line([
min(segLen(seg01, %), myVar),
legLen(segLen(seg01, %), myVar)
min(segLen('seg01', %), myVar),
legLen(segLen('seg01', %), myVar)
], %) // ln-should use legLen for y
|> line([
min(segLen(seg01, %), myVar),
-legLen(segLen(seg01, %), myVar)
min(segLen('seg01', %), myVar),
-legLen(segLen('seg01', %), myVar)
], %) // ln-legLen but negative
|> angledLine([-112, segLen(seg01, %)], %) // ln-should become angledLine
|> angledLine([myVar, segLen(seg01, %)], %) // ln-use segLen for second arg
|> angledLine([45, segLen(seg01, %)], %) // ln-segLen again
|> angledLine([54, segLen(seg01, %)], %) // ln-should be transformed to angledLine
|> angledLine([-112, segLen('seg01', %)], %) // ln-should become angledLine
|> angledLine([myVar, segLen('seg01', %)], %) // ln-use segLen for second arg
|> angledLine([45, segLen('seg01', %)], %) // ln-segLen again
|> angledLine([54, segLen('seg01', %)], %) // ln-should be transformed to angledLine
|> angledLineOfXLength([
legAngX(segLen(seg01, %), myVar),
min(segLen(seg01, %), myVar)
legAngX(segLen('seg01', %), myVar),
min(segLen('seg01', %), myVar)
], %) // ln-should use legAngX to calculate angle
|> angledLineOfXLength([
180 + legAngX(segLen(seg01, %), myVar),
min(segLen(seg01, %), myVar)
180 + legAngX(segLen('seg01', %), myVar),
min(segLen('seg01', %), myVar)
], %) // ln-same as above but should have + 180 to match original quadrant
|> line([
legLen(segLen(seg01, %), myVar),
min(segLen(seg01, %), myVar)
legLen(segLen('seg01', %), myVar),
min(segLen('seg01', %), myVar)
], %) // ln-legLen again but yRelative
|> line([
-legLen(segLen(seg01, %), myVar),
min(segLen(seg01, %), myVar)
-legLen(segLen('seg01', %), myVar),
min(segLen('seg01', %), myVar)
], %) // ln-negative legLen yRelative
|> angledLine([58, segLen(seg01, %)], %) // ln-angledLineOfYLength-free should become angledLine
|> angledLine([myAng, segLen(seg01, %)], %) // ln-angledLineOfYLength-angle should become angledLine
|> angledLine([58, segLen('seg01', %)], %) // ln-angledLineOfYLength-free should become angledLine
|> angledLine([myAng, segLen('seg01', %)], %) // ln-angledLineOfYLength-angle should become angledLine
|> angledLineOfXLength([
legAngY(segLen(seg01, %), myVar),
min(segLen(seg01, %), myVar)
legAngY(segLen('seg01', %), myVar),
min(segLen('seg01', %), myVar)
], %) // ln-angledLineOfYLength-yRelative use legAngY
|> angledLineOfXLength([
270 + legAngY(segLen(seg01, %), myVar),
min(segLen(seg01, %), myVar)
270 + legAngY(segLen('seg01', %), myVar),
min(segLen('seg01', %), myVar)
], %) // ln-angledLineOfYLength-yRelative with angle > 90 use binExp
|> xLine(segLen(seg01, %), %) // ln-xLine-free should sub in segLen
|> yLine(segLen(seg01, %), %) // ln-yLine-free should sub in segLen
|> xLine(segLen(seg01, %), %) // ln-xLineTo-free should convert to xLine
|> yLine(segLen(seg01, %), %) // ln-yLineTo-free should convert to yLine
|> xLine(segLen('seg01', %), %) // ln-xLine-free should sub in segLen
|> yLine(segLen('seg01', %), %) // ln-yLine-free should sub in segLen
|> xLine(segLen('seg01', %), %) // ln-xLineTo-free should convert to xLine
|> yLine(segLen('seg01', %), %) // ln-yLineTo-free should convert to yLine
`
it('should transform the ast', async () => {
const ast = parse(inputScript)
@ -417,10 +417,10 @@ const part001 = startSketchOn('XY')
'setVertDistance'
)
expect(expectedHorizontalCode).toContain(
`lineTo([segEndX(seg01, %) + 0.9, 4.59], %) // free`
`lineTo([segEndX('seg01', %) + 0.9, 4.59], %) // free`
)
expect(expectedVerticalCode).toContain(
`lineTo([1.21, segEndY(seg01, %) + 2.92], %) // free`
`lineTo([1.21, segEndY('seg01', %) + 2.92], %) // free`
)
})
it('testing for xRelative to vertical distance', async () => {
@ -431,7 +431,7 @@ const part001 = startSketchOn('XY')
)
expect(expectedCode).toContain(`|> lineTo([
lastSegX(%) + myVar,
segEndY(seg01, %) + 2.93
segEndY('seg01', %) + 2.93
], %) // xRelative`)
})
it('testing for yRelative to horizontal distance', async () => {
@ -441,7 +441,7 @@ const part001 = startSketchOn('XY')
'setHorzDistance'
)
expect(expectedCode).toContain(`|> lineTo([
segEndX(seg01, %) + 2.6,
segEndX('seg01', %) + 2.6,
lastSegY(%) + myVar
], %) // yRelative`)
})

View File

@ -462,7 +462,7 @@ const setAngledIntersectLineForLines: TransformInfo['createNode'] =
angleVal,
offsetVal:
forceValueUsedInTransform || createLiteral(valueUsedInTransform),
intersectTag: createIdentifier(referenceSegName),
intersectTag: createLiteral(referenceSegName),
tag,
valueUsedInTransform,
})
@ -481,7 +481,7 @@ const setAngledIntersectForAngledLines: TransformInfo['createNode'] =
angleVal: varValA,
offsetVal:
forceValueUsedInTransform || createLiteral(valueUsedInTransform),
intersectTag: createIdentifier(referenceSegName),
intersectTag: createLiteral(referenceSegName),
tag,
valueUsedInTransform,
})
@ -675,7 +675,7 @@ const transformMap: TransformMap = {
const angleToMatchLengthXCall = createCallExpression(
'angleToMatchLengthX',
[
createIdentifier(referenceSegName),
createLiteral(referenceSegName),
varValA,
createPipeSubstitution(),
]
@ -708,7 +708,7 @@ const transformMap: TransformMap = {
const angleToMatchLengthYCall = createCallExpression(
'angleToMatchLengthY',
[
createIdentifier(referenceSegName),
createLiteral(referenceSegName),
varValB,
createPipeSubstitution(),
]
@ -973,7 +973,7 @@ const transformMap: TransformMap = {
const angleToMatchLengthXCall = createCallExpression(
'angleToMatchLengthX',
[
createIdentifier(referenceSegName),
createLiteral(referenceSegName),
varValB,
createPipeSubstitution(),
]
@ -1023,7 +1023,7 @@ const transformMap: TransformMap = {
const angleToMatchLengthXCall = createCallExpression(
'angleToMatchLengthY',
[
createIdentifier(referenceSegName),
createLiteral(referenceSegName),
varValB,
createPipeSubstitution(),
]
@ -1174,7 +1174,7 @@ export function getRemoveConstraintsTransform(
// fnName: name,
// angleVal: args[0],
// offsetVal: args[1],
// intersectTag: createIdentifier(referenceSegName),
// intersectTag: createLiteral(referenceSegName),
// tag,
// })
// }
@ -1496,7 +1496,7 @@ export function transformSecondarySketchLinesTagFirst({
}
}
| Error {
// let node = ast
// let node = JSON.parse(JSON.stringify(ast))
const primarySelection = selectionRanges.codeBasedSelections[0].range
const _tag = giveSketchFnCallTag(ast, primarySelection, forceSegName)
@ -1565,7 +1565,7 @@ export function transformAstSketchLines({
}
| Error {
// deep clone since we are mutating in a loop, of which any could fail
let node = ast
let node = JSON.parse(JSON.stringify(ast))
let _valueUsedInTransform // TODO should this be an array?
const pathToNodeMap: PathToNodeMap = {}
@ -1593,8 +1593,8 @@ export function transformAstSketchLines({
const _referencedSegmentName =
referenceSegName ||
(_referencedSegmentNameVal &&
_referencedSegmentNameVal.type === 'Identifier' &&
String(_referencedSegmentNameVal.name)) ||
_referencedSegmentNameVal.type === 'Literal' &&
String(_referencedSegmentNameVal.value)) ||
''
const { val } = firstArg
const [varValA, varValB] = Array.isArray(val) ? val : [val, val]
@ -1714,21 +1714,21 @@ export function transformAstSketchLines({
function createSegLen(referenceSegName: string): Value {
return createCallExpression('segLen', [
createIdentifier(referenceSegName),
createLiteral(referenceSegName),
createPipeSubstitution(),
])
}
function createSegAngle(referenceSegName: string): Value {
return createCallExpression('segAng', [
createIdentifier(referenceSegName),
createLiteral(referenceSegName),
createPipeSubstitution(),
])
}
function createSegEnd(referenceSegName: string, isX: boolean): CallExpression {
return createCallExpression(isX ? 'segEndX' : 'segEndY', [
createIdentifier(referenceSegName),
createLiteral(referenceSegName),
createPipeSubstitution(),
])
}

View File

@ -33,7 +33,7 @@ export function updatePathToNodeFromMap(
oldPath: PathToNode,
pathToNodeMap: { [key: number]: PathToNode }
): PathToNode {
const updatedPathToNode = oldPath
const updatedPathToNode = JSON.parse(JSON.stringify(oldPath))
let max = 0
Object.values(pathToNodeMap).forEach((path) => {
const index = Number(path[1][0])

View File

@ -2,7 +2,6 @@ import init, {
parse_wasm,
recast_wasm,
execute_wasm,
kcl_lint,
lexer_wasm,
modify_ast_for_sketch_wasm,
is_points_ccw,
@ -21,7 +20,6 @@ import { KCLError } from './errors'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
import { EngineCommandManager } from './std/engineConnection'
import { ProgramReturn } from '../wasm-lib/kcl/bindings/ProgramReturn'
import { Discovered } from '../wasm-lib/kcl/bindings/Discovered'
import { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
import type { Program } from '../wasm-lib/kcl/bindings/Program'
import type { Token } from '../wasm-lib/kcl/bindings/Token'
@ -207,17 +205,6 @@ export const _executor = async (
}
}
export const kclLint = async (ast: Program): Promise<Array<Discovered>> => {
try {
const discovered_findings: Array<Discovered> = await kcl_lint(
JSON.stringify(ast)
)
return discovered_findings
} catch (e: any) {
return Promise.reject(e)
}
}
export const recast = (ast: Program): string | Error => {
return recast_wasm(JSON.stringify(ast))
}
@ -334,7 +321,6 @@ export async function coreDump(
openGithubIssue: boolean = false
): Promise<CoreDumpInfo> {
try {
console.warn('CoreDump: Initializing core dump')
const dump: CoreDumpInfo = await coredump(coreDumpManager)
/* NOTE: this console output of the coredump should include the field
`github_issue_url` which is not in the uploaded coredump file.

View File

@ -13,14 +13,6 @@ import screenshot from 'lib/screenshot'
import React from 'react'
import { VITE_KC_API_BASE_URL } from 'env'
/* eslint-disable suggest-no-throw/suggest-no-throw --
* All the throws in CoreDumpManager are intentional and should be caught and handled properly
* by the calling Promises with a catch block. The throws are essential to properly handling
* when the app isn't ready enough or otherwise unable to produce a core dump. By throwing
* instead of simply erroring, the code halts execution at the first point which it cannot
* complete the core dump request.
**/
/**
* CoreDumpManager module
* - for getting all the values from the JS world to pass to the Rust world for a core dump.
@ -30,7 +22,6 @@ import { VITE_KC_API_BASE_URL } from 'env'
// CoreDumpManager is instantiated in ModelingMachineProvider and passed to coreDump() in wasm.ts
// The async function coreDump() handles any errors thrown in its Promise catch method and rethrows
// them to so the toast handler in ModelingMachineProvider can show the user an error message toast
// TODO: Throw more
export class CoreDumpManager {
engineCommandManager: EngineCommandManager
htmlRef: React.RefObject<HTMLDivElement> | null

View File

@ -9,12 +9,12 @@ const wallMountL = 6 // the length of the bracket
const sigmaAllow = 35000 // psi
const width = 6 // inch
const p = 300 // Force on shelf - lbs
const shelfLength = 12 // inches
const moment = shelfLength * p / 2 // Moment experienced at fixed end of bracket
const factorOfSafety = 2 // Factor of safety of 2 to be conservative
const L = 12 // inches
const M = L * p / 2 // Moment experienced at fixed end of bracket
const FOS = 2 // Factor of safety of 2 to be conservative
// Calculate the thickness off the bending stress and factor of safety
const thickness = sqrt(6 * moment * factorOfSafety / (width * sigmaAllow))
const thickness = sqrt(6 * M * FOS / (width * sigmaAllow))
// 0.25 inch fillet radius
const filletR = 0.25
@ -22,20 +22,20 @@ const filletR = 0.25
// Sketch the bracket and extrude with fillets
const bracket = startSketchOn('XY')
|> startProfileAt([0, 0], %)
|> line([0, wallMountL], %, $outerEdge)
|> line([0, wallMountL], %, 'outerEdge')
|> line([-shelfMountL, 0], %)
|> line([0, -thickness], %)
|> line([shelfMountL - thickness, 0], %, $innerEdge)
|> line([shelfMountL - thickness, 0], %, 'innerEdge')
|> line([0, -wallMountL + thickness], %)
|> close(%)
|> extrude(width, %)
|> fillet({
radius: filletR,
tags: [getPreviousAdjacentEdge(innerEdge, %)]
tags: [getPreviousAdjacentEdge('innerEdge', %)]
}, %)
|> fillet({
radius: filletR + thickness,
tags: [getPreviousAdjacentEdge(outerEdge, %)]
tags: [getPreviousAdjacentEdge('outerEdge', %)]
}, %)`
function findLineInExampleCode({

View File

@ -2,10 +2,8 @@ import {
createArrayExpression,
createBinaryExpression,
createCallExpressionStdLib,
createIdentifier,
createLiteral,
createPipeSubstitution,
createTagDeclarator,
createUnaryExpression,
} from 'lang/modifyAst'
import { roundOff } from './utils'
@ -37,13 +35,13 @@ export const getRectangleCallExpressions = (
createLiteral(0), // This will be the width of the rectangle
]),
createPipeSubstitution(),
createTagDeclarator(tags[0]),
createLiteral(tags[0]),
]),
createCallExpressionStdLib('angledLine', [
createArrayExpression([
createBinaryExpression([
createCallExpressionStdLib('segAng', [
createIdentifier(tags[0]),
createLiteral(tags[0]),
createPipeSubstitution(),
]),
'+',
@ -52,24 +50,24 @@ export const getRectangleCallExpressions = (
createLiteral(0), // This will be the height of the rectangle
]),
createPipeSubstitution(),
createTagDeclarator(tags[1]),
createLiteral(tags[1]),
]),
createCallExpressionStdLib('angledLine', [
createArrayExpression([
createCallExpressionStdLib('segAng', [
createIdentifier(tags[0]),
createLiteral(tags[0]),
createPipeSubstitution(),
]), // same angle as the first line
createUnaryExpression(
createCallExpressionStdLib('segLen', [
createIdentifier(tags[0]),
createLiteral(tags[0]),
createPipeSubstitution(),
]),
'-'
), // negative height
]),
createPipeSubstitution(),
createTagDeclarator(tags[2]),
createLiteral(tags[2]),
]),
createCallExpressionStdLib('lineTo', [
createArrayExpression([
@ -103,7 +101,7 @@ export function updateRectangleSketch(
.arguments[0] as ArrayExpression) = createArrayExpression([
createBinaryExpression([
createCallExpressionStdLib('segAng', [
createIdentifier(tag),
createLiteral(tag),
createPipeSubstitution(),
]),
Math.sign(y) === Math.sign(x) ? '+' : '-',

View File

@ -29,10 +29,7 @@ export function cleanErrs<T>(
return [argsWOutErr.length !== value.length, argsWOutErr, argsWErr]
}
/**
* Used to report errors to user at a certain point in execution
* @returns boolean
*/
// Used to report errors to user at a certain point in execution
export function trap<T>(
value: ExcludeErr<T> | Error,
opts?: {
@ -46,8 +43,6 @@ export function trap<T>(
console.error(value)
opts?.suppress ||
toast.error((opts?.altErr ?? value ?? new Error('Unknown')).toString(), {
id: 'error',
})
toast.error((opts?.altErr ?? value ?? new Error('Unknown')).toString())
return true
}

View File

@ -96,7 +96,9 @@ export function useCalculateKclExpression({
ast,
engineCommandManager,
useFakeExecutor: true,
programMemoryOverride: kclManager.programMemory,
programMemoryOverride: JSON.parse(
JSON.stringify(kclManager.programMemory)
),
})
const resultDeclaration = ast.body.find(
(a) =>

View File

@ -26,11 +26,7 @@ import {
applyConstraintEqualLength,
setEqualLengthInfo,
} from 'components/Toolbar/EqualLength'
import {
addStartProfileAt,
deleteFromSelection,
extrudeSketch,
} from 'lang/modifyAst'
import { addStartProfileAt, extrudeSketch } from 'lang/modifyAst'
import { getNodeFromPath } from '../lang/queryAst'
import {
applyConstraintEqualAngle,
@ -48,14 +44,12 @@ import {
import { Models } from '@kittycad/lib/dist/types/src'
import { ModelingCommandSchema } from 'lib/commandBarConfigs/modelingCommandConfig'
import { err, trap } from 'lib/trap'
import { DefaultPlaneStr, getFaceDetails } from 'clientSideScene/sceneEntities'
import { DefaultPlaneStr } from 'clientSideScene/sceneEntities'
import { Vector3 } from 'three'
import { quaternionFromUpNForward } from 'clientSideScene/helpers'
import { uuidv4 } from 'lib/utils'
import { Coords2d } from 'lang/std/sketch'
import { deleteSegment } from 'clientSideScene/ClientSideSceneComp'
import { executeAst } from 'useStore'
import toast from 'react-hot-toast'
export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY'
@ -163,9 +157,6 @@ export type ModelingMachineEvent =
type: 'Set selection'
data: SetSelections
}
| {
type: 'Delete selection'
}
| { type: 'Sketch no face' }
| { type: 'Toggle gui mode' }
| { type: 'Cancel' }
@ -282,13 +273,6 @@ export const modelingMachine = createMachine(
cond: 'Has exportable geometry',
actions: 'Engine export',
},
'Delete selection': {
target: 'idle',
cond: 'has valid selection for deletion',
actions: ['AST delete selection'],
internal: true,
},
},
entry: 'reset client scene mouse handlers',
@ -979,42 +963,6 @@ export const modelingMachine = createMachine(
editorManager.selectRange(updatedAst?.selections)
}
},
'AST delete selection': async ({ sketchDetails, selectionRanges }) => {
let ast = kclManager.ast
const getScaledFaceDetails = async (entityId: string) => {
const faceDetails = await getFaceDetails(entityId)
if (err(faceDetails)) return {}
return {
...faceDetails,
origin: {
x: faceDetails.origin.x / sceneInfra._baseUnitMultiplier,
y: faceDetails.origin.y / sceneInfra._baseUnitMultiplier,
z: faceDetails.origin.z / sceneInfra._baseUnitMultiplier,
},
}
}
const modifiedAst = await deleteFromSelection(
ast,
selectionRanges.codeBasedSelections[0],
kclManager.programMemory,
getScaledFaceDetails
)
if (err(modifiedAst)) return
const testExecute = await executeAst({
ast: modifiedAst,
useFakeExecutor: true,
engineCommandManager,
})
if (testExecute.errors.length) {
toast.error('Unable to delete part')
return
}
await kclManager.updateAst(modifiedAst, true)
},
'conditionally equip line tool': (_, { type }) => {
if (type === 'done.invoke.animate-to-face') {
sceneInfra.modelingSend('Equip Line tool')

View File

@ -19,12 +19,8 @@ export default function UserMenu() {
'[data-testid="user-sidebar-toggle"] img'
)
const onError = () => setAvatarErrored(true)
if (element?.tagName === 'IMG') {
element?.addEventListener('error', onError)
}
return () => {
element?.removeEventListener('error', onError)
element.addEventListener('error', () => setAvatarErrored(true))
}
}, [])

View File

@ -5,13 +5,11 @@ import {
_executor,
ProgramMemory,
programMemoryInit,
kclLint,
} from './lang/wasm'
import { enginelessExecutor } from './lib/testHelpers'
import { EngineCommandManager } from './lang/std/engineConnection'
import { KCLError } from './lang/errors'
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
import { Diagnostic } from '@codemirror/lint'
export type ToolTip =
| 'lineTo'
@ -189,24 +187,3 @@ export async function executeAst({
}
}
}
export async function lintAst({
ast,
}: {
ast: Program
}): Promise<Array<Diagnostic>> {
try {
const discovered_findings = await kclLint(ast)
return discovered_findings.map((lint) => {
return {
message: lint.finding.title,
severity: 'info',
from: lint.pos[0],
to: lint.pos[1],
}
})
} catch (e: any) {
console.log(e)
return []
}
}

View File

@ -183,6 +183,12 @@ dependencies = [
"syn 2.0.68",
]
[[package]]
name = "atomic"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba"
[[package]]
name = "auto_impl"
version = "1.2.0"
@ -533,7 +539,6 @@ dependencies = [
"ciborium",
"clap",
"criterion-plot",
"futures",
"is-terminal",
"itertools 0.10.5",
"num-traits",
@ -546,7 +551,6 @@ dependencies = [
"serde_derive",
"serde_json",
"tinytemplate",
"tokio",
"walkdir",
]
@ -658,20 +662,6 @@ dependencies = [
"parking_lot_core 0.9.9",
]
[[package]]
name = "dashmap"
version = "6.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "804c8821570c3f8b70230c2ba75ffa5c0f9a4189b9a432b6656c536712acae28"
dependencies = [
"cfg-if",
"crossbeam-utils",
"hashbrown 0.14.3",
"lock_api",
"once_cell",
"parking_lot_core 0.9.9",
]
[[package]]
name = "data-encoding"
version = "2.5.0"
@ -712,7 +702,7 @@ dependencies = [
[[package]]
name = "derive-docs"
version = "0.1.19"
version = "0.1.18"
dependencies = [
"Inflector",
"anyhow",
@ -1385,7 +1375,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.1.68"
version = "0.1.66"
dependencies = [
"anyhow",
"approx",
@ -1397,7 +1387,7 @@ dependencies = [
"clap",
"convert_case",
"criterion",
"dashmap 6.0.1",
"dashmap",
"databake",
"derive-docs",
"expectorate",
@ -1996,15 +1986,15 @@ dependencies = [
[[package]]
name = "pyo3"
version = "0.22.0"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1962a33ed2a201c637fc14a4e0fd4e06e6edfdeee6a5fede0dab55507ad74cf7"
checksum = "a5e00b96a521718e08e03b1a622f01c8a8deb50719335de3f60b3b3950f069d8"
dependencies = [
"cfg-if",
"indoc",
"libc",
"memoffset",
"once_cell",
"parking_lot 0.12.1",
"portable-atomic",
"pyo3-build-config",
"pyo3-ffi",
@ -2014,9 +2004,9 @@ dependencies = [
[[package]]
name = "pyo3-build-config"
version = "0.22.0"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab7164b2202753bd33afc7f90a10355a719aa973d1f94502c50d06f3488bc420"
checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50"
dependencies = [
"once_cell",
"target-lexicon",
@ -2024,9 +2014,9 @@ dependencies = [
[[package]]
name = "pyo3-ffi"
version = "0.22.0"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6424906ca49013c0829c5c1ed405e20e2da2dc78b82d198564880a704e6a7b7"
checksum = "01be5843dc60b916ab4dad1dca6d20b9b4e6ddc8e15f50c47fe6d85f1fb97403"
dependencies = [
"libc",
"pyo3-build-config",
@ -2034,9 +2024,9 @@ dependencies = [
[[package]]
name = "pyo3-macros"
version = "0.22.0"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82b2f19e153122d64afd8ce7aaa72f06a00f52e34e1d1e74b6d71baea396460a"
checksum = "77b34069fc0682e11b31dbd10321cbf94808394c56fd996796ce45217dfac53c"
dependencies = [
"proc-macro2",
"pyo3-macros-backend",
@ -2046,11 +2036,11 @@ dependencies = [
[[package]]
name = "pyo3-macros-backend"
version = "0.22.0"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd698c04cac17cf0fe63d47790ab311b8b25542f5cb976b65c374035c50f1eef"
checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c"
dependencies = [
"heck 0.5.0",
"heck 0.4.1",
"proc-macro2",
"pyo3-build-config",
"quote",
@ -2606,9 +2596,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.118"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
dependencies = [
"indexmap 2.2.5",
"itoa",
@ -3170,7 +3160,7 @@ dependencies = [
"async-trait",
"auto_impl",
"bytes",
"dashmap 5.5.3",
"dashmap",
"futures",
"httparse",
"lsp-types",
@ -3277,9 +3267,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "ts-rs"
version = "9.0.1"
version = "9.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b44017f9f875786e543595076374b9ef7d13465a518dd93d6ccdbf5b432dde8c"
checksum = "5e2dcf58e612adda9a83800731e8e4aba04d8a302b9029617b0b6e4b021d5357"
dependencies = [
"chrono",
"serde_json",
@ -3291,9 +3281,9 @@ dependencies = [
[[package]]
name = "ts-rs-macros"
version = "9.0.1"
version = "9.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c88cc88fd23b5a04528f3a8436024f20010a16ec18eb23c164b1242f65860130"
checksum = "cbdee324e50a7402416d9c25270d3df4241ed528af5d36dda18b6f219551c577"
dependencies = [
"proc-macro2",
"quote",
@ -3419,10 +3409,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "uuid"
version = "1.9.1"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439"
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
dependencies = [
"atomic",
"getrandom",
"serde",
"wasm-bindgen",

View File

@ -15,10 +15,10 @@ clap = "4.5.7"
gloo-utils = "0.2.0"
kcl-lib = { path = "kcl" }
kittycad.workspace = true
serde_json = "1.0.118"
serde_json = "1.0.116"
tokio = { version = "1.38.0", features = ["sync"] }
toml = "0.8.14"
uuid = { version = "1.9.1", features = ["v4", "js", "serde"] }
uuid = { version = "1.8.0", features = ["v4", "js", "serde"] }
wasm-bindgen = "0.2.91"
wasm-bindgen-futures = "0.4.42"
@ -31,7 +31,7 @@ pretty_assertions = "1.4.0"
reqwest = { version = "0.11.26", default-features = false }
tokio = { version = "1.38.0", features = ["rt-multi-thread", "macros", "time"] }
twenty-twenty = "0.8"
uuid = { version = "1.9.1", features = ["v4", "js", "serde"] }
uuid = { version = "1.8.0", features = ["v4", "js", "serde"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
console_error_panic_hook = "0.1.7"

View File

@ -1,7 +1,7 @@
[package]
name = "derive-docs"
description = "A tool for generating documentation from Rust derive macros"
version = "0.1.19"
version = "0.1.18"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -96,16 +96,10 @@ fn do_stdlib_inner(
}
if !ast.sig.generics.params.is_empty() {
if ast.sig.generics.params.iter().any(|generic_type| match generic_type {
syn::GenericParam::Lifetime(_) => false,
syn::GenericParam::Type(_) => true,
syn::GenericParam::Const(_) => true,
}) {
errors.push(Error::new_spanned(
&ast.sig.generics,
"Stdlib functions may not be generic over types or constants, only lifetimes.",
));
}
errors.push(Error::new_spanned(
&ast.sig.generics,
"generics are not permitted for stdlib functions",
));
}
if ast.sig.variadic.is_some() {
@ -656,12 +650,7 @@ impl Parse for ItemFnForSignature {
}
fn clean_ty_string(t: &str) -> (String, proc_macro2::TokenStream) {
let mut ty_string = t
.replace("& 'a", "")
.replace('&', "")
.replace("mut", "")
.replace("< 'a >", "")
.replace(' ', "");
let mut ty_string = t.replace('&', "").replace("mut", "").replace(' ', "");
if ty_string.starts_with("Args") {
ty_string = "Args".to_string();
}
@ -761,7 +750,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -795,7 +784,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default()).await.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
// Zoom to fit.
ctx.engine

View File

@ -35,56 +35,6 @@ fn test_get_inner_array_type() {
}
}
#[test]
fn test_args_with_refs() {
let (item, mut errors) = do_stdlib(
quote! {
name = "someFn",
},
quote! {
/// Docs
/// ```
/// someFn()
/// ```
fn someFn(
data: &'a str,
) -> i32 {
3
}
},
)
.unwrap();
if let Some(e) = errors.pop() {
panic!("{e}");
}
expectorate::assert_contents("tests/args_with_refs.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_args_with_lifetime() {
let (item, mut errors) = do_stdlib(
quote! {
name = "someFn",
},
quote! {
/// Docs
/// ```
/// someFn()
/// ```
fn someFn<'a>(
data: Foo<'a>,
) -> i32 {
3
}
},
)
.unwrap();
if let Some(e) = errors.pop() {
panic!("{e}");
}
expectorate::assert_contents("tests/args_with_lifetime.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_line_to() {
let (item, errors) = do_stdlib(
@ -114,6 +64,7 @@ fn test_stdlib_line_to() {
},
)
.unwrap();
let _expected = quote! {};
assert!(errors.is_empty());
expectorate::assert_contents("tests/lineTo.gen", &get_text_fmt(&item).unwrap());

View File

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

View File

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

View File

@ -16,7 +16,7 @@ mod test_examples_show {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -45,7 +45,7 @@ mod test_examples_show {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
@ -106,7 +106,7 @@ mod test_examples_show {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -135,7 +135,7 @@ mod test_examples_show {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),

View File

@ -16,7 +16,7 @@ mod test_examples_show {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -45,7 +45,7 @@ mod test_examples_show {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),

View File

@ -17,7 +17,7 @@ mod test_examples_my_func {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -47,7 +47,7 @@ mod test_examples_my_func {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
@ -108,7 +108,7 @@ mod test_examples_my_func {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -137,7 +137,7 @@ mod test_examples_my_func {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),

View File

@ -17,7 +17,7 @@ mod test_examples_line_to {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -47,7 +47,7 @@ mod test_examples_line_to {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
@ -108,7 +108,7 @@ mod test_examples_line_to {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -137,7 +137,7 @@ mod test_examples_line_to {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),

View File

@ -16,7 +16,7 @@ mod test_examples_min {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -45,7 +45,7 @@ mod test_examples_min {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
@ -106,7 +106,7 @@ mod test_examples_min {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -135,7 +135,7 @@ mod test_examples_min {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),

View File

@ -16,7 +16,7 @@ mod test_examples_show {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -45,7 +45,7 @@ mod test_examples_show {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),

View File

@ -16,7 +16,7 @@ mod test_examples_import {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -45,7 +45,7 @@ mod test_examples_import {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),

View File

@ -16,7 +16,7 @@ mod test_examples_import {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -45,7 +45,7 @@ mod test_examples_import {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),

View File

@ -16,7 +16,7 @@ mod test_examples_import {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -45,7 +45,7 @@ mod test_examples_import {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),

View File

@ -16,7 +16,7 @@ mod test_examples_show {
settings: Default::default(),
is_mock: true,
};
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
@ -45,7 +45,7 @@ mod test_examples_show {
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.run(program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),

Some files were not shown because too many files have changed in this diff Show More