Compare commits
23 Commits
jtran/fix-
...
kcl-71
Author | SHA1 | Date | |
---|---|---|---|
d3a4fd8b55 | |||
2be7107cca | |||
94f194a984 | |||
4fe880a970 | |||
8f5fbfc273 | |||
e660f52bb0 | |||
d74fdd9369 | |||
334145f0be | |||
c24073b6ae | |||
078b7f3bf7 | |||
3d65676ccb | |||
ce566fb6e5 | |||
b23fc9f623 | |||
5c2dfb8e40 | |||
0e341d7863 | |||
6a03ff9596 | |||
d7bd0c937d | |||
d3b2483f4f | |||
7838b7c9fd | |||
130ecf1f88 | |||
550d8b3753 | |||
696222a070 | |||
edb424988d |
38
.github/workflows/e2e-tests.yml
vendored
38
.github/workflows/e2e-tests.yml
vendored
@ -40,7 +40,7 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|
||||||
- name: Download Wasm Cache
|
- name: Download Wasm cache
|
||||||
id: download-wasm
|
id: download-wasm
|
||||||
if: ${{ github.event_name != 'schedule' && steps.filter.outputs.rust == 'false' }}
|
if: ${{ github.event_name != 'schedule' && steps.filter.outputs.rust == 'false' }}
|
||||||
uses: dawidd6/action-download-artifact@v7
|
uses: dawidd6/action-download-artifact@v7
|
||||||
@ -52,7 +52,7 @@ jobs:
|
|||||||
branch: main
|
branch: main
|
||||||
path: rust/kcl-wasm-lib/pkg
|
path: rust/kcl-wasm-lib/pkg
|
||||||
|
|
||||||
- name: Build WASM condition
|
- name: Build Wasm condition
|
||||||
id: wasm
|
id: wasm
|
||||||
run: |
|
run: |
|
||||||
set -euox pipefail
|
set -euox pipefail
|
||||||
@ -70,7 +70,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||||
|
|
||||||
- name: Install rust
|
- name: Install Rust
|
||||||
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
@ -81,7 +81,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
tool: wasm-pack
|
tool: wasm-pack
|
||||||
|
|
||||||
- name: Rust Cache
|
- name: Use Rust cache
|
||||||
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
@ -117,7 +117,7 @@ jobs:
|
|||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
name: prepared-wasm
|
name: prepared-wasm
|
||||||
|
|
||||||
- name: Copy prepared wasm
|
- name: Copy prepared Wasm
|
||||||
run: |
|
run: |
|
||||||
ls -R prepared-wasm
|
ls -R prepared-wasm
|
||||||
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||||
@ -133,20 +133,17 @@ jobs:
|
|||||||
id: deps-install
|
id: deps-install
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|
||||||
- name: Cache Playwright Browsers
|
- name: Cache browsers
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/ms-playwright/
|
~/.cache/ms-playwright/
|
||||||
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
|
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
|
||||||
|
|
||||||
- name: Install Playwright Browsers
|
- name: Install browsers
|
||||||
run: npm run playwright install --with-deps
|
run: npm run playwright install --with-deps
|
||||||
|
|
||||||
- name: build web
|
- name: Capture snapshots
|
||||||
run: npm run tronb:vite:dev
|
|
||||||
|
|
||||||
- name: Run ubuntu/chrome snapshots
|
|
||||||
uses: nick-fields/retry@v3.0.2
|
uses: nick-fields/retry@v3.0.2
|
||||||
with:
|
with:
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -170,7 +167,7 @@ jobs:
|
|||||||
retention-days: 30
|
retention-days: 30
|
||||||
overwrite: true
|
overwrite: true
|
||||||
|
|
||||||
- name: Check for changes
|
- name: Check diff
|
||||||
if: ${{ github.ref != 'refs/heads/main' }}
|
if: ${{ github.ref != 'refs/heads/main' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
id: git-check
|
id: git-check
|
||||||
@ -181,9 +178,8 @@ jobs:
|
|||||||
else echo "modified=false" >> $GITHUB_OUTPUT
|
else echo "modified=false" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Commit changes, if any
|
- name: Commit changes
|
||||||
# TODO: find a more reliable way to detect visual changes
|
if: ${{ steps.git-check.outputs.modified == 'true' }}
|
||||||
if: ${{ false && steps.git-check.outputs.modified == 'true' }}
|
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
||||||
@ -193,7 +189,7 @@ jobs:
|
|||||||
git fetch origin
|
git fetch origin
|
||||||
echo ${{ github.head_ref }}
|
echo ${{ github.head_ref }}
|
||||||
git checkout ${{ github.head_ref }}
|
git checkout ${{ github.head_ref }}
|
||||||
git commit -m "A snapshot a day keeps the bugs away! 📷🐛" || true
|
git commit --message "Update snapshots" || true
|
||||||
git push
|
git push
|
||||||
git push origin ${{ github.head_ref }}
|
git push origin ${{ github.head_ref }}
|
||||||
|
|
||||||
@ -234,10 +230,16 @@ jobs:
|
|||||||
shardTotal: 8
|
shardTotal: 8
|
||||||
- os: namespace-profile-macos-8-cores
|
- os: namespace-profile-macos-8-cores
|
||||||
shardIndex: 1
|
shardIndex: 1
|
||||||
shardTotal: 1
|
shardTotal: 2
|
||||||
|
- os: namespace-profile-macos-8-cores
|
||||||
|
shardIndex: 2
|
||||||
|
shardTotal: 2
|
||||||
- os: windows-latest-8-cores
|
- os: windows-latest-8-cores
|
||||||
shardIndex: 1
|
shardIndex: 1
|
||||||
shardTotal: 1
|
shardTotal: 2
|
||||||
|
- os: windows-latest-8-cores
|
||||||
|
shardIndex: 2
|
||||||
|
shardTotal: 2
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -158,10 +158,14 @@ extrude001 = extrude(sketch001, length = 5)`
|
|||||||
await expect(
|
await expect(
|
||||||
page
|
page
|
||||||
.getByText(
|
.getByText(
|
||||||
'Modeling command failed: [ApiError { error_code: InternalEngine, message: "Solid3D revolve failed: sketch profile must lie entirely on one side of the revolution axis" }]'
|
'Solid3D revolve failed: sketch profile must lie entirely on one side of the revolution axis'
|
||||||
)
|
)
|
||||||
.first()
|
.first()
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
|
|
||||||
|
// Make sure ApiError is not on the page.
|
||||||
|
// This ensures we didn't nest the json
|
||||||
|
await expect(page.getByText('ApiError')).not.toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('When error is not in view WITH LINTS you can click the badge to scroll to it', async ({
|
test('When error is not in view WITH LINTS you can click the badge to scroll to it', async ({
|
||||||
|
@ -58,12 +58,6 @@ test(
|
|||||||
await expect(submitButton).toBeVisible()
|
await expect(submitButton).toBeVisible()
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Look out for the toast message
|
|
||||||
const exportingToastMessage = page.getByText(`Exporting...`)
|
|
||||||
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
|
||||||
await expect(exportingToastMessage).toBeVisible()
|
|
||||||
await expect(alreadyExportingToastMessage).not.toBeVisible()
|
|
||||||
|
|
||||||
// Expect it to succeed
|
// Expect it to succeed
|
||||||
const errorToastMessage = page.getByText(`Error while exporting`)
|
const errorToastMessage = page.getByText(`Error while exporting`)
|
||||||
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
||||||
@ -72,7 +66,6 @@ test(
|
|||||||
|
|
||||||
const successToastMessage = page.getByText(`Exported successfully`)
|
const successToastMessage = page.getByText(`Exported successfully`)
|
||||||
await expect(successToastMessage).toBeVisible()
|
await expect(successToastMessage).toBeVisible()
|
||||||
await expect(exportingToastMessage).not.toBeVisible()
|
|
||||||
|
|
||||||
// Check for the exported file
|
// Check for the exported file
|
||||||
const firstFileFullPath = path.resolve(
|
const firstFileFullPath = path.resolve(
|
||||||
|
@ -155,6 +155,12 @@ export class CmdBarFixture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeCmdBar = async () => {
|
||||||
|
const cmdBarCloseBtn = this.page.getByTestId('command-bar-close-button')
|
||||||
|
await cmdBarCloseBtn.click()
|
||||||
|
await expect(this.cmdBarElement).not.toBeVisible()
|
||||||
|
}
|
||||||
|
|
||||||
get cmdSearchInput() {
|
get cmdSearchInput() {
|
||||||
return this.page.getByTestId('cmd-bar-search')
|
return this.page.getByTestId('cmd-bar-search')
|
||||||
}
|
}
|
||||||
@ -298,4 +304,27 @@ export class CmdBarFixture {
|
|||||||
`Monitoring text-to-cad API requests. Output will be saved to: ${outputPath}`
|
`Monitoring text-to-cad API requests. Output will be saved to: ${outputPath}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async toBeOpened() {
|
||||||
|
// Check that the command bar is opened
|
||||||
|
await expect(this.cmdBarElement).toBeVisible({ timeout: 10_000 })
|
||||||
|
}
|
||||||
|
|
||||||
|
async expectArgValue(value: string) {
|
||||||
|
// Check the placeholder project name exists
|
||||||
|
const actualArgument = await this.cmdBarElement
|
||||||
|
.getByTestId('cmd-bar-arg-value')
|
||||||
|
.inputValue()
|
||||||
|
const expectedArgument = value
|
||||||
|
expect(actualArgument).toBe(expectedArgument)
|
||||||
|
}
|
||||||
|
|
||||||
|
async expectCommandName(value: string) {
|
||||||
|
// Check the placeholder project name exists
|
||||||
|
const actual = await this.cmdBarElement
|
||||||
|
.getByTestId('command-name')
|
||||||
|
.textContent()
|
||||||
|
const expected = value
|
||||||
|
expect(actual).toBe(expected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ export class HomePageFixture {
|
|||||||
projectTextName!: Locator
|
projectTextName!: Locator
|
||||||
sortByDateBtn!: Locator
|
sortByDateBtn!: Locator
|
||||||
sortByNameBtn!: Locator
|
sortByNameBtn!: Locator
|
||||||
|
appHeader!: Locator
|
||||||
tutorialBtn!: Locator
|
tutorialBtn!: Locator
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
@ -44,6 +45,7 @@ export class HomePageFixture {
|
|||||||
|
|
||||||
this.sortByDateBtn = this.page.getByTestId('home-sort-by-modified')
|
this.sortByDateBtn = this.page.getByTestId('home-sort-by-modified')
|
||||||
this.sortByNameBtn = this.page.getByTestId('home-sort-by-name')
|
this.sortByNameBtn = this.page.getByTestId('home-sort-by-name')
|
||||||
|
this.appHeader = this.page.getByTestId('app-header')
|
||||||
this.tutorialBtn = this.page.getByTestId('home-tutorial-button')
|
this.tutorialBtn = this.page.getByTestId('home-tutorial-button')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,4 +127,11 @@ export class HomePageFixture {
|
|||||||
|
|
||||||
await this.createAndGoToProject(name)
|
await this.createAndGoToProject(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isNativeFileMenuCreated = async () => {
|
||||||
|
await expect(this.appHeader).toHaveAttribute(
|
||||||
|
'data-native-file-menu',
|
||||||
|
'true'
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ export class SceneFixture {
|
|||||||
public networkToggleConnected!: Locator
|
public networkToggleConnected!: Locator
|
||||||
public engineConnectionsSpinner!: Locator
|
public engineConnectionsSpinner!: Locator
|
||||||
public startEditSketchBtn!: Locator
|
public startEditSketchBtn!: Locator
|
||||||
|
public appHeader!: Locator
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page
|
this.page = page
|
||||||
@ -57,6 +58,7 @@ export class SceneFixture {
|
|||||||
this.startEditSketchBtn = page
|
this.startEditSketchBtn = page
|
||||||
.getByRole('button', { name: 'Start Sketch' })
|
.getByRole('button', { name: 'Start Sketch' })
|
||||||
.or(page.getByRole('button', { name: 'Edit Sketch' }))
|
.or(page.getByRole('button', { name: 'Edit Sketch' }))
|
||||||
|
this.appHeader = this.page.getByTestId('app-header')
|
||||||
}
|
}
|
||||||
private _serialiseScene = async (): Promise<SceneSerialised> => {
|
private _serialiseScene = async (): Promise<SceneSerialised> => {
|
||||||
const camera = await this.getCameraInfo()
|
const camera = await this.getCameraInfo()
|
||||||
@ -280,6 +282,13 @@ export class SceneFixture {
|
|||||||
await expect(buttonToTest).toBeVisible()
|
await expect(buttonToTest).toBeVisible()
|
||||||
await buttonToTest.click()
|
await buttonToTest.click()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isNativeFileMenuCreated = async () => {
|
||||||
|
await expect(this.appHeader).toHaveAttribute(
|
||||||
|
'data-native-file-menu',
|
||||||
|
'true'
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isColourArray(
|
function isColourArray(
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -51,8 +51,11 @@ test.describe('Regression tests', () => {
|
|||||||
// the close doesn't work
|
// the close doesn't work
|
||||||
// when https://github.com/KittyCAD/modeling-app/issues/3268 is closed
|
// when https://github.com/KittyCAD/modeling-app/issues/3268 is closed
|
||||||
// this test will need updating
|
// this test will need updating
|
||||||
const crypticErrorText = `ApiError`
|
const crypticErrorText = `Cannot close a path that is non-planar or with duplicate vertices.
|
||||||
|
Internal engine error on request`
|
||||||
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
|
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
|
||||||
|
// Ensure we didn't nest the json.
|
||||||
|
await expect(page.getByText('ApiError')).not.toBeVisible()
|
||||||
})
|
})
|
||||||
test('user should not have to press down twice in cmdbar', async ({
|
test('user should not have to press down twice in cmdbar', async ({
|
||||||
page,
|
page,
|
||||||
@ -545,7 +548,8 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
expect(alreadyExportingToastMessage).not.toBeVisible(),
|
expect(alreadyExportingToastMessage).not.toBeVisible(),
|
||||||
])
|
])
|
||||||
|
|
||||||
await expect(successToastMessage).toHaveCount(2)
|
const count = await successToastMessage.count()
|
||||||
|
await expect(count).toBeGreaterThanOrEqual(2)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -3496,6 +3496,73 @@ profile001 = startProfile(sketch001, at = [-102.72, 237.44])
|
|||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Ensure feature tree is not showing previous file's content when switching to a file with KCL errors.
|
||||||
|
test('Feature tree shows correct sketch count per file', async ({
|
||||||
|
context,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
toolbar,
|
||||||
|
cmdBar,
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
|
||||||
|
// Setup project with files.
|
||||||
|
const GOOD_KCL = `sketch001 = startSketchOn(XZ)
|
||||||
|
profile001 = startProfile(sketch001, at = [220.81, 253.8])
|
||||||
|
|> line(end = [132.84, -151.31])
|
||||||
|
|> line(end = [25.51, 167.15])
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|
|> close()
|
||||||
|
sketch002 = startSketchOn(XZ)
|
||||||
|
profile002 = startProfile(sketch002, at = [158.35, -70.82])
|
||||||
|
|> line(end = [73.9, -152.19])
|
||||||
|
|> line(end = [85.33, 135.48])
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|
|> close()`
|
||||||
|
|
||||||
|
const ERROR_KCL = `sketch001 = startSketchOn(XZ)
|
||||||
|
profile001 = startProfile(sketch001, at = [127.56, 179.02])
|
||||||
|
|> line(end = [132.84, -112.6])
|
||||||
|
|> line(end = [85.33, 234.01])
|
||||||
|
|> line(enfd = [-137.23, -54.55])`
|
||||||
|
|
||||||
|
await context.folderSetupFn(async (dir) => {
|
||||||
|
const projectDir = path.join(dir, 'multi-file-sketch-test')
|
||||||
|
await fs.mkdir(projectDir, { recursive: true })
|
||||||
|
await Promise.all([
|
||||||
|
fs.writeFile(path.join(projectDir, 'good.kcl'), GOOD_KCL, 'utf-8'),
|
||||||
|
fs.writeFile(path.join(projectDir, 'error.kcl'), ERROR_KCL, 'utf-8'),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
await page.setBodyDimensions({ width: 1000, height: 800 })
|
||||||
|
|
||||||
|
await homePage.openProject('multi-file-sketch-test')
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
|
await toolbar.openFeatureTreePane()
|
||||||
|
await toolbar.openPane('files')
|
||||||
|
|
||||||
|
await toolbar.openFile('good.kcl')
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
toolbar.featureTreePane.getByRole('button', { name: 'Sketch' })
|
||||||
|
).toHaveCount(2)
|
||||||
|
|
||||||
|
await toolbar.openFile('error.kcl')
|
||||||
|
|
||||||
|
// Ensure filetree is populated
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
toolbar.featureTreePane.getByRole('button', { name: 'Sketch' })
|
||||||
|
).toHaveCount(0)
|
||||||
|
})
|
||||||
|
|
||||||
test('adding a syntax error, recovers after fixing', async ({
|
test('adding a syntax error, recovers after fixing', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
|
|
||||||
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
||||||
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||||
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
|
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
|
||||||
@ -9,6 +8,7 @@ import {
|
|||||||
settingsToToml,
|
settingsToToml,
|
||||||
} from '@e2e/playwright/test-utils'
|
} from '@e2e/playwright/test-utils'
|
||||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
|
||||||
|
|
||||||
test.beforeEach(async ({ page, context }) => {
|
test.beforeEach(async ({ page, context }) => {
|
||||||
// Make the user avatar image always 404
|
// Make the user avatar image always 404
|
||||||
@ -873,6 +873,50 @@ sweepSketch = startSketchOn(XY)
|
|||||||
mask: lowerRightMasks(page),
|
mask: lowerRightMasks(page),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
test('code color goober works with single quotes', async ({
|
||||||
|
page,
|
||||||
|
context,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await context.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`// Create a pipe using a sweep.
|
||||||
|
|
||||||
|
// Create a path for the sweep.
|
||||||
|
sweepPath = startSketchOn(XZ)
|
||||||
|
|> startProfile(at = [0.05, 0.05])
|
||||||
|
|> line(end = [0, 7])
|
||||||
|
|> tangentialArc(angle = 90, radius = 5)
|
||||||
|
|> line(end = [-3, 0])
|
||||||
|
|> tangentialArc(angle = -90, radius = 5)
|
||||||
|
|> line(end = [0, 7])
|
||||||
|
|
||||||
|
sweepSketch = startSketchOn(XY)
|
||||||
|
|> startProfile(at = [2, 0])
|
||||||
|
|> arc(angleStart = 0, angleEnd = 360, radius = 2)
|
||||||
|
|> sweep(path = sweepPath)
|
||||||
|
|> appearance(
|
||||||
|
color = '#bb00ff',
|
||||||
|
metalness = 90,
|
||||||
|
roughness = 90
|
||||||
|
)
|
||||||
|
`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await page.setViewportSize({ width: 1200, height: 1000 })
|
||||||
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await expect(page, 'expect small color widget').toHaveScreenshot({
|
||||||
|
maxDiffPixels: 100,
|
||||||
|
mask: lowerRightMasks(page),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test('code color goober opening window', async ({
|
test('code color goober opening window', async ({
|
||||||
page,
|
page,
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 132 KiB |
@ -21,6 +21,7 @@ export const token = process.env.token || ''
|
|||||||
|
|
||||||
import type { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
|
import type { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
|
||||||
|
|
||||||
|
import type { ElectronZoo } from '@e2e/playwright/fixtures/fixtureSetup'
|
||||||
import { isErrorWhitelisted } from '@e2e/playwright/lib/console-error-whitelist'
|
import { isErrorWhitelisted } from '@e2e/playwright/lib/console-error-whitelist'
|
||||||
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
|
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
|
||||||
import { test } from '@e2e/playwright/zoo-test'
|
import { test } from '@e2e/playwright/zoo-test'
|
||||||
@ -1149,3 +1150,77 @@ export function perProjectSettingsToToml(
|
|||||||
// eslint-disable-next-line no-restricted-syntax
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
return TOML.stringify(settings as any)
|
return TOML.stringify(settings as any)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function clickElectronNativeMenuById(
|
||||||
|
tronApp: ElectronZoo,
|
||||||
|
menuId: string
|
||||||
|
) {
|
||||||
|
const clickWasTriggered = await tronApp.electron.evaluate(
|
||||||
|
async ({ app }, menuId) => {
|
||||||
|
if (!app || !app.applicationMenu) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const menu = app.applicationMenu.getMenuItemById(menuId)
|
||||||
|
if (!menu) return false
|
||||||
|
menu.click()
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
menuId
|
||||||
|
)
|
||||||
|
expect(clickWasTriggered).toBe(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function findElectronNativeMenuById(
|
||||||
|
tronApp: ElectronZoo,
|
||||||
|
menuId: string
|
||||||
|
) {
|
||||||
|
const found = await tronApp.electron.evaluate(async ({ app }, menuId) => {
|
||||||
|
if (!app || !app.applicationMenu) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const menu = app.applicationMenu.getMenuItemById(menuId)
|
||||||
|
if (!menu) return false
|
||||||
|
return true
|
||||||
|
}, menuId)
|
||||||
|
expect(found).toBe(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function openSettingsExpectText(page: Page, text: string) {
|
||||||
|
const settings = page.getByTestId('settings-dialog-panel')
|
||||||
|
await expect(settings).toBeVisible()
|
||||||
|
// You are viewing the user tab
|
||||||
|
const actualText = settings.getByText(text)
|
||||||
|
await expect(actualText).toBeVisible()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function openSettingsExpectLocator(page: Page, selector: string) {
|
||||||
|
const settings = page.getByTestId('settings-dialog-panel')
|
||||||
|
await expect(settings).toBeVisible()
|
||||||
|
// You are viewing the keybindings tab
|
||||||
|
const settingsLocator = settings.locator(selector)
|
||||||
|
await expect(settingsLocator).toBeVisible()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A developer helper function to make playwright send all the console logs to stdout
|
||||||
|
* Call this within your E2E test and pass in the page or the tronApp to get as many
|
||||||
|
* logs piped to stdout for debugging
|
||||||
|
*/
|
||||||
|
export async function enableConsoleLogEverything({
|
||||||
|
page,
|
||||||
|
tronApp,
|
||||||
|
}: { page?: Page; tronApp?: ElectronZoo }) {
|
||||||
|
page?.on('console', (msg) => {
|
||||||
|
console.log(`[Page-log]: ${msg.text()}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
tronApp?.electron.on('window', async (electronPage) => {
|
||||||
|
electronPage.on('console', (msg) => {
|
||||||
|
console.log(`[Renderer] ${msg.type()}: ${msg.text()}`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
tronApp?.electron.on('console', (msg) => {
|
||||||
|
console.log(`[Main] ${msg.type()}: ${msg.text()}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -57,9 +57,9 @@ fn connectorSketch(@plane, start) {
|
|||||||
|
|
||||||
export fn connector(@plane, length) {
|
export fn connector(@plane, length) {
|
||||||
connectorSketch(plane, start = [-12, 8])
|
connectorSketch(plane, start = [-12, 8])
|
||||||
|> extrude(length = length)
|
|> extrude(length)
|
||||||
connectorSketch(plane, start = [16, 8])
|
connectorSketch(plane, start = [16, 8])
|
||||||
|> extrude(length = length)
|
|> extrude(length)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ fn seatSlatSketch(@plane) {
|
|||||||
|
|
||||||
export fn seatSlats(@plane, length) {
|
export fn seatSlats(@plane, length) {
|
||||||
seatSlatSketch(plane)
|
seatSlatSketch(plane)
|
||||||
|> extrude(length = length)
|
|> extrude(length)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ fn backSlatsSketch(@plane) {
|
|||||||
|
|
||||||
export fn backSlats(@plane, length) {
|
export fn backSlats(@plane, length) {
|
||||||
b = backSlatsSketch(plane)
|
b = backSlatsSketch(plane)
|
||||||
|> extrude(length = length)
|
|> extrude(length)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ holeDia = 4
|
|||||||
sketch001 = startSketchOn(XY)
|
sketch001 = startSketchOn(XY)
|
||||||
|> startProfile(at = [0, 0])
|
|> startProfile(at = [0, 0])
|
||||||
|> angledLine(angle = 0, length = width, tag = $rectangleSegmentA001)
|
|> angledLine(angle = 0, length = width, tag = $rectangleSegmentA001)
|
||||||
|> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = length, tag = $rectangleSegmentB001)
|
|> angledLine(angle = segAng(rectangleSegmentA001) + 90, length, tag = $rectangleSegmentB001)
|
||||||
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001)
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001)
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001)
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001)
|
||||||
|> close()
|
|> close()
|
||||||
@ -74,7 +74,7 @@ function001([
|
|||||||
sketch003 = startSketchOn(XY)
|
sketch003 = startSketchOn(XY)
|
||||||
|> startProfile(at = [width * 1.2, 0])
|
|> startProfile(at = [width * 1.2, 0])
|
||||||
|> angledLine(angle = 0, length = width, tag = $rectangleSegmentA002)
|
|> angledLine(angle = 0, length = width, tag = $rectangleSegmentA002)
|
||||||
|> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = length, tag = $rectangleSegmentB002)
|
|> angledLine(angle = segAng(rectangleSegmentA001) + 90, length, tag = $rectangleSegmentB002)
|
||||||
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC002)
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC002)
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD002)
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD002)
|
||||||
|> close()
|
|> close()
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
[test-groups]
|
[test-groups]
|
||||||
# If a test uses the engine, we want to limit the number that can run in parallel.
|
# If a test uses the engine, we want to limit the number that can run in parallel.
|
||||||
# This way we don't start and stop too many engine instances, putting pressure on our cloud.
|
# This way we don't start and stop too many engine instances, putting pressure on our cloud.
|
||||||
uses-engine = { max-threads = 4 }
|
uses-engine = { max-threads = 32 }
|
||||||
# If a test must run after the engine tests, we want to make sure the engine tests are done first.
|
# If a test must run after the engine tests, we want to make sure the engine tests are done first.
|
||||||
after-engine = { max-threads = 12 }
|
after-engine = { max-threads = 32 }
|
||||||
|
|
||||||
[profile.default]
|
[profile.default]
|
||||||
slow-timeout = { period = "180s", terminate-after = 1 }
|
slow-timeout = { period = "280s", terminate-after = 1 }
|
||||||
|
|
||||||
[profile.ci]
|
[profile.ci]
|
||||||
slow-timeout = { period = "280s", terminate-after = 5 }
|
slow-timeout = { period = "280s", terminate-after = 5 }
|
||||||
|
24
rust/Cargo.lock
generated
24
rust/Cargo.lock
generated
@ -1815,7 +1815,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-bumper"
|
name = "kcl-bumper"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@ -1826,7 +1826,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-derive-docs"
|
name = "kcl-derive-docs"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Inflector",
|
"Inflector",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -1845,7 +1845,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-directory-test-macro"
|
name = "kcl-directory-test-macro"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1854,7 +1854,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-language-server"
|
name = "kcl-language-server"
|
||||||
version = "0.2.69"
|
version = "0.2.71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@ -1875,7 +1875,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-language-server-release"
|
name = "kcl-language-server-release"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@ -1895,7 +1895,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.2.69"
|
version = "0.2.71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"approx 0.5.1",
|
"approx 0.5.1",
|
||||||
@ -1971,7 +1971,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-python-bindings"
|
name = "kcl-python-bindings"
|
||||||
version = "0.3.69"
|
version = "0.3.71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"kcl-lib",
|
"kcl-lib",
|
||||||
@ -1986,7 +1986,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-test-server"
|
name = "kcl-test-server"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"hyper 0.14.32",
|
"hyper 0.14.32",
|
||||||
@ -1999,7 +1999,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-to-core"
|
name = "kcl-to-core"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -2013,7 +2013,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-wasm-lib"
|
name = "kcl-wasm-lib"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bson",
|
"bson",
|
||||||
@ -2080,9 +2080,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kittycad-modeling-cmds"
|
name = "kittycad-modeling-cmds"
|
||||||
version = "0.2.120"
|
version = "0.2.121"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "48b71e06ee5d711d0085864a756fb6a304531246689ea00c6ef5d740670c3701"
|
checksum = "94ba95c22493d79ec8a1faab963d8903f6de0e373efedf2bc3bb76a0ddbab036"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "kcl-bumper"
|
name = "kcl-bumper"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://github.com/KittyCAD/modeling-api"
|
repository = "https://github.com/KittyCAD/modeling-api"
|
||||||
rust-version = "1.76"
|
rust-version = "1.76"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-derive-docs"
|
name = "kcl-derive-docs"
|
||||||
description = "A tool for generating documentation from Rust derive macros"
|
description = "A tool for generating documentation from Rust derive macros"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-directory-test-macro"
|
name = "kcl-directory-test-macro"
|
||||||
description = "A tool for generating tests from a directory of kcl files"
|
description = "A tool for generating tests from a directory of kcl files"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-language-server-release"
|
name = "kcl-language-server-release"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||||
publish = false
|
publish = false
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
name = "kcl-language-server"
|
name = "kcl-language-server"
|
||||||
description = "A language server for KCL."
|
description = "A language server for KCL."
|
||||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||||
version = "0.2.69"
|
version = "0.2.71"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
description = "KittyCAD Language implementation and tools"
|
description = "KittyCAD Language implementation and tools"
|
||||||
version = "0.2.69"
|
version = "0.2.71"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
@ -953,36 +953,6 @@ sketch001 = startSketchOn(box, face = END)
|
|||||||
assert_out("revolve_on_edge", &result);
|
assert_out("revolve_on_edge", &result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
|
||||||
async fn kcl_test_revolve_on_edge_get_edge() {
|
|
||||||
let code = r#"box = startSketchOn(XY)
|
|
||||||
|> startProfile(at = [0, 0])
|
|
||||||
|> line(end = [0, 10])
|
|
||||||
|> line(end = [10, 0])
|
|
||||||
|> line(end = [0, -10], tag = $revolveAxis)
|
|
||||||
|> close()
|
|
||||||
|> extrude(length = 10)
|
|
||||||
|
|
||||||
sketch001 = startSketchOn(box, face = revolveAxis)
|
|
||||||
|> startProfile(at = [5, 10])
|
|
||||||
|> line(end = [0, -10])
|
|
||||||
|> line(end = [2, 0])
|
|
||||||
|> line(end = [0, 10])
|
|
||||||
|> close()
|
|
||||||
|> revolve(axis = revolveAxis, angle = 90)
|
|
||||||
|
|
||||||
"#;
|
|
||||||
|
|
||||||
let result = execute_and_snapshot(code, None).await;
|
|
||||||
|
|
||||||
result.unwrap_err();
|
|
||||||
//this fails right now, but slightly differently, lets just say its enough for it to fail - mike
|
|
||||||
//assert_eq!(
|
|
||||||
// result.err().unwrap().to_string(),
|
|
||||||
// r#"engine: KclErrorDetails { source_ranges: [SourceRange([346, 390, 0])], message: "Modeling command failed: [ApiError { error_code: InternalEngine, message: \"Solid3D revolve failed: sketch profile must lie entirely on one side of the revolution axis\" }]" }"#
|
|
||||||
//);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn kcl_test_revolve_on_face_circle_edge() {
|
async fn kcl_test_revolve_on_face_circle_edge() {
|
||||||
let code = r#"box = startSketchOn(XY)
|
let code = r#"box = startSketchOn(XY)
|
||||||
@ -1249,7 +1219,7 @@ secondSketch = startSketchOn(part001, face = '')
|
|||||||
let err = err.as_kcl_error().unwrap();
|
let err = err.as_kcl_error().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err.message(),
|
err.message(),
|
||||||
"The arg face was given, but it was the wrong type. It should be type FaceTag but it was string (text)"
|
"The arg face was given, but it was the wrong type. It should be type FaceTag but it was string"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1882,7 +1852,7 @@ someFunction('INVALID')
|
|||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.err().unwrap().to_string(),
|
result.err().unwrap().to_string(),
|
||||||
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([46, 55, 0]), SourceRange([60, 83, 0])], message: "This function expected the input argument to be Solid or Plane but it's actually of type string (text)" }"#
|
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([46, 55, 0]), SourceRange([60, 83, 0])], message: "This function expected the input argument to be Solid or Plane but it's actually of type string" }"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,6 +223,26 @@ impl EngineConnection {
|
|||||||
message: errors.iter().map(|e| e.message.clone()).collect::<Vec<_>>().join("\n"),
|
message: errors.iter().map(|e| e.message.clone()).collect::<Vec<_>>().join("\n"),
|
||||||
source_ranges: vec![source_range],
|
source_ranges: vec![source_range],
|
||||||
})
|
})
|
||||||
|
} else if let Ok(data) =
|
||||||
|
serde_json::from_str::<Vec<kittycad_modeling_cmds::websocket::FailureWebSocketResponse>>(&err_str)
|
||||||
|
{
|
||||||
|
if let Some(data) = data.first() {
|
||||||
|
// It could also be an array of responses.
|
||||||
|
KclError::Engine(KclErrorDetails {
|
||||||
|
message: data
|
||||||
|
.errors
|
||||||
|
.iter()
|
||||||
|
.map(|e| e.message.clone())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n"),
|
||||||
|
source_ranges: vec![source_range],
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
KclError::Engine(KclErrorDetails {
|
||||||
|
message: "Received empty response from engine".into(),
|
||||||
|
source_ranges: vec![source_range],
|
||||||
|
})
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
KclError::Engine(KclErrorDetails {
|
KclError::Engine(KclErrorDetails {
|
||||||
message: format!("Failed to wait for promise from send modeling command: {:?}", e),
|
message: format!("Failed to wait for promise from send modeling command: {:?}", e),
|
||||||
|
@ -764,7 +764,12 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
WebSocketResponse::Failure(fail) => {
|
WebSocketResponse::Failure(fail) => {
|
||||||
let _request_id = fail.request_id;
|
let _request_id = fail.request_id;
|
||||||
Err(KclError::Engine(KclErrorDetails {
|
Err(KclError::Engine(KclErrorDetails {
|
||||||
message: format!("Modeling command failed: {:?}", fail.errors),
|
message: fail
|
||||||
|
.errors
|
||||||
|
.iter()
|
||||||
|
.map(|e| e.message.clone())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n"),
|
||||||
source_ranges: vec![source_range],
|
source_ranges: vec![source_range],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -807,7 +812,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
return Err(KclError::Engine(KclErrorDetails {
|
return Err(KclError::Engine(KclErrorDetails {
|
||||||
message: format!("Modeling command failed: {:?}", errors),
|
message: errors.iter().map(|e| e.message.clone()).collect::<Vec<_>>().join("\n"),
|
||||||
source_ranges: vec![source_range],
|
source_ranges: vec![source_range],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -913,11 +913,9 @@ impl Node<MemberExpression> {
|
|||||||
}),
|
}),
|
||||||
(being_indexed, _, _) => {
|
(being_indexed, _, _) => {
|
||||||
let t = being_indexed.human_friendly_type();
|
let t = being_indexed.human_friendly_type();
|
||||||
let article = article_for(t);
|
let article = article_for(&t);
|
||||||
Err(KclError::Semantic(KclErrorDetails {
|
Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Only arrays can be indexed, but you're trying to index {article} {t}"),
|
||||||
"Only arrays and objects can be indexed, but you're trying to index {article} {t}"
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.clone().into()],
|
source_ranges: vec![self.clone().into()],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -1313,10 +1311,15 @@ impl Node<CallExpressionKw> {
|
|||||||
Some(l) => {
|
Some(l) => {
|
||||||
fn_args.insert(l.name.clone(), arg);
|
fn_args.insert(l.name.clone(), arg);
|
||||||
}
|
}
|
||||||
None => errors.push(arg),
|
None => {
|
||||||
|
if let Some(id) = arg_expr.arg.ident_name() {
|
||||||
|
fn_args.insert(id.to_owned(), arg);
|
||||||
|
} else {
|
||||||
|
errors.push(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let fn_args = fn_args; // remove mutability
|
|
||||||
|
|
||||||
// Evaluate the unlabeled first param, if any exists.
|
// Evaluate the unlabeled first param, if any exists.
|
||||||
let unlabeled = if let Some(ref arg_expr) = self.unlabeled {
|
let unlabeled = if let Some(ref arg_expr) = self.unlabeled {
|
||||||
@ -1325,12 +1328,15 @@ impl Node<CallExpressionKw> {
|
|||||||
let value = ctx
|
let value = ctx
|
||||||
.execute_expr(arg_expr, exec_state, &metadata, &[], StatementKind::Expression)
|
.execute_expr(arg_expr, exec_state, &metadata, &[], StatementKind::Expression)
|
||||||
.await?;
|
.await?;
|
||||||
Some(Arg::new(value, source_range))
|
|
||||||
|
let label = arg_expr.ident_name().map(str::to_owned);
|
||||||
|
|
||||||
|
Some((label, Arg::new(value, source_range)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let args = Args::new_kw(
|
let mut args = Args::new_kw(
|
||||||
KwArgs {
|
KwArgs {
|
||||||
unlabeled,
|
unlabeled,
|
||||||
labeled: fn_args,
|
labeled: fn_args,
|
||||||
@ -1349,6 +1355,20 @@ impl Node<CallExpressionKw> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let formals = func.args(false);
|
||||||
|
|
||||||
|
// If it's possible the input arg was meant to be labelled and we probably don't want to use
|
||||||
|
// it as the input arg, then treat it as labelled.
|
||||||
|
if let Some((Some(label), _)) = &args.kw_args.unlabeled {
|
||||||
|
if (formals.iter().all(|a| a.label_required) || exec_state.pipe_value().is_some())
|
||||||
|
&& formals.iter().any(|a| &a.name == label && a.label_required)
|
||||||
|
&& !args.kw_args.labeled.contains_key(label)
|
||||||
|
{
|
||||||
|
let (label, arg) = args.kw_args.unlabeled.take().unwrap();
|
||||||
|
args.kw_args.labeled.insert(label.unwrap(), arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "artifact-graph")]
|
#[cfg(feature = "artifact-graph")]
|
||||||
let op = if func.feature_tree_operation() {
|
let op = if func.feature_tree_operation() {
|
||||||
let op_labeled_args = args
|
let op_labeled_args = args
|
||||||
@ -1370,7 +1390,6 @@ impl Node<CallExpressionKw> {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let formals = func.args(false);
|
|
||||||
for (label, arg) in &args.kw_args.labeled {
|
for (label, arg) in &args.kw_args.labeled {
|
||||||
match formals.iter().find(|p| &p.name == label) {
|
match formals.iter().find(|p| &p.name == label) {
|
||||||
Some(p) => {
|
Some(p) => {
|
||||||
@ -1698,8 +1717,9 @@ impl Node<ObjectExpression> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn article_for(s: &str) -> &'static str {
|
fn article_for<S: AsRef<str>>(s: S) -> &'static str {
|
||||||
if s.starts_with(['a', 'e', 'i', 'o', 'u']) {
|
// '[' is included since it's an array.
|
||||||
|
if s.as_ref().starts_with(['a', 'e', 'i', 'o', 'u', '[']) {
|
||||||
"an"
|
"an"
|
||||||
} else {
|
} else {
|
||||||
"a"
|
"a"
|
||||||
@ -1709,10 +1729,9 @@ fn article_for(s: &str) -> &'static str {
|
|||||||
fn number_as_f64(v: &KclValue, source_range: SourceRange) -> Result<TyF64, KclError> {
|
fn number_as_f64(v: &KclValue, source_range: SourceRange) -> Result<TyF64, KclError> {
|
||||||
v.as_ty_f64().ok_or_else(|| {
|
v.as_ty_f64().ok_or_else(|| {
|
||||||
let actual_type = v.human_friendly_type();
|
let actual_type = v.human_friendly_type();
|
||||||
let article = article_for(actual_type);
|
|
||||||
KclError::Semantic(KclErrorDetails {
|
KclError::Semantic(KclErrorDetails {
|
||||||
source_ranges: vec![source_range],
|
source_ranges: vec![source_range],
|
||||||
message: format!("Expected a number, but found {article} {actual_type}",),
|
message: format!("Expected a number, but found {actual_type}",),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1867,6 +1886,21 @@ fn type_check_params_kw(
|
|||||||
args: &mut KwArgs,
|
args: &mut KwArgs,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
) -> Result<(), KclError> {
|
) -> Result<(), KclError> {
|
||||||
|
// If it's possible the input arg was meant to be labelled and we probably don't want to use
|
||||||
|
// it as the input arg, then treat it as labelled.
|
||||||
|
if let Some((Some(label), _)) = &args.unlabeled {
|
||||||
|
if (function_expression.params.iter().all(|p| p.labeled) || exec_state.pipe_value().is_some())
|
||||||
|
&& function_expression
|
||||||
|
.params
|
||||||
|
.iter()
|
||||||
|
.any(|p| &p.identifier.name == label && p.labeled)
|
||||||
|
&& !args.labeled.contains_key(label)
|
||||||
|
{
|
||||||
|
let (label, arg) = args.unlabeled.take().unwrap();
|
||||||
|
args.labeled.insert(label.unwrap(), arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (label, arg) in &mut args.labeled {
|
for (label, arg) in &mut args.labeled {
|
||||||
match function_expression.params.iter().find(|p| &p.identifier.name == label) {
|
match function_expression.params.iter().find(|p| &p.identifier.name == label) {
|
||||||
Some(p) => {
|
Some(p) => {
|
||||||
@ -1961,10 +1995,11 @@ fn type_check_params_kw(
|
|||||||
if let Some(arg) = &mut args.unlabeled {
|
if let Some(arg) = &mut args.unlabeled {
|
||||||
if let Some(p) = function_expression.params.iter().find(|p| !p.labeled) {
|
if let Some(p) = function_expression.params.iter().find(|p| !p.labeled) {
|
||||||
if let Some(ty) = &p.type_ {
|
if let Some(ty) = &p.type_ {
|
||||||
arg.value = arg
|
arg.1.value = arg
|
||||||
|
.1
|
||||||
.value
|
.value
|
||||||
.coerce(
|
.coerce(
|
||||||
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.source_range)
|
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.1.source_range)
|
||||||
.map_err(|e| KclError::Semantic(e.into()))?,
|
.map_err(|e| KclError::Semantic(e.into()))?,
|
||||||
exec_state,
|
exec_state,
|
||||||
)
|
)
|
||||||
@ -1976,9 +2011,9 @@ fn type_check_params_kw(
|
|||||||
.map(|n| format!("`{}`", n))
|
.map(|n| format!("`{}`", n))
|
||||||
.unwrap_or_else(|| "this function".to_owned()),
|
.unwrap_or_else(|| "this function".to_owned()),
|
||||||
ty.inner,
|
ty.inner,
|
||||||
arg.value.human_friendly_type()
|
arg.1.value.human_friendly_type()
|
||||||
),
|
),
|
||||||
source_ranges: vec![arg.source_range],
|
source_ranges: vec![arg.1.source_range],
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
@ -2141,10 +2176,11 @@ impl FunctionSource {
|
|||||||
if let Some(arg) = &mut args.kw_args.unlabeled {
|
if let Some(arg) = &mut args.kw_args.unlabeled {
|
||||||
if let Some(p) = ast.params.iter().find(|p| !p.labeled) {
|
if let Some(p) = ast.params.iter().find(|p| !p.labeled) {
|
||||||
if let Some(ty) = &p.type_ {
|
if let Some(ty) = &p.type_ {
|
||||||
arg.value = arg
|
arg.1.value = arg
|
||||||
|
.1
|
||||||
.value
|
.value
|
||||||
.coerce(
|
.coerce(
|
||||||
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.source_range)
|
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.1.source_range)
|
||||||
.map_err(|e| KclError::Semantic(e.into()))?,
|
.map_err(|e| KclError::Semantic(e.into()))?,
|
||||||
exec_state,
|
exec_state,
|
||||||
)
|
)
|
||||||
@ -2154,7 +2190,7 @@ impl FunctionSource {
|
|||||||
"The input argument of {} requires a value with type `{}`, but found {}",
|
"The input argument of {} requires a value with type `{}`, but found {}",
|
||||||
props.name,
|
props.name,
|
||||||
ty.inner,
|
ty.inner,
|
||||||
arg.value.human_friendly_type(),
|
arg.1.value.human_friendly_type(),
|
||||||
),
|
),
|
||||||
source_ranges: vec![callsite],
|
source_ranges: vec![callsite],
|
||||||
})
|
})
|
||||||
@ -2226,7 +2262,7 @@ impl FunctionSource {
|
|||||||
.kw_args
|
.kw_args
|
||||||
.unlabeled
|
.unlabeled
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|arg| OpArg::new(OpKclValue::from(&arg.value), arg.source_range)),
|
.map(|arg| OpArg::new(OpKclValue::from(&arg.1.value), arg.1.source_range)),
|
||||||
labeled_args: op_labeled_args,
|
labeled_args: op_labeled_args,
|
||||||
},
|
},
|
||||||
source_range: callsite,
|
source_range: callsite,
|
||||||
@ -2446,19 +2482,23 @@ arr1 = [42]: [number(cm)]
|
|||||||
a = 42: string
|
a = 42: string
|
||||||
"#;
|
"#;
|
||||||
let result = parse_execute(program).await;
|
let result = parse_execute(program).await;
|
||||||
assert!(result
|
let err = result.unwrap_err();
|
||||||
.unwrap_err()
|
assert!(
|
||||||
.to_string()
|
err.to_string()
|
||||||
.contains("could not coerce number value to type string"));
|
.contains("could not coerce number(default units) value to type string"),
|
||||||
|
"Expected error but found {err:?}"
|
||||||
|
);
|
||||||
|
|
||||||
let program = r#"
|
let program = r#"
|
||||||
a = 42: Plane
|
a = 42: Plane
|
||||||
"#;
|
"#;
|
||||||
let result = parse_execute(program).await;
|
let result = parse_execute(program).await;
|
||||||
assert!(result
|
let err = result.unwrap_err();
|
||||||
.unwrap_err()
|
assert!(
|
||||||
.to_string()
|
err.to_string()
|
||||||
.contains("could not coerce number value to type Plane"));
|
.contains("could not coerce number(default units) value to type Plane"),
|
||||||
|
"Expected error but found {err:?}"
|
||||||
|
);
|
||||||
|
|
||||||
let program = r#"
|
let program = r#"
|
||||||
arr = [0]: [string]
|
arr = [0]: [string]
|
||||||
@ -2467,7 +2507,7 @@ arr = [0]: [string]
|
|||||||
let err = result.unwrap_err();
|
let err = result.unwrap_err();
|
||||||
assert!(
|
assert!(
|
||||||
err.to_string()
|
err.to_string()
|
||||||
.contains("could not coerce array (list) value to type [string]"),
|
.contains("could not coerce [any; 1] value to type [string]"),
|
||||||
"Expected error but found {err:?}"
|
"Expected error but found {err:?}"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -2478,7 +2518,7 @@ mixedArr = [0, "a"]: [number(mm)]
|
|||||||
let err = result.unwrap_err();
|
let err = result.unwrap_err();
|
||||||
assert!(
|
assert!(
|
||||||
err.to_string()
|
err.to_string()
|
||||||
.contains("could not coerce array (list) value to type [number(mm)]"),
|
.contains("could not coerce [any; 2] value to type [number(mm)]"),
|
||||||
"Expected error but found {err:?}"
|
"Expected error but found {err:?}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -2663,13 +2703,12 @@ a = foo()
|
|||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_sensible_error_when_missing_equals_in_kwarg() {
|
async fn test_sensible_error_when_missing_equals_in_kwarg() {
|
||||||
for (i, call) in ["f(x=1,y)", "f(x=1,3,z)", "f(x=1,y,z=1)", "f(x=1, 3 + 4, z=1)"]
|
for (i, call) in ["f(x=1,3,0)", "f(x=1,3,z)", "f(x=1,0,z=1)", "f(x=1, 3 + 4, z)"]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
let program = format!(
|
let program = format!(
|
||||||
"fn foo() {{ return 0 }}
|
"fn foo() {{ return 0 }}
|
||||||
y = 42
|
|
||||||
z = 0
|
z = 0
|
||||||
fn f(x, y, z) {{ return 0 }}
|
fn f(x, y, z) {{ return 0 }}
|
||||||
{call}"
|
{call}"
|
||||||
@ -2689,9 +2728,10 @@ fn f(x, y, z) {{ return 0 }}
|
|||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn default_param_for_unlabeled() {
|
async fn default_param_for_unlabeled() {
|
||||||
// Tests that the input param for myExtrude is taken from the pipeline value.
|
// Tests that the input param for myExtrude is taken from the pipeline value and same-name
|
||||||
|
// keyword args.
|
||||||
let ast = r#"fn myExtrude(@sk, length) {
|
let ast = r#"fn myExtrude(@sk, length) {
|
||||||
return extrude(sk, length = length)
|
return extrude(sk, length)
|
||||||
}
|
}
|
||||||
sketch001 = startSketchOn(XY)
|
sketch001 = startSketchOn(XY)
|
||||||
|> circle(center = [0, 0], radius = 93.75)
|
|> circle(center = [0, 0], radius = 93.75)
|
||||||
@ -2701,6 +2741,18 @@ sketch001 = startSketchOn(XY)
|
|||||||
parse_execute(ast).await.unwrap();
|
parse_execute(ast).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn dont_use_unlabelled_as_input() {
|
||||||
|
// `length` should be used as the `length` argument to extrude, not the unlabelled input
|
||||||
|
let ast = r#"length = 10
|
||||||
|
startSketchOn(XY)
|
||||||
|
|> circle(center = [0, 0], radius = 93.75)
|
||||||
|
|> extrude(length)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
parse_execute(ast).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn ascription_in_binop() {
|
async fn ascription_in_binop() {
|
||||||
let ast = r#"foo = tan(0): number(rad) - 4deg"#;
|
let ast = r#"foo = tan(0): number(rad) - 4deg"#;
|
||||||
|
@ -280,7 +280,10 @@ impl KclValue {
|
|||||||
|
|
||||||
/// Human readable type name used in error messages. Should not be relied
|
/// Human readable type name used in error messages. Should not be relied
|
||||||
/// on for program logic.
|
/// on for program logic.
|
||||||
pub(crate) fn human_friendly_type(&self) -> &'static str {
|
pub(crate) fn human_friendly_type(&self) -> String {
|
||||||
|
if let Some(t) = self.principal_type() {
|
||||||
|
return t.to_string();
|
||||||
|
}
|
||||||
match self {
|
match self {
|
||||||
KclValue::Uuid { .. } => "Unique ID (uuid)",
|
KclValue::Uuid { .. } => "Unique ID (uuid)",
|
||||||
KclValue::TagDeclarator(_) => "TagDeclarator",
|
KclValue::TagDeclarator(_) => "TagDeclarator",
|
||||||
@ -314,6 +317,7 @@ impl KclValue {
|
|||||||
KclValue::Type { .. } => "type",
|
KclValue::Type { .. } => "type",
|
||||||
KclValue::KclNone { .. } => "None",
|
KclValue::KclNone { .. } => "None",
|
||||||
}
|
}
|
||||||
|
.to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_literal(literal: Node<Literal>, exec_state: &mut ExecState) -> Self {
|
pub(crate) fn from_literal(literal: Node<Literal>, exec_state: &mut ExecState) -> Self {
|
||||||
|
@ -1910,13 +1910,13 @@ notNull = !myNull
|
|||||||
"#;
|
"#;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_execute(code1).await.unwrap_err().message(),
|
parse_execute(code1).await.unwrap_err().message(),
|
||||||
"Cannot apply unary operator ! to non-boolean value: number",
|
"Cannot apply unary operator ! to non-boolean value: number(default units)",
|
||||||
);
|
);
|
||||||
|
|
||||||
let code2 = "notZero = !0";
|
let code2 = "notZero = !0";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_execute(code2).await.unwrap_err().message(),
|
parse_execute(code2).await.unwrap_err().message(),
|
||||||
"Cannot apply unary operator ! to non-boolean value: number",
|
"Cannot apply unary operator ! to non-boolean value: number(default units)",
|
||||||
);
|
);
|
||||||
|
|
||||||
let code3 = r#"
|
let code3 = r#"
|
||||||
@ -1924,7 +1924,7 @@ notEmptyString = !""
|
|||||||
"#;
|
"#;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_execute(code3).await.unwrap_err().message(),
|
parse_execute(code3).await.unwrap_err().message(),
|
||||||
"Cannot apply unary operator ! to non-boolean value: string (text)",
|
"Cannot apply unary operator ! to non-boolean value: string",
|
||||||
);
|
);
|
||||||
|
|
||||||
let code4 = r#"
|
let code4 = r#"
|
||||||
@ -1933,7 +1933,7 @@ notMember = !obj.a
|
|||||||
"#;
|
"#;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_execute(code4).await.unwrap_err().message(),
|
parse_execute(code4).await.unwrap_err().message(),
|
||||||
"Cannot apply unary operator ! to non-boolean value: number",
|
"Cannot apply unary operator ! to non-boolean value: number(default units)",
|
||||||
);
|
);
|
||||||
|
|
||||||
let code5 = "
|
let code5 = "
|
||||||
@ -1941,7 +1941,7 @@ a = []
|
|||||||
notArray = !a";
|
notArray = !a";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_execute(code5).await.unwrap_err().message(),
|
parse_execute(code5).await.unwrap_err().message(),
|
||||||
"Cannot apply unary operator ! to non-boolean value: array (list)",
|
"Cannot apply unary operator ! to non-boolean value: [any; 0]",
|
||||||
);
|
);
|
||||||
|
|
||||||
let code6 = "
|
let code6 = "
|
||||||
@ -1949,7 +1949,7 @@ x = {}
|
|||||||
notObject = !x";
|
notObject = !x";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_execute(code6).await.unwrap_err().message(),
|
parse_execute(code6).await.unwrap_err().message(),
|
||||||
"Cannot apply unary operator ! to non-boolean value: object",
|
"Cannot apply unary operator ! to non-boolean value: { }",
|
||||||
);
|
);
|
||||||
|
|
||||||
let code7 = "
|
let code7 = "
|
||||||
@ -1975,7 +1975,7 @@ notTagDeclarator = !myTagDeclarator";
|
|||||||
assert!(
|
assert!(
|
||||||
tag_declarator_err
|
tag_declarator_err
|
||||||
.message()
|
.message()
|
||||||
.starts_with("Cannot apply unary operator ! to non-boolean value: TagDeclarator"),
|
.starts_with("Cannot apply unary operator ! to non-boolean value: tag"),
|
||||||
"Actual error: {:?}",
|
"Actual error: {:?}",
|
||||||
tag_declarator_err
|
tag_declarator_err
|
||||||
);
|
);
|
||||||
@ -1989,7 +1989,7 @@ notTagIdentifier = !myTag";
|
|||||||
assert!(
|
assert!(
|
||||||
tag_identifier_err
|
tag_identifier_err
|
||||||
.message()
|
.message()
|
||||||
.starts_with("Cannot apply unary operator ! to non-boolean value: TagIdentifier"),
|
.starts_with("Cannot apply unary operator ! to non-boolean value: tag"),
|
||||||
"Actual error: {:?}",
|
"Actual error: {:?}",
|
||||||
tag_identifier_err
|
tag_identifier_err
|
||||||
);
|
);
|
||||||
|
@ -4220,8 +4220,8 @@ sketch001 = startSketchOn(XY)
|
|||||||
result,
|
result,
|
||||||
vec![tower_lsp::lsp_types::ColorInformation {
|
vec![tower_lsp::lsp_types::ColorInformation {
|
||||||
range: tower_lsp::lsp_types::Range {
|
range: tower_lsp::lsp_types::Range {
|
||||||
start: tower_lsp::lsp_types::Position { line: 4, character: 24 },
|
start: tower_lsp::lsp_types::Position { line: 4, character: 25 },
|
||||||
end: tower_lsp::lsp_types::Position { line: 4, character: 33 },
|
end: tower_lsp::lsp_types::Position { line: 4, character: 32 },
|
||||||
},
|
},
|
||||||
color: tower_lsp::lsp_types::Color {
|
color: tower_lsp::lsp_types::Color {
|
||||||
red: 1.0,
|
red: 1.0,
|
||||||
@ -4272,8 +4272,8 @@ sketch001 = startSketchOn(XY)
|
|||||||
result,
|
result,
|
||||||
vec![tower_lsp::lsp_types::ColorInformation {
|
vec![tower_lsp::lsp_types::ColorInformation {
|
||||||
range: tower_lsp::lsp_types::Range {
|
range: tower_lsp::lsp_types::Range {
|
||||||
start: tower_lsp::lsp_types::Position { line: 4, character: 24 },
|
start: tower_lsp::lsp_types::Position { line: 4, character: 25 },
|
||||||
end: tower_lsp::lsp_types::Position { line: 4, character: 33 },
|
end: tower_lsp::lsp_types::Position { line: 4, character: 32 },
|
||||||
},
|
},
|
||||||
color: tower_lsp::lsp_types::Color {
|
color: tower_lsp::lsp_types::Color {
|
||||||
red: 1.0,
|
red: 1.0,
|
||||||
@ -4291,8 +4291,8 @@ sketch001 = startSketchOn(XY)
|
|||||||
uri: "file:///test.kcl".try_into().unwrap(),
|
uri: "file:///test.kcl".try_into().unwrap(),
|
||||||
},
|
},
|
||||||
range: tower_lsp::lsp_types::Range {
|
range: tower_lsp::lsp_types::Range {
|
||||||
start: tower_lsp::lsp_types::Position { line: 4, character: 24 },
|
start: tower_lsp::lsp_types::Position { line: 4, character: 25 },
|
||||||
end: tower_lsp::lsp_types::Position { line: 4, character: 33 },
|
end: tower_lsp::lsp_types::Position { line: 4, character: 32 },
|
||||||
},
|
},
|
||||||
color: tower_lsp::lsp_types::Color {
|
color: tower_lsp::lsp_types::Color {
|
||||||
red: 1.0,
|
red: 1.0,
|
||||||
|
@ -186,7 +186,7 @@ impl<T> Node<T> {
|
|||||||
self.comment_start = start;
|
self.comment_start = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_ref<'a, U: 'a>(&'a self, f: fn(&'a T) -> U) -> Node<U> {
|
pub fn map_ref<'a, U: 'a>(&'a self, f: impl Fn(&'a T) -> U) -> Node<U> {
|
||||||
Node {
|
Node {
|
||||||
inner: f(&self.inner),
|
inner: f(&self.inner),
|
||||||
start: self.start,
|
start: self.start,
|
||||||
@ -438,8 +438,15 @@ impl Node<Program> {
|
|||||||
let add_color = |literal: &Node<Literal>| {
|
let add_color = |literal: &Node<Literal>| {
|
||||||
// Check if the string is a color.
|
// Check if the string is a color.
|
||||||
if let Some(c) = literal.value.is_color() {
|
if let Some(c) = literal.value.is_color() {
|
||||||
|
let source_range = literal.as_source_range();
|
||||||
|
// We subtract 1 from either side because of the "'s in the literal.
|
||||||
|
let fixed_source_range = SourceRange::new(
|
||||||
|
source_range.start() + 1,
|
||||||
|
source_range.end() - 1,
|
||||||
|
source_range.module_id(),
|
||||||
|
);
|
||||||
let color = ColorInformation {
|
let color = ColorInformation {
|
||||||
range: literal.as_source_range().to_lsp_range(code),
|
range: fixed_source_range.to_lsp_range(code),
|
||||||
color: tower_lsp::lsp_types::Color {
|
color: tower_lsp::lsp_types::Color {
|
||||||
red: c.r,
|
red: c.r,
|
||||||
green: c.g,
|
green: c.g,
|
||||||
@ -498,7 +505,11 @@ impl Node<Program> {
|
|||||||
crate::walk::walk(self, |node: crate::walk::Node<'a>| {
|
crate::walk::walk(self, |node: crate::walk::Node<'a>| {
|
||||||
match node {
|
match node {
|
||||||
crate::walk::Node::Literal(literal) => {
|
crate::walk::Node::Literal(literal) => {
|
||||||
if literal.start == pos_start && literal.end == pos_end && literal.value.is_color().is_some() {
|
// Account for the quotes in the literal.
|
||||||
|
if (literal.start + 1) == pos_start
|
||||||
|
&& (literal.end - 1) == pos_end
|
||||||
|
&& literal.value.is_color().is_some()
|
||||||
|
{
|
||||||
found.replace(true);
|
found.replace(true);
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
@ -1187,7 +1198,7 @@ impl Expr {
|
|||||||
|
|
||||||
pub fn ident_name(&self) -> Option<&str> {
|
pub fn ident_name(&self) -> Option<&str> {
|
||||||
match self {
|
match self {
|
||||||
Expr::Name(ident) => Some(&ident.name.name),
|
Expr::Name(name) => name.local_ident().map(|n| n.inner),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2371,7 +2382,7 @@ impl Name {
|
|||||||
|
|
||||||
pub fn local_ident(&self) -> Option<Node<&str>> {
|
pub fn local_ident(&self) -> Option<Node<&str>> {
|
||||||
if self.path.is_empty() && !self.abs_path {
|
if self.path.is_empty() && !self.abs_path {
|
||||||
Some(self.name.map_ref(|n| &n.name))
|
Some(self.name.map_ref(|n| &*n.name))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -2729,6 +2729,17 @@ fn ty(i: &mut TokenSlice) -> PResult<Token> {
|
|||||||
keyword(i, "type")
|
keyword(i, "type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn any_keyword(i: &mut TokenSlice) -> PResult<Token> {
|
||||||
|
any.try_map(|token: Token| match token.token_type {
|
||||||
|
TokenType::Keyword => Ok(token),
|
||||||
|
_ => Err(CompilationError::fatal(
|
||||||
|
token.as_source_range(),
|
||||||
|
"expected some reserved keyword".to_owned(),
|
||||||
|
)),
|
||||||
|
})
|
||||||
|
.parse_next(i)
|
||||||
|
}
|
||||||
|
|
||||||
fn keyword(i: &mut TokenSlice, expected: &str) -> PResult<Token> {
|
fn keyword(i: &mut TokenSlice, expected: &str) -> PResult<Token> {
|
||||||
any.try_map(|token: Token| match token.token_type {
|
any.try_map(|token: Token| match token.token_type {
|
||||||
TokenType::Keyword if token.value == expected => Ok(token),
|
TokenType::Keyword if token.value == expected => Ok(token),
|
||||||
@ -3143,12 +3154,14 @@ fn fn_call_kw(i: &mut TokenSlice) -> PResult<Node<CallExpressionKw>> {
|
|||||||
NonCode(Node<NonCodeNode>),
|
NonCode(Node<NonCodeNode>),
|
||||||
LabeledArg(LabeledArg),
|
LabeledArg(LabeledArg),
|
||||||
UnlabeledArg(Expr),
|
UnlabeledArg(Expr),
|
||||||
|
Keyword(Token),
|
||||||
}
|
}
|
||||||
let initial_unlabeled_arg = opt((expression, comma, opt(whitespace)).map(|(arg, _, _)| arg)).parse_next(i)?;
|
let initial_unlabeled_arg = opt((expression, comma, opt(whitespace)).map(|(arg, _, _)| arg)).parse_next(i)?;
|
||||||
let args: Vec<_> = repeat(
|
let args: Vec<_> = repeat(
|
||||||
0..,
|
0..,
|
||||||
alt((
|
alt((
|
||||||
terminated(non_code_node.map(ArgPlace::NonCode), whitespace),
|
terminated(non_code_node.map(ArgPlace::NonCode), whitespace),
|
||||||
|
terminated(any_keyword.map(ArgPlace::Keyword), whitespace),
|
||||||
terminated(labeled_argument, labeled_arg_separator).map(ArgPlace::LabeledArg),
|
terminated(labeled_argument, labeled_arg_separator).map(ArgPlace::LabeledArg),
|
||||||
expression.map(ArgPlace::UnlabeledArg),
|
expression.map(ArgPlace::UnlabeledArg),
|
||||||
)),
|
)),
|
||||||
@ -3164,6 +3177,18 @@ fn fn_call_kw(i: &mut TokenSlice) -> PResult<Node<CallExpressionKw>> {
|
|||||||
ArgPlace::LabeledArg(x) => {
|
ArgPlace::LabeledArg(x) => {
|
||||||
args.push(x);
|
args.push(x);
|
||||||
}
|
}
|
||||||
|
ArgPlace::Keyword(kw) => {
|
||||||
|
return Err(ErrMode::Cut(
|
||||||
|
CompilationError::fatal(
|
||||||
|
SourceRange::from(kw.clone()),
|
||||||
|
format!(
|
||||||
|
"`{}` is not the name of an argument (it's a reserved keyword)",
|
||||||
|
kw.value
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
ArgPlace::UnlabeledArg(arg) => {
|
ArgPlace::UnlabeledArg(arg) => {
|
||||||
let followed_by_equals = peek((opt(whitespace), equals)).parse_next(i).is_ok();
|
let followed_by_equals = peek((opt(whitespace), equals)).parse_next(i).is_ok();
|
||||||
if followed_by_equals {
|
if followed_by_equals {
|
||||||
@ -5055,6 +5080,30 @@ bar = 1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sensible_error_when_using_keyword_as_arg_label() {
|
||||||
|
for (i, program) in ["pow(2, fn = 8)"].into_iter().enumerate() {
|
||||||
|
let tokens = crate::parsing::token::lex(program, ModuleId::default()).unwrap();
|
||||||
|
let err = match fn_call_kw.parse(tokens.as_slice()) {
|
||||||
|
Err(e) => e,
|
||||||
|
Ok(ast) => {
|
||||||
|
eprintln!("{ast:#?}");
|
||||||
|
panic!("Expected this to error but it didn't");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let cause = err.inner().cause.as_ref().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
cause.message, "`fn` is not the name of an argument (it's a reserved keyword)",
|
||||||
|
"failed test {i}: {program}"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
cause.source_range.start(),
|
||||||
|
program.find("fn").unwrap(),
|
||||||
|
"failed test {i}: {program}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sensible_error_when_missing_rhs_of_obj_property() {
|
fn test_sensible_error_when_missing_rhs_of_obj_property() {
|
||||||
for (i, program) in ["{x = 1, y =}"].into_iter().enumerate() {
|
for (i, program) in ["{x = 1, y =}"].into_iter().enumerate() {
|
||||||
|
@ -1669,7 +1669,6 @@ mod mike_stress_test {
|
|||||||
|
|
||||||
/// Test that KCL is executed correctly.
|
/// Test that KCL is executed correctly.
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
#[ignore = "when kurt made the artifact graph lots of commands, this became super slow and sometimes the engine will just die, turn this back on when we can parallelize the simulation tests with snapshots deterministically"]
|
|
||||||
async fn kcl_test_execute() {
|
async fn kcl_test_execute() {
|
||||||
super::execute(TEST_NAME, true).await
|
super::execute(TEST_NAME, true).await
|
||||||
}
|
}
|
||||||
@ -2772,6 +2771,7 @@ mod clone_w_fillets {
|
|||||||
/// Test that KCL is executed correctly.
|
/// Test that KCL is executed correctly.
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
#[ignore] // turn on when https://github.com/KittyCAD/engine/pull/3380 is merged
|
#[ignore] // turn on when https://github.com/KittyCAD/engine/pull/3380 is merged
|
||||||
|
// Theres also a test in clone.rs you need to turn too
|
||||||
async fn kcl_test_execute() {
|
async fn kcl_test_execute() {
|
||||||
super::execute(TEST_NAME, true).await
|
super::execute(TEST_NAME, true).await
|
||||||
}
|
}
|
||||||
@ -3071,3 +3071,45 @@ mod error_inside_fn_also_has_source_range_of_call_site_recursive {
|
|||||||
super::execute(TEST_NAME, true).await
|
super::execute(TEST_NAME, true).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mod error_revolve_on_edge_get_edge {
|
||||||
|
const TEST_NAME: &str = "error_revolve_on_edge_get_edge";
|
||||||
|
|
||||||
|
/// Test parsing KCL.
|
||||||
|
#[test]
|
||||||
|
fn parse() {
|
||||||
|
super::parse(TEST_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that parsing and unparsing KCL produces the original KCL input.
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn unparse() {
|
||||||
|
super::unparse(TEST_NAME).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that KCL is executed correctly.
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn kcl_test_execute() {
|
||||||
|
super::execute(TEST_NAME, true).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mod sketch_on_face_union {
|
||||||
|
const TEST_NAME: &str = "sketch_on_face_union";
|
||||||
|
|
||||||
|
/// Test parsing KCL.
|
||||||
|
#[test]
|
||||||
|
fn parse() {
|
||||||
|
super::parse(TEST_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that parsing and unparsing KCL produces the original KCL input.
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn unparse() {
|
||||||
|
super::unparse(TEST_NAME).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that KCL is executed correctly.
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn kcl_test_execute() {
|
||||||
|
super::execute(TEST_NAME, true).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -59,7 +59,9 @@ impl Arg {
|
|||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct KwArgs {
|
pub struct KwArgs {
|
||||||
/// Unlabeled keyword args. Currently only the first arg can be unlabeled.
|
/// Unlabeled keyword args. Currently only the first arg can be unlabeled.
|
||||||
pub unlabeled: Option<Arg>,
|
/// If the argument was a local variable, then the first element of the tuple is its name
|
||||||
|
/// which may be used to treat this arg as a labelled arg.
|
||||||
|
pub unlabeled: Option<(Option<String>, Arg)>,
|
||||||
/// Labeled args.
|
/// Labeled args.
|
||||||
pub labeled: IndexMap<String, Arg>,
|
pub labeled: IndexMap<String, Arg>,
|
||||||
pub errors: Vec<Arg>,
|
pub errors: Vec<Arg>,
|
||||||
@ -257,14 +259,22 @@ impl Args {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let arg = arg.value.coerce(ty, exec_state).map_err(|_| {
|
let arg = arg.value.coerce(ty, exec_state).map_err(|_| {
|
||||||
let actual_type_name = arg.value.human_friendly_type();
|
let actual_type = arg.value.principal_type();
|
||||||
|
let actual_type_name = actual_type
|
||||||
|
.as_ref()
|
||||||
|
.map(|t| t.to_string())
|
||||||
|
.unwrap_or_else(|| arg.value.human_friendly_type().to_owned());
|
||||||
let msg_base = format!(
|
let msg_base = format!(
|
||||||
"This function expected the input argument to be {} but it's actually of type {actual_type_name}",
|
"This function expected the input argument to be {} but it's actually of type {actual_type_name}",
|
||||||
ty.human_friendly_type(),
|
ty.human_friendly_type(),
|
||||||
);
|
);
|
||||||
let suggestion = match (ty, actual_type_name) {
|
let suggestion = match (ty, actual_type) {
|
||||||
(RuntimeType::Primitive(PrimitiveType::Solid), "Sketch") => Some(ERROR_STRING_SKETCH_TO_SOLID_HELPER),
|
(RuntimeType::Primitive(PrimitiveType::Solid), Some(RuntimeType::Primitive(PrimitiveType::Sketch))) => {
|
||||||
(RuntimeType::Array(t, _), "Sketch") if **t == RuntimeType::Primitive(PrimitiveType::Solid) => {
|
Some(ERROR_STRING_SKETCH_TO_SOLID_HELPER)
|
||||||
|
}
|
||||||
|
(RuntimeType::Array(t, _), Some(RuntimeType::Primitive(PrimitiveType::Sketch)))
|
||||||
|
if **t == RuntimeType::Primitive(PrimitiveType::Solid) =>
|
||||||
|
{
|
||||||
Some(ERROR_STRING_SKETCH_TO_SOLID_HELPER)
|
Some(ERROR_STRING_SKETCH_TO_SOLID_HELPER)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -334,6 +344,7 @@ impl Args {
|
|||||||
self.kw_args
|
self.kw_args
|
||||||
.unlabeled
|
.unlabeled
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
.map(|(_, a)| a)
|
||||||
.or(self.args.first())
|
.or(self.args.first())
|
||||||
.or(self.pipe_value.as_ref())
|
.or(self.pipe_value.as_ref())
|
||||||
}
|
}
|
||||||
@ -381,14 +392,22 @@ impl Args {
|
|||||||
}))?;
|
}))?;
|
||||||
|
|
||||||
let arg = arg.value.coerce(ty, exec_state).map_err(|_| {
|
let arg = arg.value.coerce(ty, exec_state).map_err(|_| {
|
||||||
let actual_type_name = arg.value.human_friendly_type();
|
let actual_type = arg.value.principal_type();
|
||||||
|
let actual_type_name = actual_type
|
||||||
|
.as_ref()
|
||||||
|
.map(|t| t.to_string())
|
||||||
|
.unwrap_or_else(|| arg.value.human_friendly_type().to_owned());
|
||||||
let msg_base = format!(
|
let msg_base = format!(
|
||||||
"This function expected the input argument to be {} but it's actually of type {actual_type_name}",
|
"This function expected the input argument to be {} but it's actually of type {actual_type_name}",
|
||||||
ty.human_friendly_type(),
|
ty.human_friendly_type(),
|
||||||
);
|
);
|
||||||
let suggestion = match (ty, actual_type_name) {
|
let suggestion = match (ty, actual_type) {
|
||||||
(RuntimeType::Primitive(PrimitiveType::Solid), "Sketch") => Some(ERROR_STRING_SKETCH_TO_SOLID_HELPER),
|
(RuntimeType::Primitive(PrimitiveType::Solid), Some(RuntimeType::Primitive(PrimitiveType::Sketch))) => {
|
||||||
(RuntimeType::Array(ty, _), "Sketch") if **ty == RuntimeType::Primitive(PrimitiveType::Solid) => {
|
Some(ERROR_STRING_SKETCH_TO_SOLID_HELPER)
|
||||||
|
}
|
||||||
|
(RuntimeType::Array(ty, _), Some(RuntimeType::Primitive(PrimitiveType::Sketch)))
|
||||||
|
if **ty == RuntimeType::Primitive(PrimitiveType::Solid) =>
|
||||||
|
{
|
||||||
Some(ERROR_STRING_SKETCH_TO_SOLID_HELPER)
|
Some(ERROR_STRING_SKETCH_TO_SOLID_HELPER)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -48,7 +48,7 @@ async fn call_map_closure(
|
|||||||
ctxt: &ExecutorContext,
|
ctxt: &ExecutorContext,
|
||||||
) -> Result<KclValue, KclError> {
|
) -> Result<KclValue, KclError> {
|
||||||
let kw_args = KwArgs {
|
let kw_args = KwArgs {
|
||||||
unlabeled: Some(Arg::new(input, source_range)),
|
unlabeled: Some((None, Arg::new(input, source_range))),
|
||||||
labeled: Default::default(),
|
labeled: Default::default(),
|
||||||
errors: Vec::new(),
|
errors: Vec::new(),
|
||||||
};
|
};
|
||||||
@ -104,7 +104,7 @@ async fn call_reduce_closure(
|
|||||||
let mut labeled = IndexMap::with_capacity(1);
|
let mut labeled = IndexMap::with_capacity(1);
|
||||||
labeled.insert("accum".to_string(), Arg::new(accum, source_range));
|
labeled.insert("accum".to_string(), Arg::new(accum, source_range));
|
||||||
let kw_args = KwArgs {
|
let kw_args = KwArgs {
|
||||||
unlabeled: Some(Arg::new(elem, source_range)),
|
unlabeled: Some((None, Arg::new(elem, source_range))),
|
||||||
labeled,
|
labeled,
|
||||||
errors: Vec::new(),
|
errors: Vec::new(),
|
||||||
};
|
};
|
||||||
|
@ -177,25 +177,6 @@ async fn get_old_new_child_map(
|
|||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
args: &Args,
|
args: &Args,
|
||||||
) -> Result<HashMap<uuid::Uuid, uuid::Uuid>> {
|
) -> Result<HashMap<uuid::Uuid, uuid::Uuid>> {
|
||||||
// Get the new geometries entity ids.
|
|
||||||
let response = args
|
|
||||||
.send_modeling_cmd(
|
|
||||||
exec_state.next_uuid(),
|
|
||||||
ModelingCmd::from(mcmd::EntityGetAllChildUuids {
|
|
||||||
entity_id: new_geometry_id,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
let OkWebSocketResponseData::Modeling {
|
|
||||||
modeling_response:
|
|
||||||
OkModelingCmdResponse::EntityGetAllChildUuids(EntityGetAllChildUuids {
|
|
||||||
entity_ids: new_entity_ids,
|
|
||||||
}),
|
|
||||||
} = response
|
|
||||||
else {
|
|
||||||
anyhow::bail!("Expected EntityGetAllChildUuids response, got: {:?}", response);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get the old geometries entity ids.
|
// Get the old geometries entity ids.
|
||||||
let response = args
|
let response = args
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
@ -215,6 +196,25 @@ async fn get_old_new_child_map(
|
|||||||
anyhow::bail!("Expected EntityGetAllChildUuids response, got: {:?}", response);
|
anyhow::bail!("Expected EntityGetAllChildUuids response, got: {:?}", response);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Get the new geometries entity ids.
|
||||||
|
let response = args
|
||||||
|
.send_modeling_cmd(
|
||||||
|
exec_state.next_uuid(),
|
||||||
|
ModelingCmd::from(mcmd::EntityGetAllChildUuids {
|
||||||
|
entity_id: new_geometry_id,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let OkWebSocketResponseData::Modeling {
|
||||||
|
modeling_response:
|
||||||
|
OkModelingCmdResponse::EntityGetAllChildUuids(EntityGetAllChildUuids {
|
||||||
|
entity_ids: new_entity_ids,
|
||||||
|
}),
|
||||||
|
} = response
|
||||||
|
else {
|
||||||
|
anyhow::bail!("Expected EntityGetAllChildUuids response, got: {:?}", response);
|
||||||
|
};
|
||||||
|
|
||||||
// Create a map of old entity ids to new entity ids.
|
// Create a map of old entity ids to new entity ids.
|
||||||
Ok(HashMap::from_iter(
|
Ok(HashMap::from_iter(
|
||||||
old_entity_ids
|
old_entity_ids
|
||||||
|
@ -14,7 +14,7 @@ use super::{args::TyF64, DEFAULT_TOLERANCE};
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{types::RuntimeType, ExecState, KclValue, Solid},
|
execution::{types::RuntimeType, ExecState, KclValue, Solid},
|
||||||
std::Args,
|
std::{patterns::GeometryTrait, Args},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Union two or more solids into a single solid.
|
/// Union two or more solids into a single solid.
|
||||||
@ -123,7 +123,7 @@ pub(crate) async fn inner_union(
|
|||||||
let solid_out_id = exec_state.next_uuid();
|
let solid_out_id = exec_state.next_uuid();
|
||||||
|
|
||||||
let mut solid = solids[0].clone();
|
let mut solid = solids[0].clone();
|
||||||
solid.id = solid_out_id;
|
solid.set_id(solid_out_id);
|
||||||
let mut new_solids = vec![solid.clone()];
|
let mut new_solids = vec![solid.clone()];
|
||||||
|
|
||||||
if args.ctx.no_engine_commands().await {
|
if args.ctx.no_engine_commands().await {
|
||||||
@ -155,7 +155,7 @@ pub(crate) async fn inner_union(
|
|||||||
|
|
||||||
// If we have more solids, set those as well.
|
// If we have more solids, set those as well.
|
||||||
if !extra_solid_ids.is_empty() {
|
if !extra_solid_ids.is_empty() {
|
||||||
solid.id = extra_solid_ids[0];
|
solid.set_id(extra_solid_ids[0]);
|
||||||
new_solids.push(solid.clone());
|
new_solids.push(solid.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +249,7 @@ pub(crate) async fn inner_intersect(
|
|||||||
let solid_out_id = exec_state.next_uuid();
|
let solid_out_id = exec_state.next_uuid();
|
||||||
|
|
||||||
let mut solid = solids[0].clone();
|
let mut solid = solids[0].clone();
|
||||||
solid.id = solid_out_id;
|
solid.set_id(solid_out_id);
|
||||||
let mut new_solids = vec![solid.clone()];
|
let mut new_solids = vec![solid.clone()];
|
||||||
|
|
||||||
if args.ctx.no_engine_commands().await {
|
if args.ctx.no_engine_commands().await {
|
||||||
@ -281,7 +281,7 @@ pub(crate) async fn inner_intersect(
|
|||||||
|
|
||||||
// If we have more solids, set those as well.
|
// If we have more solids, set those as well.
|
||||||
if !extra_solid_ids.is_empty() {
|
if !extra_solid_ids.is_empty() {
|
||||||
solid.id = extra_solid_ids[0];
|
solid.set_id(extra_solid_ids[0]);
|
||||||
new_solids.push(solid.clone());
|
new_solids.push(solid.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,7 +385,7 @@ pub(crate) async fn inner_subtract(
|
|||||||
let solid_out_id = exec_state.next_uuid();
|
let solid_out_id = exec_state.next_uuid();
|
||||||
|
|
||||||
let mut solid = solids[0].clone();
|
let mut solid = solids[0].clone();
|
||||||
solid.id = solid_out_id;
|
solid.set_id(solid_out_id);
|
||||||
let mut new_solids = vec![solid.clone()];
|
let mut new_solids = vec![solid.clone()];
|
||||||
|
|
||||||
if args.ctx.no_engine_commands().await {
|
if args.ctx.no_engine_commands().await {
|
||||||
@ -419,7 +419,7 @@ pub(crate) async fn inner_subtract(
|
|||||||
|
|
||||||
// If we have more solids, set those as well.
|
// If we have more solids, set those as well.
|
||||||
if !extra_solid_ids.is_empty() {
|
if !extra_solid_ids.is_empty() {
|
||||||
solid.id = extra_solid_ids[0];
|
solid.set_id(extra_solid_ids[0]);
|
||||||
new_solids.push(solid.clone());
|
new_solids.push(solid.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,7 +424,7 @@ async fn make_transform<T: GeometryTrait>(
|
|||||||
meta: vec![source_range.into()],
|
meta: vec![source_range.into()],
|
||||||
};
|
};
|
||||||
let kw_args = KwArgs {
|
let kw_args = KwArgs {
|
||||||
unlabeled: Some(Arg::new(repetition_num, source_range)),
|
unlabeled: Some((None, Arg::new(repetition_num, source_range))),
|
||||||
labeled: Default::default(),
|
labeled: Default::default(),
|
||||||
errors: Vec::new(),
|
errors: Vec::new(),
|
||||||
};
|
};
|
||||||
@ -598,7 +598,7 @@ fn array_to_point2d(
|
|||||||
.map(|val| val.as_point2d().unwrap())
|
.map(|val| val.as_point2d().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
trait GeometryTrait: Clone {
|
pub trait GeometryTrait: Clone {
|
||||||
type Set: Into<Vec<Self>> + Clone;
|
type Set: Into<Vec<Self>> + Clone;
|
||||||
fn id(&self) -> Uuid;
|
fn id(&self) -> Uuid;
|
||||||
fn original_id(&self) -> Uuid;
|
fn original_id(&self) -> Uuid;
|
||||||
@ -608,6 +608,7 @@ trait GeometryTrait: Clone {
|
|||||||
source_ranges: Vec<SourceRange>,
|
source_ranges: Vec<SourceRange>,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
) -> Result<[TyF64; 3], KclError>;
|
) -> Result<[TyF64; 3], KclError>;
|
||||||
|
#[allow(async_fn_in_trait)]
|
||||||
async fn flush_batch(args: &Args, exec_state: &mut ExecState, set: &Self::Set) -> Result<(), KclError>;
|
async fn flush_batch(args: &Args, exec_state: &mut ExecState, set: &Self::Set) -> Result<(), KclError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,6 +642,8 @@ impl GeometryTrait for Solid {
|
|||||||
type Set = Vec<Solid>;
|
type Set = Vec<Solid>;
|
||||||
fn set_id(&mut self, id: Uuid) {
|
fn set_id(&mut self, id: Uuid) {
|
||||||
self.id = id;
|
self.id = id;
|
||||||
|
// We need this for in extrude.rs when you sketch on face.
|
||||||
|
self.sketch.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id(&self) -> Uuid {
|
fn id(&self) -> Uuid {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcl_derive_docs::stdlib;
|
use kcl_derive_docs::stdlib;
|
||||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
|
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
|
||||||
use kittycad_modeling_cmds::{self as kcmc};
|
use kittycad_modeling_cmds::{self as kcmc, shared::RelativeTo};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@ -37,11 +37,20 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
|||||||
)?;
|
)?;
|
||||||
let sectional = args.get_kw_arg_opt("sectional")?;
|
let sectional = args.get_kw_arg_opt("sectional")?;
|
||||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
|
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
|
||||||
|
let relative_to: Option<String> = args.get_kw_arg_opt_typed("relativeTo", &RuntimeType::string(), exec_state)?;
|
||||||
let tag_start = args.get_kw_arg_opt("tagStart")?;
|
let tag_start = args.get_kw_arg_opt("tagStart")?;
|
||||||
let tag_end = args.get_kw_arg_opt("tagEnd")?;
|
let tag_end = args.get_kw_arg_opt("tagEnd")?;
|
||||||
|
|
||||||
let value = inner_sweep(
|
let value = inner_sweep(
|
||||||
sketches, path, sectional, tolerance, tag_start, tag_end, exec_state, args,
|
sketches,
|
||||||
|
path,
|
||||||
|
sectional,
|
||||||
|
tolerance,
|
||||||
|
relative_to,
|
||||||
|
tag_start,
|
||||||
|
tag_end,
|
||||||
|
exec_state,
|
||||||
|
args,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(value.into())
|
Ok(value.into())
|
||||||
@ -103,7 +112,7 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
|||||||
/// // Create a spring by sweeping around the helix path.
|
/// // Create a spring by sweeping around the helix path.
|
||||||
/// springSketch = startSketchOn(YZ)
|
/// springSketch = startSketchOn(YZ)
|
||||||
/// |> circle( center = [0, 0], radius = 1)
|
/// |> circle( center = [0, 0], radius = 1)
|
||||||
/// |> sweep(path = helixPath)
|
/// |> sweep(path = helixPath, relativeTo = "sketchPlane")
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
@ -158,6 +167,7 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
|||||||
path = { docs = "The path to sweep the sketch along" },
|
path = { docs = "The path to sweep the sketch along" },
|
||||||
sectional = { docs = "If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components." },
|
sectional = { docs = "If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components." },
|
||||||
tolerance = { docs = "Tolerance for this operation" },
|
tolerance = { docs = "Tolerance for this operation" },
|
||||||
|
relative_to = { docs = "What is the sweep relative to? Can be either 'sketchPlane' or 'trajectoryCurve'. Defaults to trajectoryCurve."},
|
||||||
tag_start = { docs = "A named tag for the face at the start of the sweep, i.e. the original sketch" },
|
tag_start = { docs = "A named tag for the face at the start of the sweep, i.e. the original sketch" },
|
||||||
tag_end = { docs = "A named tag for the face at the end of the sweep" },
|
tag_end = { docs = "A named tag for the face at the end of the sweep" },
|
||||||
},
|
},
|
||||||
@ -169,6 +179,7 @@ async fn inner_sweep(
|
|||||||
path: SweepPath,
|
path: SweepPath,
|
||||||
sectional: Option<bool>,
|
sectional: Option<bool>,
|
||||||
tolerance: Option<TyF64>,
|
tolerance: Option<TyF64>,
|
||||||
|
relative_to: Option<String>,
|
||||||
tag_start: Option<TagNode>,
|
tag_start: Option<TagNode>,
|
||||||
tag_end: Option<TagNode>,
|
tag_end: Option<TagNode>,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
@ -178,6 +189,16 @@ async fn inner_sweep(
|
|||||||
SweepPath::Sketch(sketch) => sketch.id.into(),
|
SweepPath::Sketch(sketch) => sketch.id.into(),
|
||||||
SweepPath::Helix(helix) => helix.value.into(),
|
SweepPath::Helix(helix) => helix.value.into(),
|
||||||
};
|
};
|
||||||
|
let relative_to = match relative_to.as_deref() {
|
||||||
|
Some("sketchPlane") => RelativeTo::SketchPlane,
|
||||||
|
Some("trajectoryCurve") | None => RelativeTo::TrajectoryCurve,
|
||||||
|
Some(_) => {
|
||||||
|
return Err(KclError::Syntax(crate::errors::KclErrorDetails {
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
message: "If you provide relativeTo, it must either be 'sketchPlane' or 'trajectoryCurve'".to_owned(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut solids = Vec::new();
|
let mut solids = Vec::new();
|
||||||
for sketch in &sketches {
|
for sketch in &sketches {
|
||||||
@ -189,6 +210,7 @@ async fn inner_sweep(
|
|||||||
trajectory,
|
trajectory,
|
||||||
sectional: sectional.unwrap_or(false),
|
sectional: sectional.unwrap_or(false),
|
||||||
tolerance: LengthUnit(tolerance.as_ref().map(|t| t.to_mm()).unwrap_or(DEFAULT_TOLERANCE)),
|
tolerance: LengthUnit(tolerance.as_ref().map(|t| t.to_mm()).unwrap_or(DEFAULT_TOLERANCE)),
|
||||||
|
relative_to,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -83,7 +83,7 @@ export END = 'end'
|
|||||||
/// // Create a spring by sweeping around the helix path.
|
/// // Create a spring by sweeping around the helix path.
|
||||||
/// springSketch = startSketchOn(YZ)
|
/// springSketch = startSketchOn(YZ)
|
||||||
/// |> circle( center = [0, 0], radius = 0.5)
|
/// |> circle( center = [0, 0], radius = 0.5)
|
||||||
/// |> sweep(path = helixPath)
|
/// |> sweep(path = helixPath, relativeTo = "sketchPlane")
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -104,7 +104,7 @@ export END = 'end'
|
|||||||
/// // Create a spring by sweeping around the helix path.
|
/// // Create a spring by sweeping around the helix path.
|
||||||
/// springSketch = startSketchOn(XY)
|
/// springSketch = startSketchOn(XY)
|
||||||
/// |> circle( center = [0, 0], radius = 0.5 )
|
/// |> circle( center = [0, 0], radius = 0.5 )
|
||||||
/// |> sweep(path = helixPath)
|
/// |> sweep(path = helixPath, relativeTo = "sketchPlane")
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -124,7 +124,7 @@ export END = 'end'
|
|||||||
/// // Create a spring by sweeping around the helix path.
|
/// // Create a spring by sweeping around the helix path.
|
||||||
/// springSketch = startSketchOn(XY)
|
/// springSketch = startSketchOn(XY)
|
||||||
/// |> circle( center = [0, 0], radius = 1 )
|
/// |> circle( center = [0, 0], radius = 1 )
|
||||||
/// |> sweep(path = helixPath)
|
/// |> sweep(path = helixPath, relativeTo = "sketchPlane")
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -413,7 +413,7 @@ export fn offsetPlane(
|
|||||||
/// // Create a spring by sweeping around the helix path.
|
/// // Create a spring by sweeping around the helix path.
|
||||||
/// sweepedSpring = clone(springSketch)
|
/// sweepedSpring = clone(springSketch)
|
||||||
/// |> translate(x=100)
|
/// |> translate(x=100)
|
||||||
/// |> sweep(path = helixPath)
|
/// |> sweep(path = helixPath, relativeTo = "sketchPlane")
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```kcl
|
/// ```kcl
|
||||||
|
@ -4,8 +4,7 @@ description: Error from executing argument_error.kcl
|
|||||||
---
|
---
|
||||||
KCL Semantic error
|
KCL Semantic error
|
||||||
|
|
||||||
× semantic: f requires a value with type `fn(any): any`, but found array
|
× semantic: f requires a value with type `fn(any): any`, but found [any; 2]
|
||||||
│ (list)
|
|
||||||
╭─[5:1]
|
╭─[5:1]
|
||||||
4 │
|
4 │
|
||||||
5 │ map(f, f = [0, 1])
|
5 │ map(f, f = [0, 1])
|
||||||
@ -16,7 +15,7 @@ KCL Semantic error
|
|||||||
╰─▶ KCL Semantic error
|
╰─▶ KCL Semantic error
|
||||||
|
|
||||||
× semantic: f requires a value with type `fn(any): any`, but found
|
× semantic: f requires a value with type `fn(any): any`, but found
|
||||||
│ array (list)
|
│ [any; 2]
|
||||||
╭─[5:12]
|
╭─[5:12]
|
||||||
4 │
|
4 │
|
||||||
5 │ map(f, f = [0, 1])
|
5 │ map(f, f = [0, 1])
|
||||||
|
@ -5,7 +5,7 @@ description: Error from executing array_elem_pop_empty_fail.kcl
|
|||||||
KCL Semantic error
|
KCL Semantic error
|
||||||
|
|
||||||
× semantic: The input argument of `std::array::pop` requires a value with
|
× semantic: The input argument of `std::array::pop` requires a value with
|
||||||
│ type `[any; 1+]`, but found array (list)
|
│ type `[any; 1+]`, but found [any; 0]
|
||||||
╭─[2:8]
|
╭─[2:8]
|
||||||
1 │ arr = []
|
1 │ arr = []
|
||||||
2 │ fail = pop(arr)
|
2 │ fail = pop(arr)
|
||||||
@ -16,7 +16,7 @@ KCL Semantic error
|
|||||||
╰─▶ KCL Semantic error
|
╰─▶ KCL Semantic error
|
||||||
|
|
||||||
× semantic: The input argument of `std::array::pop` requires a value
|
× semantic: The input argument of `std::array::pop` requires a value
|
||||||
│ with type `[any; 1+]`, but found array (list)
|
│ with type `[any; 1+]`, but found [any; 0]
|
||||||
╭─[2:12]
|
╭─[2:12]
|
||||||
1 │ arr = []
|
1 │ arr = []
|
||||||
2 │ fail = pop(arr)
|
2 │ fail = pop(arr)
|
||||||
|
@ -4,7 +4,7 @@ description: Error from executing comparisons_multiple.kcl
|
|||||||
---
|
---
|
||||||
KCL Semantic error
|
KCL Semantic error
|
||||||
|
|
||||||
× semantic: Expected a number, but found a boolean (true/false value)
|
× semantic: Expected a number, but found bool
|
||||||
╭────
|
╭────
|
||||||
1 │ assert(3 == 3 == 3, error = "this should not compile")
|
1 │ assert(3 == 3 == 3, error = "this should not compile")
|
||||||
· ───┬──
|
· ───┬──
|
||||||
|
@ -5,7 +5,7 @@ description: Error from executing error_inside_fn_also_has_source_range_of_call_
|
|||||||
KCL Semantic error
|
KCL Semantic error
|
||||||
|
|
||||||
× semantic: This function expected the input argument to be Solid or Plane
|
× semantic: This function expected the input argument to be Solid or Plane
|
||||||
│ but it's actually of type string (text)
|
│ but it's actually of type string
|
||||||
╭─[3:23]
|
╭─[3:23]
|
||||||
2 │ fn someNestedFunction(@something2) {
|
2 │ fn someNestedFunction(@something2) {
|
||||||
3 │ startSketchOn(something2)
|
3 │ startSketchOn(something2)
|
||||||
@ -25,7 +25,7 @@ KCL Semantic error
|
|||||||
├─▶ KCL Semantic error
|
├─▶ KCL Semantic error
|
||||||
│
|
│
|
||||||
│ × semantic: This function expected the input argument to be Solid or
|
│ × semantic: This function expected the input argument to be Solid or
|
||||||
│ │ Plane but it's actually of type string (text)
|
│ │ Plane but it's actually of type string
|
||||||
│ ╭─[3:23]
|
│ ╭─[3:23]
|
||||||
│ 2 │ fn someNestedFunction(@something2) {
|
│ 2 │ fn someNestedFunction(@something2) {
|
||||||
│ 3 │ startSketchOn(something2)
|
│ 3 │ startSketchOn(something2)
|
||||||
@ -37,7 +37,7 @@ KCL Semantic error
|
|||||||
╰─▶ KCL Semantic error
|
╰─▶ KCL Semantic error
|
||||||
|
|
||||||
× semantic: This function expected the input argument to be Solid or
|
× semantic: This function expected the input argument to be Solid or
|
||||||
│ Plane but it's actually of type string (text)
|
│ Plane but it's actually of type string
|
||||||
╭─[6:5]
|
╭─[6:5]
|
||||||
5 │
|
5 │
|
||||||
6 │ someNestedFunction(something)
|
6 │ someNestedFunction(something)
|
||||||
|
@ -0,0 +1,349 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Artifact commands error_revolve_on_edge_get_edge.kcl
|
||||||
|
---
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "edge_lines_visible",
|
||||||
|
"hidden": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_visible",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_visible",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "make_plane",
|
||||||
|
"origin": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"x_axis": {
|
||||||
|
"x": 1.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"y_axis": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 1.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"size": 60.0,
|
||||||
|
"clobber": false,
|
||||||
|
"hide": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "enable_sketch_mode",
|
||||||
|
"entity_id": "[uuid]",
|
||||||
|
"ortho": false,
|
||||||
|
"animated": false,
|
||||||
|
"adjust_camera": false,
|
||||||
|
"planar_normal": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "move_path_pen",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"to": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "sketch_mode_disable"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "start_path"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "extend_path",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"segment": {
|
||||||
|
"type": "line",
|
||||||
|
"end": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 10.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"relative": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "extend_path",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"segment": {
|
||||||
|
"type": "line",
|
||||||
|
"end": {
|
||||||
|
"x": 10.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"relative": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "extend_path",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"segment": {
|
||||||
|
"type": "line",
|
||||||
|
"end": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": -10.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"relative": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "close_path",
|
||||||
|
"path_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "enable_sketch_mode",
|
||||||
|
"entity_id": "[uuid]",
|
||||||
|
"ortho": false,
|
||||||
|
"animated": false,
|
||||||
|
"adjust_camera": false,
|
||||||
|
"planar_normal": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "extrude",
|
||||||
|
"target": "[uuid]",
|
||||||
|
"distance": 10.0,
|
||||||
|
"faces": null,
|
||||||
|
"opposite": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_bring_to_front",
|
||||||
|
"object_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "sketch_mode_disable"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "solid3d_get_adjacency_info",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"edge_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "solid3d_get_extrusion_face_info",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"edge_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "enable_sketch_mode",
|
||||||
|
"entity_id": "[uuid]",
|
||||||
|
"ortho": false,
|
||||||
|
"animated": false,
|
||||||
|
"adjust_camera": false,
|
||||||
|
"planar_normal": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "move_path_pen",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"to": {
|
||||||
|
"x": 5.0,
|
||||||
|
"y": 10.0,
|
||||||
|
"z": 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "sketch_mode_disable"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "start_path"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "extend_path",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"segment": {
|
||||||
|
"type": "line",
|
||||||
|
"end": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": -10.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"relative": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "extend_path",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"segment": {
|
||||||
|
"type": "line",
|
||||||
|
"end": {
|
||||||
|
"x": 2.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"relative": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "extend_path",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"segment": {
|
||||||
|
"type": "line",
|
||||||
|
"end": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 10.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"relative": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "close_path",
|
||||||
|
"path_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_bring_to_front",
|
||||||
|
"object_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "revolve_about_edge",
|
||||||
|
"target": "[uuid]",
|
||||||
|
"edge_id": "[uuid]",
|
||||||
|
"angle": {
|
||||||
|
"unit": "degrees",
|
||||||
|
"value": 90.0
|
||||||
|
},
|
||||||
|
"tolerance": 0.0000001,
|
||||||
|
"opposite": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "solid3d_get_extrusion_face_info",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"edge_id": "[uuid]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
937
rust/kcl-lib/tests/error_revolve_on_edge_get_edge/ast.snap
Normal file
937
rust/kcl-lib/tests/error_revolve_on_edge_get_edge/ast.snap
Normal file
@ -0,0 +1,937 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of parsing error_revolve_on_edge_get_edge.kcl
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"Ok": {
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"declaration": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"id": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "box",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "startSketchOn",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "XY",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
|
"type": "Name"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "at",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "0",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 0.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "0",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 0.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "startProfile",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "end",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "0",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 0.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "10",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 10.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "line",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "end",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "10",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 10.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "0",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 0.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "line",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "end",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "0",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 0.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"argument": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "10",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 10.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"operator": "-",
|
||||||
|
"start": 0,
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"type": "UnaryExpression"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "tag",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "TagDeclarator",
|
||||||
|
"type": "TagDeclarator",
|
||||||
|
"value": "revolveAxis"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "line",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "close",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "length",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "10",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 10.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "extrude",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"type": "PipeExpression"
|
||||||
|
},
|
||||||
|
"start": 0,
|
||||||
|
"type": "VariableDeclarator"
|
||||||
|
},
|
||||||
|
"end": 0,
|
||||||
|
"kind": "const",
|
||||||
|
"start": 0,
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"declaration": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"id": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "sketch001",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "face",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "revolveAxis",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
|
"type": "Name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "startSketchOn",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "box",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
|
"type": "Name"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "at",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "5",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 5.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "10",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 10.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "startProfile",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "end",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "0",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 0.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"argument": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "10",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 10.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"operator": "-",
|
||||||
|
"start": 0,
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"type": "UnaryExpression"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "line",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "end",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "2",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 2.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "0",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 0.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "line",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "end",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "0",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 0.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "10",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 10.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "line",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "close",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "axis",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "revolveAxis",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
|
"type": "Name"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "angle",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "90",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 90.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "revolve",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"type": "PipeExpression"
|
||||||
|
},
|
||||||
|
"start": 0,
|
||||||
|
"type": "VariableDeclarator"
|
||||||
|
},
|
||||||
|
"end": 0,
|
||||||
|
"kind": "const",
|
||||||
|
"start": 0,
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {
|
||||||
|
"0": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "NonCodeNode",
|
||||||
|
"value": {
|
||||||
|
"type": "newLine"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"startNodes": []
|
||||||
|
},
|
||||||
|
"start": 0
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Error from executing error_revolve_on_edge_get_edge.kcl
|
||||||
|
---
|
||||||
|
KCL Engine error
|
||||||
|
|
||||||
|
× engine: Solid3D revolve failed: sketch profile must lie entirely on one
|
||||||
|
│ side of the revolution axis
|
||||||
|
╭─[15:6]
|
||||||
|
14 │ |> close()
|
||||||
|
15 │ |> revolve(axis = revolveAxis, angle = 90)
|
||||||
|
· ───────────────────┬───────────────────┬
|
||||||
|
· ╰── tests/error_revolve_on_edge_get_edge/input.kcl
|
||||||
|
· ╰── tests/error_revolve_on_edge_get_edge/input.kcl
|
||||||
|
╰────
|
||||||
|
╰─▶ KCL Engine error
|
||||||
|
|
||||||
|
× engine: Solid3D revolve failed: sketch profile must lie entirely on
|
||||||
|
│ one side of the revolution axis
|
||||||
|
╭─[15:6]
|
||||||
|
14 │ |> close()
|
||||||
|
15 │ |> revolve(axis = revolveAxis, angle = 90)
|
||||||
|
· ───────────────────┬───────────────────
|
||||||
|
· ╰── tests/error_revolve_on_edge_get_edge/
|
||||||
|
input.kcl
|
||||||
|
╰────
|
15
rust/kcl-lib/tests/error_revolve_on_edge_get_edge/input.kcl
Normal file
15
rust/kcl-lib/tests/error_revolve_on_edge_get_edge/input.kcl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
box = startSketchOn(XY)
|
||||||
|
|> startProfile(at = [0, 0])
|
||||||
|
|> line(end = [0, 10])
|
||||||
|
|> line(end = [10, 0])
|
||||||
|
|> line(end = [0, -10], tag = $revolveAxis)
|
||||||
|
|> close()
|
||||||
|
|> extrude(length = 10)
|
||||||
|
|
||||||
|
sketch001 = startSketchOn(box, face = revolveAxis)
|
||||||
|
|> startProfile(at = [5, 10])
|
||||||
|
|> line(end = [0, -10])
|
||||||
|
|> line(end = [2, 0])
|
||||||
|
|> line(end = [0, 10])
|
||||||
|
|> close()
|
||||||
|
|> revolve(axis = revolveAxis, angle = 90)
|
116
rust/kcl-lib/tests/error_revolve_on_edge_get_edge/ops.snap
Normal file
116
rust/kcl-lib/tests/error_revolve_on_edge_get_edge/ops.snap
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Operations executed error_revolve_on_edge_get_edge.kcl
|
||||||
|
---
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"labeledArgs": {},
|
||||||
|
"name": "startSketchOn",
|
||||||
|
"sourceRange": [],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Plane",
|
||||||
|
"artifact_id": "[uuid]"
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"labeledArgs": {
|
||||||
|
"length": {
|
||||||
|
"value": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 10.0,
|
||||||
|
"ty": {
|
||||||
|
"type": "Default",
|
||||||
|
"len": {
|
||||||
|
"type": "Mm"
|
||||||
|
},
|
||||||
|
"angle": {
|
||||||
|
"type": "Degrees"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "extrude",
|
||||||
|
"sourceRange": [],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Sketch",
|
||||||
|
"value": {
|
||||||
|
"artifactId": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"labeledArgs": {
|
||||||
|
"face": {
|
||||||
|
"value": {
|
||||||
|
"type": "TagIdentifier",
|
||||||
|
"value": "revolveAxis",
|
||||||
|
"artifact_id": "[uuid]"
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "startSketchOn",
|
||||||
|
"sourceRange": [],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Solid",
|
||||||
|
"value": {
|
||||||
|
"artifactId": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "KclStdLibCall",
|
||||||
|
"name": "revolve",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Sketch",
|
||||||
|
"value": {
|
||||||
|
"artifactId": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
},
|
||||||
|
"labeledArgs": {
|
||||||
|
"angle": {
|
||||||
|
"value": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 90.0,
|
||||||
|
"ty": {
|
||||||
|
"type": "Default",
|
||||||
|
"len": {
|
||||||
|
"type": "Mm"
|
||||||
|
},
|
||||||
|
"angle": {
|
||||||
|
"type": "Degrees"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
},
|
||||||
|
"axis": {
|
||||||
|
"value": {
|
||||||
|
"type": "TagIdentifier",
|
||||||
|
"value": "revolveAxis",
|
||||||
|
"artifact_id": "[uuid]"
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": [],
|
||||||
|
"isError": true
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of unparsing error_revolve_on_edge_get_edge.kcl
|
||||||
|
---
|
||||||
|
box = startSketchOn(XY)
|
||||||
|
|> startProfile(at = [0, 0])
|
||||||
|
|> line(end = [0, 10])
|
||||||
|
|> line(end = [10, 0])
|
||||||
|
|> line(end = [0, -10], tag = $revolveAxis)
|
||||||
|
|> close()
|
||||||
|
|> extrude(length = 10)
|
||||||
|
|
||||||
|
sketch001 = startSketchOn(box, face = revolveAxis)
|
||||||
|
|> startProfile(at = [5, 10])
|
||||||
|
|> line(end = [0, -10])
|
||||||
|
|> line(end = [2, 0])
|
||||||
|
|> line(end = [0, 10])
|
||||||
|
|> close()
|
||||||
|
|> revolve(axis = revolveAxis, angle = 90)
|
@ -4,9 +4,8 @@ description: Error from executing execute_engine_error_return.kcl
|
|||||||
---
|
---
|
||||||
KCL Engine error
|
KCL Engine error
|
||||||
|
|
||||||
× engine: Modeling command failed: [ApiError { error_code: BadRequest,
|
× engine: The path is not closed. Solid2D construction requires a closed
|
||||||
│ message: "The path is not closed. Solid2D construction requires a closed
|
│ path!
|
||||||
│ path!" }]
|
|
||||||
╭─[7:6]
|
╭─[7:6]
|
||||||
6 │ |> line(end = [-11.53311, 2.81559])
|
6 │ |> line(end = [-11.53311, 2.81559])
|
||||||
7 │ |> extrude(length = 4)
|
7 │ |> extrude(length = 4)
|
||||||
|
@ -1012,8 +1012,41 @@ description: Artifact commands import_mesh_clone.kcl
|
|||||||
"cmdId": "[uuid]",
|
"cmdId": "[uuid]",
|
||||||
"range": [],
|
"range": [],
|
||||||
"command": {
|
"command": {
|
||||||
"type": "entity_get_all_child_uuids",
|
"type": "set_object_transform",
|
||||||
"entity_id": "[uuid]"
|
"object_id": "[uuid]",
|
||||||
|
"transforms": [
|
||||||
|
{
|
||||||
|
"translate": {
|
||||||
|
"property": {
|
||||||
|
"x": 1020.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"set": false,
|
||||||
|
"is_local": true
|
||||||
|
},
|
||||||
|
"rotate_rpy": null,
|
||||||
|
"rotate_angle_axis": null,
|
||||||
|
"scale": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_set_material_params_pbr",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"color": {
|
||||||
|
"r": 1.0,
|
||||||
|
"g": 0.0,
|
||||||
|
"b": 0.0,
|
||||||
|
"a": 100.0
|
||||||
|
},
|
||||||
|
"metalness": 0.5,
|
||||||
|
"roughness": 0.5,
|
||||||
|
"ambient_occlusion": 0.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2,18 +2,9 @@
|
|||||||
source: kcl-lib/src/simulation_tests.rs
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
description: Error from executing import_mesh_clone.kcl
|
description: Error from executing import_mesh_clone.kcl
|
||||||
---
|
---
|
||||||
KCL Internal error
|
KCL Engine error
|
||||||
|
|
||||||
× internal: failed to fix tags and references: engine: KclErrorDetails
|
× engine: Modeling command failed: websocket closed early
|
||||||
│ { source_ranges: [SourceRange([60, 72, 0])], message: "Modeling command
|
╭────
|
||||||
│ failed: [ApiError { error_code: BadRequest, message: \"Entity type does
|
13 │ )
|
||||||
│ not currently support transform patterns.\" }, ApiError { error_code:
|
╰────
|
||||||
│ InternalEngine, message: \"Failed to clone entity.\" }, ApiError
|
|
||||||
│ { error_code: InternalEngine, message: \"Failed to clone entity\" }]" }
|
|
||||||
╭─[5:10]
|
|
||||||
4 │
|
|
||||||
5 │ model2 = clone(model)
|
|
||||||
· ──────┬─────
|
|
||||||
· ╰── tests/import_mesh_clone/input.kcl
|
|
||||||
6 │ |> translate(
|
|
||||||
╰────
|
|
||||||
|
@ -7,28 +7,25 @@ description: Operations executed import_mesh_clone.kcl
|
|||||||
"type": "GroupBegin",
|
"type": "GroupBegin",
|
||||||
"group": {
|
"group": {
|
||||||
"type": "ModuleInstance",
|
"type": "ModuleInstance",
|
||||||
"name": "cube",
|
"name": "cube.obj",
|
||||||
"moduleId": 6
|
"moduleId": 0
|
||||||
},
|
},
|
||||||
"sourceRange": []
|
"sourceRange": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "GroupEnd"
|
"type": "KclStdLibCall",
|
||||||
|
"name": "clone",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "ImportedGeometry",
|
||||||
|
"artifact_id": "[uuid]"
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
},
|
||||||
|
"labeledArgs": {},
|
||||||
|
"sourceRange": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"isError": true,
|
"type": "GroupEnd"
|
||||||
"labeledArgs": {
|
|
||||||
"geometry": {
|
|
||||||
"value": {
|
|
||||||
"type": "ImportedGeometry",
|
|
||||||
"artifact_id": "[uuid]"
|
|
||||||
},
|
|
||||||
"sourceRange": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"name": "clone",
|
|
||||||
"sourceRange": [],
|
|
||||||
"type": "StdLibCall",
|
|
||||||
"unlabeledArg": null
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
source: kcl/src/simulation_tests.rs
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
description: Error from executing invalid_member_object.kcl
|
description: Error from executing invalid_member_object.kcl
|
||||||
---
|
---
|
||||||
KCL Semantic error
|
KCL Semantic error
|
||||||
|
|
||||||
× semantic: Only arrays and objects can be indexed, but you're trying to
|
× semantic: Only arrays can be indexed, but you're trying to index a
|
||||||
│ index a number
|
│ number(default units)
|
||||||
╭─[2:5]
|
╭─[2:5]
|
||||||
1 │ num = 999
|
1 │ num = 999
|
||||||
2 │ x = num[3]
|
2 │ x = num[3]
|
||||||
|
@ -5121,7 +5121,8 @@ description: Artifact commands bench.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -5132,7 +5133,8 @@ description: Artifact commands bench.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -905,7 +905,8 @@ description: Artifact commands cold-plate.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -5575,7 +5575,8 @@ description: Artifact commands cpu-cooler.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -6109,7 +6110,8 @@ description: Artifact commands cpu-cooler.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -9466,7 +9468,8 @@ description: Artifact commands cpu-cooler.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -9597,7 +9600,8 @@ description: Artifact commands cpu-cooler.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -10115,7 +10119,8 @@ description: Artifact commands cpu-cooler.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -10246,7 +10251,8 @@ description: Artifact commands cpu-cooler.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -456,13 +456,7 @@ description: Result of parsing enclosure.kcl
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "LabeledArg",
|
"type": "LabeledArg",
|
||||||
"label": {
|
"label": null,
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": "length",
|
|
||||||
"start": 0,
|
|
||||||
"type": "Identifier"
|
|
||||||
},
|
|
||||||
"arg": {
|
"arg": {
|
||||||
"abs_path": false,
|
"abs_path": false,
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
@ -3178,13 +3172,7 @@ description: Result of parsing enclosure.kcl
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "LabeledArg",
|
"type": "LabeledArg",
|
||||||
"label": {
|
"label": null,
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": "length",
|
|
||||||
"start": 0,
|
|
||||||
"type": "Identifier"
|
|
||||||
},
|
|
||||||
"arg": {
|
"arg": {
|
||||||
"abs_path": false,
|
"abs_path": false,
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
|
@ -28,9 +28,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 485,
|
"commentStart": 476,
|
||||||
"end": 506,
|
"end": 497,
|
||||||
"start": 485,
|
"start": 476,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB001"
|
"value": "rectangleSegmentB001"
|
||||||
},
|
},
|
||||||
@ -41,9 +41,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 608,
|
"commentStart": 599,
|
||||||
"end": 629,
|
"end": 620,
|
||||||
"start": 608,
|
"start": 599,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC001"
|
"value": "rectangleSegmentC001"
|
||||||
},
|
},
|
||||||
@ -54,9 +54,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 699,
|
"commentStart": 690,
|
||||||
"end": 720,
|
"end": 711,
|
||||||
"start": 699,
|
"start": 690,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD001"
|
"value": "rectangleSegmentD001"
|
||||||
},
|
},
|
||||||
@ -102,9 +102,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
0.0
|
0.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 485,
|
"commentStart": 476,
|
||||||
"end": 506,
|
"end": 497,
|
||||||
"start": 485,
|
"start": 476,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB001"
|
"value": "rectangleSegmentB001"
|
||||||
},
|
},
|
||||||
@ -127,9 +127,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
175.0
|
175.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 608,
|
"commentStart": 599,
|
||||||
"end": 629,
|
"end": 620,
|
||||||
"start": 608,
|
"start": 599,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC001"
|
"value": "rectangleSegmentC001"
|
||||||
},
|
},
|
||||||
@ -152,9 +152,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
175.0
|
175.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 699,
|
"commentStart": 690,
|
||||||
"end": 720,
|
"end": 711,
|
||||||
"start": 699,
|
"start": 690,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD001"
|
"value": "rectangleSegmentD001"
|
||||||
},
|
},
|
||||||
@ -354,9 +354,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2445,
|
"commentStart": 2436,
|
||||||
"end": 2466,
|
"end": 2457,
|
||||||
"start": 2445,
|
"start": 2436,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentA002"
|
"value": "rectangleSegmentA002"
|
||||||
},
|
},
|
||||||
@ -367,9 +367,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2550,
|
"commentStart": 2532,
|
||||||
"end": 2571,
|
"end": 2553,
|
||||||
"start": 2550,
|
"start": 2532,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB002"
|
"value": "rectangleSegmentB002"
|
||||||
},
|
},
|
||||||
@ -380,9 +380,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2673,
|
"commentStart": 2655,
|
||||||
"end": 2694,
|
"end": 2676,
|
||||||
"start": 2673,
|
"start": 2655,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC002"
|
"value": "rectangleSegmentC002"
|
||||||
},
|
},
|
||||||
@ -393,9 +393,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2764,
|
"commentStart": 2746,
|
||||||
"end": 2785,
|
"end": 2767,
|
||||||
"start": 2764,
|
"start": 2746,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD002"
|
"value": "rectangleSegmentD002"
|
||||||
},
|
},
|
||||||
@ -416,9 +416,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
0.0
|
0.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2445,
|
"commentStart": 2436,
|
||||||
"end": 2466,
|
"end": 2457,
|
||||||
"start": 2445,
|
"start": 2436,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentA002"
|
"value": "rectangleSegmentA002"
|
||||||
},
|
},
|
||||||
@ -441,9 +441,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
0.0
|
0.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2550,
|
"commentStart": 2532,
|
||||||
"end": 2571,
|
"end": 2553,
|
||||||
"start": 2550,
|
"start": 2532,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB002"
|
"value": "rectangleSegmentB002"
|
||||||
},
|
},
|
||||||
@ -466,9 +466,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
175.0
|
175.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2673,
|
"commentStart": 2655,
|
||||||
"end": 2694,
|
"end": 2676,
|
||||||
"start": 2673,
|
"start": 2655,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC002"
|
"value": "rectangleSegmentC002"
|
||||||
},
|
},
|
||||||
@ -491,9 +491,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
175.0
|
175.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2764,
|
"commentStart": 2746,
|
||||||
"end": 2785,
|
"end": 2767,
|
||||||
"start": 2764,
|
"start": 2746,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD002"
|
"value": "rectangleSegmentD002"
|
||||||
},
|
},
|
||||||
@ -693,9 +693,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 4147,
|
"commentStart": 4129,
|
||||||
"end": 4168,
|
"end": 4150,
|
||||||
"start": 4147,
|
"start": 4129,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentA003"
|
"value": "rectangleSegmentA003"
|
||||||
},
|
},
|
||||||
@ -706,9 +706,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 4274,
|
"commentStart": 4256,
|
||||||
"end": 4295,
|
"end": 4277,
|
||||||
"start": 4274,
|
"start": 4256,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB003"
|
"value": "rectangleSegmentB003"
|
||||||
},
|
},
|
||||||
@ -719,9 +719,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 4397,
|
"commentStart": 4379,
|
||||||
"end": 4418,
|
"end": 4400,
|
||||||
"start": 4397,
|
"start": 4379,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC003"
|
"value": "rectangleSegmentC003"
|
||||||
},
|
},
|
||||||
@ -732,9 +732,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 4488,
|
"commentStart": 4470,
|
||||||
"end": 4509,
|
"end": 4491,
|
||||||
"start": 4488,
|
"start": 4470,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD003"
|
"value": "rectangleSegmentD003"
|
||||||
},
|
},
|
||||||
@ -755,9 +755,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
3.0
|
3.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 4147,
|
"commentStart": 4129,
|
||||||
"end": 4168,
|
"end": 4150,
|
||||||
"start": 4147,
|
"start": 4129,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentA003"
|
"value": "rectangleSegmentA003"
|
||||||
},
|
},
|
||||||
@ -780,9 +780,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
3.0
|
3.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 4274,
|
"commentStart": 4256,
|
||||||
"end": 4295,
|
"end": 4277,
|
||||||
"start": 4274,
|
"start": 4256,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB003"
|
"value": "rectangleSegmentB003"
|
||||||
},
|
},
|
||||||
@ -805,9 +805,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
172.0
|
172.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 4397,
|
"commentStart": 4379,
|
||||||
"end": 4418,
|
"end": 4400,
|
||||||
"start": 4397,
|
"start": 4379,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC003"
|
"value": "rectangleSegmentC003"
|
||||||
},
|
},
|
||||||
@ -830,9 +830,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
172.0
|
172.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 4488,
|
"commentStart": 4470,
|
||||||
"end": 4509,
|
"end": 4491,
|
||||||
"start": 4488,
|
"start": 4470,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD003"
|
"value": "rectangleSegmentD003"
|
||||||
},
|
},
|
||||||
@ -896,9 +896,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2445,
|
"commentStart": 2436,
|
||||||
"end": 2466,
|
"end": 2457,
|
||||||
"start": 2445,
|
"start": 2436,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentA002"
|
"value": "rectangleSegmentA002"
|
||||||
},
|
},
|
||||||
@ -909,9 +909,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2550,
|
"commentStart": 2532,
|
||||||
"end": 2571,
|
"end": 2553,
|
||||||
"start": 2550,
|
"start": 2532,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB002"
|
"value": "rectangleSegmentB002"
|
||||||
},
|
},
|
||||||
@ -922,9 +922,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2673,
|
"commentStart": 2655,
|
||||||
"end": 2694,
|
"end": 2676,
|
||||||
"start": 2673,
|
"start": 2655,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC002"
|
"value": "rectangleSegmentC002"
|
||||||
},
|
},
|
||||||
@ -935,9 +935,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2764,
|
"commentStart": 2746,
|
||||||
"end": 2785,
|
"end": 2767,
|
||||||
"start": 2764,
|
"start": 2746,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD002"
|
"value": "rectangleSegmentD002"
|
||||||
},
|
},
|
||||||
@ -958,9 +958,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
0.0
|
0.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2445,
|
"commentStart": 2436,
|
||||||
"end": 2466,
|
"end": 2457,
|
||||||
"start": 2445,
|
"start": 2436,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentA002"
|
"value": "rectangleSegmentA002"
|
||||||
},
|
},
|
||||||
@ -983,9 +983,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
0.0
|
0.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2550,
|
"commentStart": 2532,
|
||||||
"end": 2571,
|
"end": 2553,
|
||||||
"start": 2550,
|
"start": 2532,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB002"
|
"value": "rectangleSegmentB002"
|
||||||
},
|
},
|
||||||
@ -1008,9 +1008,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
175.0
|
175.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2673,
|
"commentStart": 2655,
|
||||||
"end": 2694,
|
"end": 2676,
|
||||||
"start": 2673,
|
"start": 2655,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC002"
|
"value": "rectangleSegmentC002"
|
||||||
},
|
},
|
||||||
@ -1033,9 +1033,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
175.0
|
175.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2764,
|
"commentStart": 2746,
|
||||||
"end": 2785,
|
"end": 2767,
|
||||||
"start": 2764,
|
"start": 2746,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD002"
|
"value": "rectangleSegmentD002"
|
||||||
},
|
},
|
||||||
@ -1495,9 +1495,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
0.0
|
0.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 485,
|
"commentStart": 476,
|
||||||
"end": 506,
|
"end": 497,
|
||||||
"start": 485,
|
"start": 476,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB001"
|
"value": "rectangleSegmentB001"
|
||||||
},
|
},
|
||||||
@ -1520,9 +1520,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
175.0
|
175.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 608,
|
"commentStart": 599,
|
||||||
"end": 629,
|
"end": 620,
|
||||||
"start": 608,
|
"start": 599,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC001"
|
"value": "rectangleSegmentC001"
|
||||||
},
|
},
|
||||||
@ -1545,9 +1545,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
175.0
|
175.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 699,
|
"commentStart": 690,
|
||||||
"end": 720,
|
"end": 711,
|
||||||
"start": 699,
|
"start": 690,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD001"
|
"value": "rectangleSegmentD001"
|
||||||
},
|
},
|
||||||
@ -1669,9 +1669,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
0.0
|
0.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2445,
|
"commentStart": 2436,
|
||||||
"end": 2466,
|
"end": 2457,
|
||||||
"start": 2445,
|
"start": 2436,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentA002"
|
"value": "rectangleSegmentA002"
|
||||||
},
|
},
|
||||||
@ -1694,9 +1694,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
0.0
|
0.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2550,
|
"commentStart": 2532,
|
||||||
"end": 2571,
|
"end": 2553,
|
||||||
"start": 2550,
|
"start": 2532,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB002"
|
"value": "rectangleSegmentB002"
|
||||||
},
|
},
|
||||||
@ -1719,9 +1719,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
175.0
|
175.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2673,
|
"commentStart": 2655,
|
||||||
"end": 2694,
|
"end": 2676,
|
||||||
"start": 2673,
|
"start": 2655,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC002"
|
"value": "rectangleSegmentC002"
|
||||||
},
|
},
|
||||||
@ -1744,9 +1744,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
175.0
|
175.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2764,
|
"commentStart": 2746,
|
||||||
"end": 2785,
|
"end": 2767,
|
||||||
"start": 2764,
|
"start": 2746,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD002"
|
"value": "rectangleSegmentD002"
|
||||||
},
|
},
|
||||||
@ -1868,9 +1868,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
3.0
|
3.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 4147,
|
"commentStart": 4129,
|
||||||
"end": 4168,
|
"end": 4150,
|
||||||
"start": 4147,
|
"start": 4129,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentA003"
|
"value": "rectangleSegmentA003"
|
||||||
},
|
},
|
||||||
@ -1893,9 +1893,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
3.0
|
3.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 4274,
|
"commentStart": 4256,
|
||||||
"end": 4295,
|
"end": 4277,
|
||||||
"start": 4274,
|
"start": 4256,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB003"
|
"value": "rectangleSegmentB003"
|
||||||
},
|
},
|
||||||
@ -1918,9 +1918,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
172.0
|
172.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 4397,
|
"commentStart": 4379,
|
||||||
"end": 4418,
|
"end": 4400,
|
||||||
"start": 4397,
|
"start": 4379,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC003"
|
"value": "rectangleSegmentC003"
|
||||||
},
|
},
|
||||||
@ -1943,9 +1943,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
172.0
|
172.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 4488,
|
"commentStart": 4470,
|
||||||
"end": 4509,
|
"end": 4491,
|
||||||
"start": 4488,
|
"start": 4470,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD003"
|
"value": "rectangleSegmentD003"
|
||||||
},
|
},
|
||||||
@ -2009,9 +2009,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2445,
|
"commentStart": 2436,
|
||||||
"end": 2466,
|
"end": 2457,
|
||||||
"start": 2445,
|
"start": 2436,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentA002"
|
"value": "rectangleSegmentA002"
|
||||||
},
|
},
|
||||||
@ -2022,9 +2022,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2550,
|
"commentStart": 2532,
|
||||||
"end": 2571,
|
"end": 2553,
|
||||||
"start": 2550,
|
"start": 2532,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB002"
|
"value": "rectangleSegmentB002"
|
||||||
},
|
},
|
||||||
@ -2035,9 +2035,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2673,
|
"commentStart": 2655,
|
||||||
"end": 2694,
|
"end": 2676,
|
||||||
"start": 2673,
|
"start": 2655,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC002"
|
"value": "rectangleSegmentC002"
|
||||||
},
|
},
|
||||||
@ -2048,9 +2048,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
"id": "[uuid]",
|
"id": "[uuid]",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2764,
|
"commentStart": 2746,
|
||||||
"end": 2785,
|
"end": 2767,
|
||||||
"start": 2764,
|
"start": 2746,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD002"
|
"value": "rectangleSegmentD002"
|
||||||
},
|
},
|
||||||
@ -2071,9 +2071,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
0.0
|
0.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2445,
|
"commentStart": 2436,
|
||||||
"end": 2466,
|
"end": 2457,
|
||||||
"start": 2445,
|
"start": 2436,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentA002"
|
"value": "rectangleSegmentA002"
|
||||||
},
|
},
|
||||||
@ -2096,9 +2096,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
0.0
|
0.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2550,
|
"commentStart": 2532,
|
||||||
"end": 2571,
|
"end": 2553,
|
||||||
"start": 2550,
|
"start": 2532,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentB002"
|
"value": "rectangleSegmentB002"
|
||||||
},
|
},
|
||||||
@ -2121,9 +2121,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
175.0
|
175.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2673,
|
"commentStart": 2655,
|
||||||
"end": 2694,
|
"end": 2676,
|
||||||
"start": 2673,
|
"start": 2655,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentC002"
|
"value": "rectangleSegmentC002"
|
||||||
},
|
},
|
||||||
@ -2146,9 +2146,9 @@ description: Variables in memory after executing enclosure.kcl
|
|||||||
175.0
|
175.0
|
||||||
],
|
],
|
||||||
"tag": {
|
"tag": {
|
||||||
"commentStart": 2764,
|
"commentStart": 2746,
|
||||||
"end": 2785,
|
"end": 2767,
|
||||||
"start": 2764,
|
"start": 2746,
|
||||||
"type": "TagDeclarator",
|
"type": "TagDeclarator",
|
||||||
"value": "rectangleSegmentD002"
|
"value": "rectangleSegmentD002"
|
||||||
},
|
},
|
||||||
|
@ -1597,7 +1597,8 @@ description: Artifact commands exhaust-manifold.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1608,7 +1609,8 @@ description: Artifact commands exhaust-manifold.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1619,7 +1621,8 @@ description: Artifact commands exhaust-manifold.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1630,7 +1633,8 @@ description: Artifact commands exhaust-manifold.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -4490,7 +4490,8 @@ description: Artifact commands utility-sink.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,19 +4,17 @@ description: Operations executed mike_stress_test.kcl
|
|||||||
---
|
---
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"labeledArgs": {
|
"labeledArgs": {},
|
||||||
"planeOrSolid": {
|
|
||||||
"value": {
|
|
||||||
"type": "String",
|
|
||||||
"value": "XY"
|
|
||||||
},
|
|
||||||
"sourceRange": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"name": "startSketchOn",
|
"name": "startSketchOn",
|
||||||
"sourceRange": [],
|
"sourceRange": [],
|
||||||
"type": "StdLibCall",
|
"type": "StdLibCall",
|
||||||
"unlabeledArg": null
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Plane",
|
||||||
|
"artifact_id": "[uuid]"
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"labeledArgs": {
|
"labeledArgs": {
|
||||||
|
@ -26043,10 +26043,8 @@ description: Variables in memory after executing mike_stress_test.kcl
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"on": {
|
"on": {
|
||||||
"type": "plane",
|
|
||||||
"id": "[uuid]",
|
|
||||||
"artifactId": "[uuid]",
|
"artifactId": "[uuid]",
|
||||||
"value": "XY",
|
"id": "[uuid]",
|
||||||
"origin": {
|
"origin": {
|
||||||
"x": 0.0,
|
"x": 0.0,
|
||||||
"y": 0.0,
|
"y": 0.0,
|
||||||
@ -26055,12 +26053,14 @@ description: Variables in memory after executing mike_stress_test.kcl
|
|||||||
"type": "Mm"
|
"type": "Mm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"type": "plane",
|
||||||
|
"value": "XY",
|
||||||
"xAxis": {
|
"xAxis": {
|
||||||
"x": 1.0,
|
"x": 1.0,
|
||||||
"y": 0.0,
|
"y": 0.0,
|
||||||
"z": 0.0,
|
"z": 0.0,
|
||||||
"units": {
|
"units": {
|
||||||
"type": "Mm"
|
"type": "Unknown"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"yAxis": {
|
"yAxis": {
|
||||||
@ -26068,7 +26068,7 @@ description: Variables in memory after executing mike_stress_test.kcl
|
|||||||
"y": 1.0,
|
"y": 1.0,
|
||||||
"z": 0.0,
|
"z": 0.0,
|
||||||
"units": {
|
"units": {
|
||||||
"type": "Mm"
|
"type": "Unknown"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -5,7 +5,7 @@ description: Error from executing panic_repro_cube.kcl
|
|||||||
KCL Semantic error
|
KCL Semantic error
|
||||||
|
|
||||||
× semantic: This function expected the input argument to be tag identifier
|
× semantic: This function expected the input argument to be tag identifier
|
||||||
│ but it's actually of type Unique ID (uuid)
|
│ but it's actually of type tag
|
||||||
╭─[43:25]
|
╭─[43:25]
|
||||||
42 │ // these double wrapped functions are the point of this test
|
42 │ // these double wrapped functions are the point of this test
|
||||||
43 │ getNextAdjacentEdge(getNextAdjacentEdge(seg01)),
|
43 │ getNextAdjacentEdge(getNextAdjacentEdge(seg01)),
|
||||||
|
@ -4,8 +4,7 @@ description: Error from executing pattern_into_union.kcl
|
|||||||
---
|
---
|
||||||
KCL Engine error
|
KCL Engine error
|
||||||
|
|
||||||
× engine: Modeling command failed: [ApiError { error_code: InternalEngine,
|
× engine: More than 2 solids were passed to the low-level CSG method
|
||||||
│ message: "More than 2 solids were passed to the low-level CSG method" }]
|
|
||||||
╭─[67:1]
|
╭─[67:1]
|
||||||
66 │
|
66 │
|
||||||
67 │ union([base,endTabs])
|
67 │ union([base,endTabs])
|
||||||
|
1060
rust/kcl-lib/tests/sketch_on_face_union/artifact_commands.snap
Normal file
1060
rust/kcl-lib/tests/sketch_on_face_union/artifact_commands.snap
Normal file
File diff suppressed because it is too large
Load Diff
3671
rust/kcl-lib/tests/sketch_on_face_union/ast.snap
Normal file
3671
rust/kcl-lib/tests/sketch_on_face_union/ast.snap
Normal file
File diff suppressed because it is too large
Load Diff
58
rust/kcl-lib/tests/sketch_on_face_union/input.kcl
Normal file
58
rust/kcl-lib/tests/sketch_on_face_union/input.kcl
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
@settings(defaultLengthUnit = in)
|
||||||
|
|
||||||
|
// Define parameters
|
||||||
|
trussSupportAngle = 15
|
||||||
|
height = 120
|
||||||
|
thickness = 4
|
||||||
|
|
||||||
|
sketch001 = startSketchOn(YZ)
|
||||||
|
profile001 = startProfile(sketch001, at = [60, 0])
|
||||||
|
|> xLine(length = -120, tag = $bottomFace)
|
||||||
|
|> yLine(length = 12)
|
||||||
|
|> angledLine(angle = 25, endAbsoluteX = 0, tag = $tag001)
|
||||||
|
|> angledLine(angle = -25, endAbsoluteX = 60)
|
||||||
|
|> close()
|
||||||
|
|
||||||
|
profile002 = startProfile(sketch001, at = [60-thickness, thickness])
|
||||||
|
|> xLine(endAbsolute = thickness/2)
|
||||||
|
|> yLine(endAbsolute = segEndY(tag001)-thickness) // update
|
||||||
|
|> angledLine(endAbsoluteX = profileStartX(%), angle = -25)
|
||||||
|
|> close(%)
|
||||||
|
|
||||||
|
profile003 = startProfile(sketch001, at = [-60+thickness, thickness])
|
||||||
|
|> xLine(endAbsolute = -thickness/2)
|
||||||
|
|> yLine(endAbsolute = segEndY(tag001)-thickness) // update
|
||||||
|
|> angledLine(endAbsoluteX = profileStartX(%), angle = 205)
|
||||||
|
|> close(%)
|
||||||
|
|
||||||
|
profile004 = subtract2d(profile001, tool = profile002)
|
||||||
|
subtract2d(profile001, tool = profile003)
|
||||||
|
|
||||||
|
body001 = extrude(profile001, length = 2)
|
||||||
|
|
||||||
|
sketch002 = startSketchOn(offsetPlane(YZ, offset = .1))
|
||||||
|
profile006 = startProfile(sketch002, at = [thickness/2-1, 14])
|
||||||
|
|> angledLine(angle = 30, length = 25)
|
||||||
|
|> angledLine(angle = -25, length = 5)
|
||||||
|
|> angledLine(angle = 210, endAbsoluteX = profileStartX(%))
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(%, length = 1.8)
|
||||||
|
|
||||||
|
profile007 = startProfile(sketch002, at = [-thickness/2+1, 14])
|
||||||
|
|> angledLine(angle = 150, length = 25)
|
||||||
|
|> angledLine(angle = 205, length = 5)
|
||||||
|
|> angledLine(angle = -30, endAbsoluteX = profileStartX(%))
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(%, length = 1.8)
|
||||||
|
|
||||||
|
newSketch = body001 + profile006 + profile007
|
||||||
|
|
||||||
|
leg001Sketch = startSketchOn(newSketch, face = bottomFace)
|
||||||
|
legProfile001 = startProfile(leg001Sketch, at = [-60, 0])
|
||||||
|
|> xLine(%, length = 4)
|
||||||
|
|> yLine(%, length = 2)
|
||||||
|
|> xLine(%, endAbsolute = profileStartX(%))
|
||||||
|
|> close(%)
|
||||||
|
|
||||||
|
leg001 = extrude(legProfile001, length = 48)
|
||||||
|
|> rotate(axis = [0, 0, 1.0], angle = -90)
|
264
rust/kcl-lib/tests/sketch_on_face_union/ops.snap
Normal file
264
rust/kcl-lib/tests/sketch_on_face_union/ops.snap
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Operations executed sketch_on_face_union.kcl
|
||||||
|
---
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"labeledArgs": {},
|
||||||
|
"name": "startSketchOn",
|
||||||
|
"sourceRange": [],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Plane",
|
||||||
|
"artifact_id": "[uuid]"
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"labeledArgs": {
|
||||||
|
"tool": {
|
||||||
|
"value": {
|
||||||
|
"type": "Sketch",
|
||||||
|
"value": {
|
||||||
|
"artifactId": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "subtract2d",
|
||||||
|
"sourceRange": [],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Sketch",
|
||||||
|
"value": {
|
||||||
|
"artifactId": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"labeledArgs": {
|
||||||
|
"tool": {
|
||||||
|
"value": {
|
||||||
|
"type": "Sketch",
|
||||||
|
"value": {
|
||||||
|
"artifactId": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "subtract2d",
|
||||||
|
"sourceRange": [],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Sketch",
|
||||||
|
"value": {
|
||||||
|
"artifactId": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"labeledArgs": {
|
||||||
|
"length": {
|
||||||
|
"value": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 2.0,
|
||||||
|
"ty": {
|
||||||
|
"type": "Default",
|
||||||
|
"len": {
|
||||||
|
"type": "Inches"
|
||||||
|
},
|
||||||
|
"angle": {
|
||||||
|
"type": "Degrees"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "extrude",
|
||||||
|
"sourceRange": [],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Sketch",
|
||||||
|
"value": {
|
||||||
|
"artifactId": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"labeledArgs": {},
|
||||||
|
"name": "startSketchOn",
|
||||||
|
"sourceRange": [],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Plane",
|
||||||
|
"artifact_id": "[uuid]"
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "KclStdLibCall",
|
||||||
|
"name": "offsetPlane",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Plane",
|
||||||
|
"artifact_id": "[uuid]"
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
},
|
||||||
|
"labeledArgs": {
|
||||||
|
"offset": {
|
||||||
|
"value": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 0.1,
|
||||||
|
"ty": {
|
||||||
|
"type": "Default",
|
||||||
|
"len": {
|
||||||
|
"type": "Inches"
|
||||||
|
},
|
||||||
|
"angle": {
|
||||||
|
"type": "Degrees"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"labeledArgs": {
|
||||||
|
"length": {
|
||||||
|
"value": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 1.8,
|
||||||
|
"ty": {
|
||||||
|
"type": "Default",
|
||||||
|
"len": {
|
||||||
|
"type": "Inches"
|
||||||
|
},
|
||||||
|
"angle": {
|
||||||
|
"type": "Degrees"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "extrude",
|
||||||
|
"sourceRange": [],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Sketch",
|
||||||
|
"value": {
|
||||||
|
"artifactId": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"labeledArgs": {
|
||||||
|
"length": {
|
||||||
|
"value": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 1.8,
|
||||||
|
"ty": {
|
||||||
|
"type": "Default",
|
||||||
|
"len": {
|
||||||
|
"type": "Inches"
|
||||||
|
},
|
||||||
|
"angle": {
|
||||||
|
"type": "Degrees"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "extrude",
|
||||||
|
"sourceRange": [],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Sketch",
|
||||||
|
"value": {
|
||||||
|
"artifactId": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"labeledArgs": {
|
||||||
|
"face": {
|
||||||
|
"value": {
|
||||||
|
"type": "TagIdentifier",
|
||||||
|
"value": "bottomFace",
|
||||||
|
"artifact_id": "[uuid]"
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "startSketchOn",
|
||||||
|
"sourceRange": [],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Solid",
|
||||||
|
"value": {
|
||||||
|
"artifactId": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"labeledArgs": {
|
||||||
|
"length": {
|
||||||
|
"value": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 48.0,
|
||||||
|
"ty": {
|
||||||
|
"type": "Default",
|
||||||
|
"len": {
|
||||||
|
"type": "Inches"
|
||||||
|
},
|
||||||
|
"angle": {
|
||||||
|
"type": "Degrees"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "extrude",
|
||||||
|
"sourceRange": [],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": {
|
||||||
|
"value": {
|
||||||
|
"type": "Sketch",
|
||||||
|
"value": {
|
||||||
|
"artifactId": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
2639
rust/kcl-lib/tests/sketch_on_face_union/program_memory.snap
Normal file
2639
rust/kcl-lib/tests/sketch_on_face_union/program_memory.snap
Normal file
File diff suppressed because it is too large
Load Diff
BIN
rust/kcl-lib/tests/sketch_on_face_union/rendered_model.png
Normal file
BIN
rust/kcl-lib/tests/sketch_on_face_union/rendered_model.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
62
rust/kcl-lib/tests/sketch_on_face_union/unparsed.snap
Normal file
62
rust/kcl-lib/tests/sketch_on_face_union/unparsed.snap
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of unparsing sketch_on_face_union.kcl
|
||||||
|
---
|
||||||
|
@settings(defaultLengthUnit = in)
|
||||||
|
|
||||||
|
// Define parameters
|
||||||
|
trussSupportAngle = 15
|
||||||
|
height = 120
|
||||||
|
thickness = 4
|
||||||
|
|
||||||
|
sketch001 = startSketchOn(YZ)
|
||||||
|
profile001 = startProfile(sketch001, at = [60, 0])
|
||||||
|
|> xLine(length = -120, tag = $bottomFace)
|
||||||
|
|> yLine(length = 12)
|
||||||
|
|> angledLine(angle = 25, endAbsoluteX = 0, tag = $tag001)
|
||||||
|
|> angledLine(angle = -25, endAbsoluteX = 60)
|
||||||
|
|> close()
|
||||||
|
|
||||||
|
profile002 = startProfile(sketch001, at = [60 - thickness, thickness])
|
||||||
|
|> xLine(endAbsolute = thickness / 2)
|
||||||
|
|> yLine(endAbsolute = segEndY(tag001) - thickness) // update
|
||||||
|
|> angledLine(endAbsoluteX = profileStartX(%), angle = -25)
|
||||||
|
|> close(%)
|
||||||
|
|
||||||
|
profile003 = startProfile(sketch001, at = [-60 + thickness, thickness])
|
||||||
|
|> xLine(endAbsolute = -thickness / 2)
|
||||||
|
|> yLine(endAbsolute = segEndY(tag001) - thickness) // update
|
||||||
|
|> angledLine(endAbsoluteX = profileStartX(%), angle = 205)
|
||||||
|
|> close(%)
|
||||||
|
|
||||||
|
profile004 = subtract2d(profile001, tool = profile002)
|
||||||
|
subtract2d(profile001, tool = profile003)
|
||||||
|
|
||||||
|
body001 = extrude(profile001, length = 2)
|
||||||
|
|
||||||
|
sketch002 = startSketchOn(offsetPlane(YZ, offset = .1))
|
||||||
|
profile006 = startProfile(sketch002, at = [thickness / 2 - 1, 14])
|
||||||
|
|> angledLine(angle = 30, length = 25)
|
||||||
|
|> angledLine(angle = -25, length = 5)
|
||||||
|
|> angledLine(angle = 210, endAbsoluteX = profileStartX(%))
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(%, length = 1.8)
|
||||||
|
|
||||||
|
profile007 = startProfile(sketch002, at = [-thickness / 2 + 1, 14])
|
||||||
|
|> angledLine(angle = 150, length = 25)
|
||||||
|
|> angledLine(angle = 205, length = 5)
|
||||||
|
|> angledLine(angle = -30, endAbsoluteX = profileStartX(%))
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(%, length = 1.8)
|
||||||
|
|
||||||
|
newSketch = body001 + profile006 + profile007
|
||||||
|
|
||||||
|
leg001Sketch = startSketchOn(newSketch, face = bottomFace)
|
||||||
|
legProfile001 = startProfile(leg001Sketch, at = [-60, 0])
|
||||||
|
|> xLine(%, length = 4)
|
||||||
|
|> yLine(%, length = 2)
|
||||||
|
|> xLine(%, endAbsolute = profileStartX(%))
|
||||||
|
|> close(%)
|
||||||
|
|
||||||
|
leg001 = extrude(legProfile001, length = 48)
|
||||||
|
|> rotate(axis = [0, 0, 1.0], angle = -90)
|
@ -417,7 +417,8 @@ description: Artifact commands subtract_regression03.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -394,7 +394,8 @@ description: Artifact commands subtract_regression05.kcl
|
|||||||
"target": "[uuid]",
|
"target": "[uuid]",
|
||||||
"trajectory": "[uuid]",
|
"trajectory": "[uuid]",
|
||||||
"sectional": false,
|
"sectional": false,
|
||||||
"tolerance": 0.0000001
|
"tolerance": 0.0000001,
|
||||||
|
"relative_to": "trajectory_curve"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-python-bindings"
|
name = "kcl-python-bindings"
|
||||||
version = "0.3.69"
|
version = "0.3.71"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://github.com/kittycad/modeling-app"
|
repository = "https://github.com/kittycad/modeling-app"
|
||||||
exclude = ["tests/*", "files/*", "venv/*"]
|
exclude = ["tests/*", "files/*", "venv/*"]
|
||||||
|
@ -227,6 +227,31 @@ async fn new_context_state(current_file: Option<std::path::PathBuf>) -> Result<(
|
|||||||
Ok((ctx, state))
|
Ok((ctx, state))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse the kcl code from a file path.
|
||||||
|
#[pyfunction]
|
||||||
|
async fn parse(path: String) -> PyResult<()> {
|
||||||
|
tokio()
|
||||||
|
.spawn(async move {
|
||||||
|
let (code, path) = get_code_and_file_path(&path)
|
||||||
|
.await
|
||||||
|
.map_err(|err| pyo3::exceptions::PyException::new_err(err.to_string()))?;
|
||||||
|
let _program = kcl_lib::Program::parse_no_errs(&code)
|
||||||
|
.map_err(|err| into_miette_for_parse(&path.display().to_string(), &code, err))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.map_err(|err| pyo3::exceptions::PyException::new_err(err.to_string()))?
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse the kcl code.
|
||||||
|
#[pyfunction]
|
||||||
|
fn parse_code(code: String) -> PyResult<()> {
|
||||||
|
let _program = kcl_lib::Program::parse_no_errs(&code).map_err(|err| into_miette_for_parse("", &code, err))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Execute the kcl code from a file path.
|
/// Execute the kcl code from a file path.
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
async fn execute(path: String) -> PyResult<()> {
|
async fn execute(path: String) -> PyResult<()> {
|
||||||
@ -534,6 +559,8 @@ fn kcl(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|||||||
m.add_class::<Discovered>()?;
|
m.add_class::<Discovered>()?;
|
||||||
|
|
||||||
// Add our functions to the module.
|
// Add our functions to the module.
|
||||||
|
m.add_function(wrap_pyfunction!(parse, m)?)?;
|
||||||
|
m.add_function(wrap_pyfunction!(parse_code, m)?)?;
|
||||||
m.add_function(wrap_pyfunction!(execute, m)?)?;
|
m.add_function(wrap_pyfunction!(execute, m)?)?;
|
||||||
m.add_function(wrap_pyfunction!(execute_code, m)?)?;
|
m.add_function(wrap_pyfunction!(execute_code, m)?)?;
|
||||||
m.add_function(wrap_pyfunction!(execute_and_snapshot, m)?)?;
|
m.add_function(wrap_pyfunction!(execute_and_snapshot, m)?)?;
|
||||||
|
@ -39,6 +39,33 @@ async def test_kcl_execute():
|
|||||||
await kcl.execute(lego_file)
|
await kcl.execute(lego_file)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_kcl_parse_with_exception():
|
||||||
|
# Read from a file.
|
||||||
|
try:
|
||||||
|
await kcl.parse(os.path.join(files_dir, "parse_file_error"))
|
||||||
|
except Exception as e:
|
||||||
|
assert e is not None
|
||||||
|
assert len(str(e)) > 0
|
||||||
|
assert "lksjndflsskjfnak;jfna##" in str(e)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_kcl_parse():
|
||||||
|
# Read from a file.
|
||||||
|
await kcl.parse(lego_file)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_kcl_parse_code():
|
||||||
|
# Read from a file.
|
||||||
|
with open(lego_file, "r") as f:
|
||||||
|
code = str(f.read())
|
||||||
|
assert code is not None
|
||||||
|
assert len(code) > 0
|
||||||
|
kcl.parse_code(code)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_kcl_execute_code():
|
async def test_kcl_execute_code():
|
||||||
# Read from a file.
|
# Read from a file.
|
||||||
@ -97,9 +124,7 @@ async def test_kcl_execute_and_snapshot():
|
|||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_kcl_execute_and_snapshot_dir():
|
async def test_kcl_execute_and_snapshot_dir():
|
||||||
# Read from a file.
|
# Read from a file.
|
||||||
image_bytes = await kcl.execute_and_snapshot(
|
image_bytes = await kcl.execute_and_snapshot(car_wheel_dir, kcl.ImageFormat.Jpeg)
|
||||||
car_wheel_dir, kcl.ImageFormat.Jpeg
|
|
||||||
)
|
|
||||||
assert image_bytes is not None
|
assert image_bytes is not None
|
||||||
assert len(image_bytes) > 0
|
assert len(image_bytes) > 0
|
||||||
|
|
||||||
@ -129,10 +154,12 @@ def test_kcl_format():
|
|||||||
assert formatted_code is not None
|
assert formatted_code is not None
|
||||||
assert len(formatted_code) > 0
|
assert len(formatted_code) > 0
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_kcl_format_dir():
|
async def test_kcl_format_dir():
|
||||||
await kcl.format_dir(car_wheel_dir)
|
await kcl.format_dir(car_wheel_dir)
|
||||||
|
|
||||||
|
|
||||||
def test_kcl_lint():
|
def test_kcl_lint():
|
||||||
# Read from a file.
|
# Read from a file.
|
||||||
with open(os.path.join(files_dir, "box_with_linter_errors.kcl"), "r") as f:
|
with open(os.path.join(files_dir, "box_with_linter_errors.kcl"), "r") as f:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-test-server"
|
name = "kcl-test-server"
|
||||||
description = "A test server for KCL"
|
description = "A test server for KCL"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-to-core"
|
name = "kcl-to-core"
|
||||||
description = "Utility methods to convert kcl to engine core executable tests"
|
description = "Utility methods to convert kcl to engine core executable tests"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-wasm-lib"
|
name = "kcl-wasm-lib"
|
||||||
version = "0.1.69"
|
version = "0.1.71"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
rust-version = "1.83"
|
rust-version = "1.83"
|
||||||
|
17
src/App.tsx
17
src/App.tsx
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
import ModalContainer from 'react-modal-promise'
|
import ModalContainer from 'react-modal-promise'
|
||||||
@ -42,6 +42,7 @@ import {
|
|||||||
ONBOARDING_TOAST_ID,
|
ONBOARDING_TOAST_ID,
|
||||||
TutorialRequestToast,
|
TutorialRequestToast,
|
||||||
} from '@src/routes/Onboarding/utils'
|
} from '@src/routes/Onboarding/utils'
|
||||||
|
import { reportRejection } from '@src/lib/trap'
|
||||||
|
|
||||||
// CYCLIC REF
|
// CYCLIC REF
|
||||||
sceneInfra.camControls.engineStreamActor = engineStreamActor
|
sceneInfra.camControls.engineStreamActor = engineStreamActor
|
||||||
@ -52,6 +53,7 @@ maybeWriteToDisk()
|
|||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
const { project, file } = useLoaderData() as IndexLoaderData
|
const { project, file } = useLoaderData() as IndexLoaderData
|
||||||
|
const [nativeFileMenuCreated, setNativeFileMenuCreated] = useState(false)
|
||||||
|
|
||||||
// Keep a lookout for a URL query string that invokes the 'import file from URL' command
|
// Keep a lookout for a URL query string that invokes the 'import file from URL' command
|
||||||
useCreateFileLinkQuery((argDefaultValues) => {
|
useCreateFileLinkQuery((argDefaultValues) => {
|
||||||
@ -145,12 +147,25 @@ export function App() {
|
|||||||
}
|
}
|
||||||
}, [location, settings.app.onboardingStatus, navigate])
|
}, [location, settings.app.onboardingStatus, navigate])
|
||||||
|
|
||||||
|
// Only create the native file menus on desktop
|
||||||
|
useEffect(() => {
|
||||||
|
if (isDesktop()) {
|
||||||
|
window.electron
|
||||||
|
.createModelingPageMenu()
|
||||||
|
.then(() => {
|
||||||
|
setNativeFileMenuCreated(true)
|
||||||
|
})
|
||||||
|
.catch(reportRejection)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative h-full flex flex-col" ref={ref}>
|
<div className="relative h-full flex flex-col" ref={ref}>
|
||||||
<AppHeader
|
<AppHeader
|
||||||
className="transition-opacity transition-duration-75"
|
className="transition-opacity transition-duration-75"
|
||||||
project={{ project, file }}
|
project={{ project, file }}
|
||||||
enableMenu={true}
|
enableMenu={true}
|
||||||
|
nativeFileMenuCreated={nativeFileMenuCreated}
|
||||||
>
|
>
|
||||||
<CommandBarOpenButton />
|
<CommandBarOpenButton />
|
||||||
<ShareButton />
|
<ShareButton />
|
||||||
|
@ -14,6 +14,7 @@ interface AppHeaderProps extends React.PropsWithChildren {
|
|||||||
className?: string
|
className?: string
|
||||||
enableMenu?: boolean
|
enableMenu?: boolean
|
||||||
style?: React.CSSProperties
|
style?: React.CSSProperties
|
||||||
|
nativeFileMenuCreated: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AppHeader = ({
|
export const AppHeader = ({
|
||||||
@ -23,12 +24,14 @@ export const AppHeader = ({
|
|||||||
className = '',
|
className = '',
|
||||||
style,
|
style,
|
||||||
enableMenu = false,
|
enableMenu = false,
|
||||||
|
nativeFileMenuCreated,
|
||||||
}: AppHeaderProps) => {
|
}: AppHeaderProps) => {
|
||||||
const user = useUser()
|
const user = useUser()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
id="app-header"
|
id="app-header"
|
||||||
|
data-testid="app-header"
|
||||||
className={
|
className={
|
||||||
'w-full grid ' +
|
'w-full grid ' +
|
||||||
styles.header +
|
styles.header +
|
||||||
@ -37,6 +40,7 @@ export const AppHeader = ({
|
|||||||
}overlaid-panes sticky top-0 z-20 px-2 items-start ` +
|
}overlaid-panes sticky top-0 z-20 px-2 items-start ` +
|
||||||
className
|
className
|
||||||
}
|
}
|
||||||
|
data-native-file-menu={nativeFileMenuCreated}
|
||||||
style={style}
|
style={style}
|
||||||
>
|
>
|
||||||
<ProjectSidebarMenu
|
<ProjectSidebarMenu
|
||||||
|
@ -169,6 +169,7 @@ export const CommandBar = () => {
|
|||||||
)}
|
)}
|
||||||
<div className="flex flex-col gap-2 !absolute left-auto right-full top-[-3px] m-2.5 p-0 border-none bg-transparent hover:bg-transparent">
|
<div className="flex flex-col gap-2 !absolute left-auto right-full top-[-3px] m-2.5 p-0 border-none bg-transparent hover:bg-transparent">
|
||||||
<button
|
<button
|
||||||
|
data-testid="command-bar-close-button"
|
||||||
onClick={() => commandBarActor.send({ type: 'Close' })}
|
onClick={() => commandBarActor.send({ type: 'Close' })}
|
||||||
className="group m-0 p-0 border-none bg-transparent hover:bg-transparent"
|
className="group m-0 p-0 border-none bg-transparent hover:bg-transparent"
|
||||||
>
|
>
|
||||||
|
@ -29,15 +29,9 @@ import { useSelector } from '@xstate/react'
|
|||||||
import type { MouseEventHandler } from 'react'
|
import type { MouseEventHandler } from 'react'
|
||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { useRouteLoaderData } from 'react-router-dom'
|
import { useRouteLoaderData } from 'react-router-dom'
|
||||||
import { isPlaywright } from '@src/lib/isPlaywright'
|
|
||||||
import {
|
|
||||||
engineStreamZoomToFit,
|
|
||||||
engineViewIsometricWithGeometryPresent,
|
|
||||||
engineViewIsometricWithoutGeometryPresent,
|
|
||||||
} from '@src/lib/utils'
|
|
||||||
import { DEFAULT_DEFAULT_LENGTH_UNIT } from '@src/lib/constants'
|
|
||||||
import { createThumbnailPNGOnDesktop } from '@src/lib/screenshot'
|
import { createThumbnailPNGOnDesktop } from '@src/lib/screenshot'
|
||||||
import type { SettingsViaQueryString } from '@src/lib/settings/settingsTypes'
|
import type { SettingsViaQueryString } from '@src/lib/settings/settingsTypes'
|
||||||
|
import { resetCameraPosition } from '@src/lib/resetCameraPosition'
|
||||||
|
|
||||||
export const EngineStream = (props: {
|
export const EngineStream = (props: {
|
||||||
pool: string | null
|
pool: string | null
|
||||||
@ -104,31 +98,7 @@ export const EngineStream = (props: {
|
|||||||
|
|
||||||
kmp
|
kmp
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
// Gotcha: Playwright E2E tests will be zoom_to_fit, when you try to recreate the e2e test manually
|
await resetCameraPosition()
|
||||||
// your localhost will do view_isometric. Turn this boolean on to have the same experience when manually
|
|
||||||
// debugging e2e tests
|
|
||||||
|
|
||||||
// We need a padding of 0.1 for zoom_to_fit for all E2E tests since they were originally
|
|
||||||
// written with zoom_to_fit with padding 0.1
|
|
||||||
const padding = 0.1
|
|
||||||
if (isPlaywright()) {
|
|
||||||
await engineStreamZoomToFit({ engineCommandManager, padding })
|
|
||||||
} else {
|
|
||||||
// If the scene is empty you cannot use view_isometric, it will not move the camera
|
|
||||||
if (kclManager.isAstBodyEmpty(kclManager.ast)) {
|
|
||||||
await engineViewIsometricWithoutGeometryPresent({
|
|
||||||
engineCommandManager,
|
|
||||||
unit:
|
|
||||||
kclManager.fileSettings.defaultLengthUnit ||
|
|
||||||
DEFAULT_DEFAULT_LENGTH_UNIT,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
await engineViewIsometricWithGeometryPresent({
|
|
||||||
engineCommandManager,
|
|
||||||
padding,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (project && project.path) {
|
if (project && project.path) {
|
||||||
createThumbnailPNGOnDesktop({
|
createThumbnailPNGOnDesktop({
|
||||||
|
@ -29,7 +29,7 @@ import { kclCommands } from '@src/lib/kclCommands'
|
|||||||
import { BROWSER_PATH, PATHS } from '@src/lib/paths'
|
import { BROWSER_PATH, PATHS } from '@src/lib/paths'
|
||||||
import { markOnce } from '@src/lib/performance'
|
import { markOnce } from '@src/lib/performance'
|
||||||
import { codeManager, kclManager } from '@src/lib/singletons'
|
import { codeManager, kclManager } from '@src/lib/singletons'
|
||||||
import { err, reportRejection } from '@src/lib/trap'
|
import { err } from '@src/lib/trap'
|
||||||
import { type IndexLoaderData } from '@src/lib/types'
|
import { type IndexLoaderData } from '@src/lib/types'
|
||||||
import { useSettings, useToken } from '@src/lib/singletons'
|
import { useSettings, useToken } from '@src/lib/singletons'
|
||||||
import { commandBarActor } from '@src/lib/singletons'
|
import { commandBarActor } from '@src/lib/singletons'
|
||||||
@ -59,12 +59,6 @@ export const FileMachineProvider = ({
|
|||||||
const { project, file } = projectData
|
const { project, file } = projectData
|
||||||
|
|
||||||
const filePath = useAbsoluteFilePath()
|
const filePath = useAbsoluteFilePath()
|
||||||
// Only create the native file menus on desktop
|
|
||||||
useEffect(() => {
|
|
||||||
if (isDesktop()) {
|
|
||||||
window.electron.createModelingPageMenu().catch(reportRejection)
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const {
|
const {
|
||||||
|
@ -13,6 +13,7 @@ import { VIEW_NAMES_SEMANTIC } from '@src/lib/constants'
|
|||||||
import { sceneInfra } from '@src/lib/singletons'
|
import { sceneInfra } from '@src/lib/singletons'
|
||||||
import { reportRejection } from '@src/lib/trap'
|
import { reportRejection } from '@src/lib/trap'
|
||||||
import { useSettings } from '@src/lib/singletons'
|
import { useSettings } from '@src/lib/singletons'
|
||||||
|
import { resetCameraPosition } from '@src/lib/resetCameraPosition'
|
||||||
|
|
||||||
export function useViewControlMenuItems() {
|
export function useViewControlMenuItems() {
|
||||||
const { state: modelingState, send: modelingSend } = useModelingContext()
|
const { state: modelingState, send: modelingSend } = useModelingContext()
|
||||||
@ -38,7 +39,7 @@ export function useViewControlMenuItems() {
|
|||||||
<ContextMenuDivider />,
|
<ContextMenuDivider />,
|
||||||
<ContextMenuItem
|
<ContextMenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
sceneInfra.camControls.resetCameraPosition().catch(reportRejection)
|
resetCameraPosition().catch(reportRejection)
|
||||||
}}
|
}}
|
||||||
disabled={shouldLockView}
|
disabled={shouldLockView}
|
||||||
>
|
>
|
||||||
|
@ -111,7 +111,7 @@ function discoverColorsInKCL(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function parseColorLiteral(colorLiteral: string): ColorData | null {
|
export function parseColorLiteral(colorLiteral: string): ColorData | null {
|
||||||
const literal = colorLiteral.replace(/"/g, '')
|
const literal = colorLiteral.replace(/"/g, '').replace(/'/g, '')
|
||||||
const match = hexRegex.exec(literal)
|
const match = hexRegex.exec(literal)
|
||||||
if (!match) {
|
if (!match) {
|
||||||
return null
|
return null
|
||||||
|
@ -212,6 +212,12 @@ code {
|
|||||||
z-index: 99999999999 !important;
|
z-index: 99999999999 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cm-rename-popup input {
|
||||||
|
/* use black text on white background in both light and dark mode */
|
||||||
|
color: black !important;
|
||||||
|
background: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes blink {
|
@keyframes blink {
|
||||||
0%,
|
0%,
|
||||||
100% {
|
100% {
|
||||||
|
@ -147,6 +147,14 @@ export class KclManager {
|
|||||||
|
|
||||||
set switchedFiles(switchedFiles: boolean) {
|
set switchedFiles(switchedFiles: boolean) {
|
||||||
this._switchedFiles = switchedFiles
|
this._switchedFiles = switchedFiles
|
||||||
|
|
||||||
|
// These belonged to the previous file
|
||||||
|
this.lastSuccessfulOperations = []
|
||||||
|
this.lastSuccessfulVariables = {}
|
||||||
|
|
||||||
|
// Without this, when leaving a project which has errors and opening another project which doesn't,
|
||||||
|
// you'd see the errors from the previous project for a short time until the new code is executed.
|
||||||
|
this._errors = []
|
||||||
}
|
}
|
||||||
|
|
||||||
get variables() {
|
get variables() {
|
||||||
|
@ -23,7 +23,7 @@ import {
|
|||||||
getThemeColorForEngine,
|
getThemeColorForEngine,
|
||||||
} from '@src/lib/theme'
|
} from '@src/lib/theme'
|
||||||
import { reportRejection } from '@src/lib/trap'
|
import { reportRejection } from '@src/lib/trap'
|
||||||
import { binaryToUuid, uuidv4 } from '@src/lib/utils'
|
import { binaryToUuid, isArray, uuidv4 } from '@src/lib/utils'
|
||||||
|
|
||||||
const pingIntervalMs = 1_000
|
const pingIntervalMs = 1_000
|
||||||
|
|
||||||
@ -2010,12 +2010,20 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
return Promise.reject(EXECUTE_AST_INTERRUPT_ERROR_MESSAGE)
|
return Promise.reject(EXECUTE_AST_INTERRUPT_ERROR_MESSAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
const resp = await this.sendCommand(id, {
|
try {
|
||||||
command,
|
const resp = await this.sendCommand(id, {
|
||||||
range,
|
command,
|
||||||
idToRangeMap,
|
range,
|
||||||
})
|
idToRangeMap,
|
||||||
return BSON.serialize(resp[0])
|
})
|
||||||
|
return BSON.serialize(resp[0])
|
||||||
|
} catch (e) {
|
||||||
|
if (isArray(e) && e.length > 0) {
|
||||||
|
return Promise.reject(JSON.stringify(e[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.reject(JSON.stringify(e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Common send command function used for both modeling and scene commands
|
* Common send command function used for both modeling and scene commands
|
||||||
|
@ -31,7 +31,7 @@ const save_ = async (file: ModelingAppFile, toastId: string) => {
|
|||||||
)
|
)
|
||||||
toast.success(EXPORT_TOAST_MESSAGES.SUCCESS + ' [TEST]', {
|
toast.success(EXPORT_TOAST_MESSAGES.SUCCESS + ' [TEST]', {
|
||||||
id: toastId,
|
id: toastId,
|
||||||
duration: 5_000,
|
duration: 10_000,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
40
src/lib/resetCameraPosition.ts
Normal file
40
src/lib/resetCameraPosition.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { DEFAULT_DEFAULT_LENGTH_UNIT } from '@src/lib/constants'
|
||||||
|
import { isPlaywright } from '@src/lib/isPlaywright'
|
||||||
|
import { engineCommandManager, kclManager } from '@src/lib/singletons'
|
||||||
|
import {
|
||||||
|
engineStreamZoomToFit,
|
||||||
|
engineViewIsometricWithoutGeometryPresent,
|
||||||
|
engineViewIsometricWithGeometryPresent,
|
||||||
|
} from '@src/lib/utils'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the camera position to a baseline, which is isometric for
|
||||||
|
* normal users and a deprecated "front-down" view for playwright tests.
|
||||||
|
*
|
||||||
|
* Gotcha: Playwright E2E tests will be zoom_to_fit, when you try to recreate the e2e test manually
|
||||||
|
* your localhost will do view_isometric. Turn this boolean on to have the same experience when manually
|
||||||
|
* debugging e2e tests
|
||||||
|
*/
|
||||||
|
export async function resetCameraPosition() {
|
||||||
|
// We need a padding of 0.1 for zoom_to_fit for all E2E tests since they were originally
|
||||||
|
// written with zoom_to_fit with padding 0.1
|
||||||
|
const padding = 0.1
|
||||||
|
if (isPlaywright()) {
|
||||||
|
await engineStreamZoomToFit({ engineCommandManager, padding })
|
||||||
|
} else {
|
||||||
|
// If the scene is empty you cannot use view_isometric, it will not move the camera
|
||||||
|
if (kclManager.isAstBodyEmpty(kclManager.ast)) {
|
||||||
|
await engineViewIsometricWithoutGeometryPresent({
|
||||||
|
engineCommandManager,
|
||||||
|
unit:
|
||||||
|
kclManager.fileSettings.defaultLengthUnit ||
|
||||||
|
DEFAULT_DEFAULT_LENGTH_UNIT,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
await engineViewIsometricWithGeometryPresent({
|
||||||
|
engineCommandManager,
|
||||||
|
padding,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -139,18 +139,20 @@ export const settingsMachine = setup({
|
|||||||
return () => darkModeMatcher?.removeEventListener('change', listener)
|
return () => darkModeMatcher?.removeEventListener('change', listener)
|
||||||
}),
|
}),
|
||||||
registerCommands: fromCallback<
|
registerCommands: fromCallback<
|
||||||
{ type: 'update' },
|
{ type: 'update'; settings: SettingsType },
|
||||||
{ settings: SettingsType; actor: AnyActorRef }
|
{ settings: SettingsType; actor: AnyActorRef }
|
||||||
>(({ input, receive, system }) => {
|
>(({ input, receive, system }) => {
|
||||||
// This assumes this actor is running in a system with a command palette
|
// This assumes this actor is running in a system with a command palette
|
||||||
const commandBarActor = system.get(ACTOR_IDS.COMMAND_BAR)
|
const commandBarActor = system.get(ACTOR_IDS.COMMAND_BAR)
|
||||||
// If the user wants to hide the settings commands
|
// If the user wants to hide the settings commands
|
||||||
//from the command bar don't add them.
|
//from the command bar don't add them.
|
||||||
if (settings.commandBar.includeSettings.current === false) return
|
if (settings.commandBar.includeSettings.current === false) {
|
||||||
|
return
|
||||||
|
}
|
||||||
let commands: Command[] = []
|
let commands: Command[] = []
|
||||||
|
|
||||||
const updateCommands = () =>
|
const updateCommands = (newSettings: SettingsType) =>
|
||||||
settingsWithCommandConfigs(input.settings)
|
settingsWithCommandConfigs(newSettings)
|
||||||
.map((type) =>
|
.map((type) =>
|
||||||
createSettingsCommand({
|
createSettingsCommand({
|
||||||
type,
|
type,
|
||||||
@ -175,14 +177,19 @@ export const settingsMachine = setup({
|
|||||||
data: { commands: commands },
|
data: { commands: commands },
|
||||||
})
|
})
|
||||||
|
|
||||||
receive((event) => {
|
receive(({ type, settings: newSettings }) => {
|
||||||
if (event.type !== 'update') return
|
if (type !== 'update') {
|
||||||
|
return
|
||||||
|
}
|
||||||
removeCommands()
|
removeCommands()
|
||||||
commands = updateCommands()
|
commands =
|
||||||
|
newSettings.commandBar.includeSettings.current === false
|
||||||
|
? []
|
||||||
|
: updateCommands(newSettings)
|
||||||
addCommands()
|
addCommands()
|
||||||
})
|
})
|
||||||
|
|
||||||
commands = updateCommands()
|
commands = updateCommands(settings)
|
||||||
addCommands()
|
addCommands()
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@ -205,7 +212,9 @@ export const settingsMachine = setup({
|
|||||||
const sceneInfra = rootContext.sceneInfra
|
const sceneInfra = rootContext.sceneInfra
|
||||||
const sceneEntitiesManager = rootContext.sceneEntitiesManager
|
const sceneEntitiesManager = rootContext.sceneEntitiesManager
|
||||||
|
|
||||||
if (!sceneInfra || !sceneEntitiesManager) return
|
if (!sceneInfra || !sceneEntitiesManager) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const opposingTheme = getOppositeTheme(context.app.theme.current)
|
const opposingTheme = getOppositeTheme(context.app.theme.current)
|
||||||
sceneInfra.theme = opposingTheme
|
sceneInfra.theme = opposingTheme
|
||||||
sceneEntitiesManager.updateSegmentBaseColor(opposingTheme)
|
sceneEntitiesManager.updateSegmentBaseColor(opposingTheme)
|
||||||
@ -213,13 +222,17 @@ export const settingsMachine = setup({
|
|||||||
setAllowOrbitInSketchMode: ({ context, self }) => {
|
setAllowOrbitInSketchMode: ({ context, self }) => {
|
||||||
const rootContext = self.system.get('root').getSnapshot().context
|
const rootContext = self.system.get('root').getSnapshot().context
|
||||||
const sceneInfra = rootContext.sceneInfra
|
const sceneInfra = rootContext.sceneInfra
|
||||||
if (!sceneInfra.camControls) return
|
if (!sceneInfra.camControls) {
|
||||||
|
return
|
||||||
|
}
|
||||||
sceneInfra.camControls._setting_allowOrbitInSketchMode =
|
sceneInfra.camControls._setting_allowOrbitInSketchMode =
|
||||||
context.app.allowOrbitInSketchMode.current
|
context.app.allowOrbitInSketchMode.current
|
||||||
// ModelingMachineProvider will do a use effect to trigger the camera engine sync
|
// ModelingMachineProvider will do a use effect to trigger the camera engine sync
|
||||||
},
|
},
|
||||||
toastSuccess: ({ event }) => {
|
toastSuccess: ({ event }) => {
|
||||||
if (!('data' in event)) return
|
if (!('data' in event)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const eventParts = event.type.replace(/^set./, '').split('.') as [
|
const eventParts = event.type.replace(/^set./, '').split('.') as [
|
||||||
keyof typeof settings,
|
keyof typeof settings,
|
||||||
string,
|
string,
|
||||||
@ -435,6 +448,22 @@ export const settingsMachine = setup({
|
|||||||
actions: ['setSettingAtLevel', 'setThemeColor'],
|
actions: ['setSettingAtLevel', 'setThemeColor'],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'set.commandBar.includeSettings': {
|
||||||
|
target: 'persisting settings',
|
||||||
|
|
||||||
|
actions: [
|
||||||
|
'setSettingAtLevel',
|
||||||
|
'toastSuccess',
|
||||||
|
sendTo(
|
||||||
|
'registerCommands',
|
||||||
|
({ context: { currentProject: _, ...settings } }) => ({
|
||||||
|
type: 'update',
|
||||||
|
settings,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
'set.modeling.defaultUnit': {
|
'set.modeling.defaultUnit': {
|
||||||
target: 'persisting settings',
|
target: 'persisting settings',
|
||||||
|
|
||||||
@ -497,6 +526,13 @@ export const settingsMachine = setup({
|
|||||||
'setClientTheme',
|
'setClientTheme',
|
||||||
'setAllowOrbitInSketchMode',
|
'setAllowOrbitInSketchMode',
|
||||||
'sendThemeToWatcher',
|
'sendThemeToWatcher',
|
||||||
|
sendTo(
|
||||||
|
'registerCommands',
|
||||||
|
({ context: { currentProject: _, ...settings } }) => ({
|
||||||
|
type: 'update',
|
||||||
|
settings,
|
||||||
|
})
|
||||||
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -510,6 +546,13 @@ export const settingsMachine = setup({
|
|||||||
'setClientTheme',
|
'setClientTheme',
|
||||||
'setAllowOrbitInSketchMode',
|
'setAllowOrbitInSketchMode',
|
||||||
'sendThemeToWatcher',
|
'sendThemeToWatcher',
|
||||||
|
sendTo(
|
||||||
|
'registerCommands',
|
||||||
|
({ context: { currentProject: _, ...settings } }) => ({
|
||||||
|
type: 'update',
|
||||||
|
settings,
|
||||||
|
})
|
||||||
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -529,7 +572,13 @@ export const settingsMachine = setup({
|
|||||||
'clearProjectSettings',
|
'clearProjectSettings',
|
||||||
'clearCurrentProject',
|
'clearCurrentProject',
|
||||||
'setThemeColor',
|
'setThemeColor',
|
||||||
sendTo('registerCommands', { type: 'update' }),
|
sendTo(
|
||||||
|
'registerCommands',
|
||||||
|
({ context: { currentProject: _, ...settings } }) => ({
|
||||||
|
type: 'update',
|
||||||
|
settings,
|
||||||
|
})
|
||||||
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -582,6 +631,13 @@ export const settingsMachine = setup({
|
|||||||
'setClientTheme',
|
'setClientTheme',
|
||||||
'setAllowOrbitInSketchMode',
|
'setAllowOrbitInSketchMode',
|
||||||
'sendThemeToWatcher',
|
'sendThemeToWatcher',
|
||||||
|
sendTo(
|
||||||
|
'registerCommands',
|
||||||
|
({ context: { currentProject: _, ...settings } }) => ({
|
||||||
|
type: 'update',
|
||||||
|
settings,
|
||||||
|
})
|
||||||
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
onError: {
|
onError: {
|
||||||
@ -612,7 +668,13 @@ export const settingsMachine = setup({
|
|||||||
'setClientTheme',
|
'setClientTheme',
|
||||||
'setAllowOrbitInSketchMode',
|
'setAllowOrbitInSketchMode',
|
||||||
'sendThemeToWatcher',
|
'sendThemeToWatcher',
|
||||||
sendTo('registerCommands', { type: 'update' }),
|
sendTo(
|
||||||
|
'registerCommands',
|
||||||
|
({ context: { currentProject: _, ...settings } }) => ({
|
||||||
|
type: 'update',
|
||||||
|
settings,
|
||||||
|
})
|
||||||
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
onError: 'idle',
|
onError: 'idle',
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { FormEvent, HTMLProps } from 'react'
|
import type { FormEvent, HTMLProps } from 'react'
|
||||||
import { useEffect } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { toast } from 'react-hot-toast'
|
import { toast } from 'react-hot-toast'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
import {
|
import {
|
||||||
@ -70,13 +70,20 @@ type ReadWriteProjectState = {
|
|||||||
// This route only opens in the desktop context for now,
|
// This route only opens in the desktop context for now,
|
||||||
// as defined in Router.tsx, so we can use the desktop APIs and types.
|
// as defined in Router.tsx, so we can use the desktop APIs and types.
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
|
const navigate = useNavigate()
|
||||||
const readWriteProjectDir = useCanReadWriteProjectDirectory()
|
const readWriteProjectDir = useCanReadWriteProjectDirectory()
|
||||||
|
const [nativeFileMenuCreated, setNativeFileMenuCreated] = useState(false)
|
||||||
const apiToken = useToken()
|
const apiToken = useToken()
|
||||||
|
|
||||||
// Only create the native file menus on desktop
|
// Only create the native file menus on desktop
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isDesktop()) {
|
if (isDesktop()) {
|
||||||
window.electron.createHomePageMenu().catch(reportRejection)
|
window.electron
|
||||||
|
.createHomePageMenu()
|
||||||
|
.then(() => {
|
||||||
|
setNativeFileMenuCreated(true)
|
||||||
|
})
|
||||||
|
.catch(reportRejection)
|
||||||
}
|
}
|
||||||
billingActor.send({ type: BillingTransition.Update, apiToken })
|
billingActor.send({ type: BillingTransition.Update, apiToken })
|
||||||
}, [])
|
}, [])
|
||||||
@ -94,7 +101,6 @@ const Home = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const navigate = useNavigate()
|
|
||||||
const settings = useSettings()
|
const settings = useSettings()
|
||||||
const onboardingStatus = settings.app.onboardingStatus.current
|
const onboardingStatus = settings.app.onboardingStatus.current
|
||||||
|
|
||||||
@ -217,7 +223,10 @@ const Home = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative flex flex-col items-stretch h-screen w-screen overflow-hidden">
|
<div className="relative flex flex-col items-stretch h-screen w-screen overflow-hidden">
|
||||||
<AppHeader showToolbar={false} />
|
<AppHeader
|
||||||
|
nativeFileMenuCreated={nativeFileMenuCreated}
|
||||||
|
showToolbar={false}
|
||||||
|
/>
|
||||||
<div className="overflow-hidden self-stretch w-full flex-1 home-layout max-w-4xl lg:max-w-5xl xl:max-w-7xl mb-12 px-4 mx-auto mt-8 lg:mt-24 lg:px-0">
|
<div className="overflow-hidden self-stretch w-full flex-1 home-layout max-w-4xl lg:max-w-5xl xl:max-w-7xl mb-12 px-4 mx-auto mt-8 lg:mt-24 lg:px-0">
|
||||||
<HomeHeader
|
<HomeHeader
|
||||||
setQuery={setQuery}
|
setQuery={setQuery}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Dialog, Transition } from '@headlessui/react'
|
import { Dialog, Transition } from '@headlessui/react'
|
||||||
import { Fragment, useEffect, useRef } from 'react'
|
import { Fragment, useEffect, useRef } from 'react'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
|
||||||
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'
|
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'
|
||||||
|
|
||||||
import { CustomIcon } from '@src/components/CustomIcon'
|
import { CustomIcon } from '@src/components/CustomIcon'
|
||||||
@ -10,14 +9,19 @@ import { KeybindingsSectionsList } from '@src/components/Settings/KeybindingsSec
|
|||||||
import { SettingsSearchBar } from '@src/components/Settings/SettingsSearchBar'
|
import { SettingsSearchBar } from '@src/components/Settings/SettingsSearchBar'
|
||||||
import { SettingsSectionsList } from '@src/components/Settings/SettingsSectionsList'
|
import { SettingsSectionsList } from '@src/components/Settings/SettingsSectionsList'
|
||||||
import { SettingsTabs } from '@src/components/Settings/SettingsTabs'
|
import { SettingsTabs } from '@src/components/Settings/SettingsTabs'
|
||||||
import { useDotDotSlash } from '@src/hooks/useDotDotSlash'
|
|
||||||
import { PATHS } from '@src/lib/paths'
|
import { PATHS } from '@src/lib/paths'
|
||||||
import type { SettingsLevel } from '@src/lib/settings/settingsTypes'
|
import type { SettingsLevel } from '@src/lib/settings/settingsTypes'
|
||||||
|
|
||||||
export const Settings = () => {
|
export const Settings = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const [searchParams, setSearchParams] = useSearchParams()
|
const [searchParams, setSearchParams] = useSearchParams()
|
||||||
const close = () => navigate(location.pathname.replace(PATHS.SETTINGS, ''))
|
const close = () => {
|
||||||
|
// This makes sure input texts are saved before closing the dialog (eg. default project name).
|
||||||
|
if (document.activeElement instanceof HTMLInputElement) {
|
||||||
|
document.activeElement.blur()
|
||||||
|
}
|
||||||
|
navigate(location.pathname.replace(PATHS.SETTINGS, ''))
|
||||||
|
}
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const isFileSettings = location.pathname.includes(PATHS.FILE)
|
const isFileSettings = location.pathname.includes(PATHS.FILE)
|
||||||
const searchParamTab =
|
const searchParamTab =
|
||||||
@ -25,20 +29,21 @@ export const Settings = () => {
|
|||||||
(isFileSettings ? 'project' : 'user')
|
(isFileSettings ? 'project' : 'user')
|
||||||
|
|
||||||
const scrollRef = useRef<HTMLDivElement>(null)
|
const scrollRef = useRef<HTMLDivElement>(null)
|
||||||
const dotDotSlash = useDotDotSlash()
|
|
||||||
useHotkeys('esc', () => navigate(dotDotSlash()))
|
|
||||||
|
|
||||||
// Scroll to the hash on load if it exists
|
// Scroll to the hash on load if it exists
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('hash', location.hash)
|
console.log('hash', location.hash)
|
||||||
if (location.hash) {
|
if (location.hash) {
|
||||||
const element = document.getElementById(location.hash.slice(1))
|
setTimeout(() => {
|
||||||
if (element) {
|
// GOTCHA: Next tick required, you can instantly navigate to a path and this code will find a null element and not scroll into view.
|
||||||
element.scrollIntoView({ block: 'center', behavior: 'smooth' })
|
const element = document.getElementById(location.hash.slice(1))
|
||||||
;(
|
if (element) {
|
||||||
element.querySelector('input, select, textarea') as HTMLInputElement
|
element.scrollIntoView({ block: 'center', behavior: 'smooth' })
|
||||||
)?.focus()
|
;(
|
||||||
}
|
element.querySelector('input, select, textarea') as HTMLInputElement
|
||||||
|
)?.focus()
|
||||||
|
}
|
||||||
|
}, 0)
|
||||||
}
|
}
|
||||||
}, [location.hash])
|
}, [location.hash])
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user