BREAKING: KCL @settings are the source of truth for units (#5808)

This commit is contained in:
Jonathan Tran
2025-03-31 10:56:03 -04:00
committed by GitHub
parent eac5abba79
commit efc8c82d8b
237 changed files with 820 additions and 2146 deletions

View File

@ -85,7 +85,7 @@ async function doBasicSketch(
await page.mouse.click(startXPx, 500 - PUR * 20) await page.mouse.click(startXPx, 500 - PUR * 20)
if (openPanes.includes('code')) { if (openPanes.includes('code')) {
await expect(u.codeLocator) await expect(u.codeLocator)
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${ .toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
commonPoints.startAt commonPoints.startAt
}, sketch001) }, sketch001)
|> xLine(length = ${commonPoints.num1}) |> xLine(length = ${commonPoints.num1})
@ -119,10 +119,7 @@ async function doBasicSketch(
await page.waitForTimeout(100) await page.waitForTimeout(100)
if (openPanes.includes('code')) { if (openPanes.includes('code')) {
await expect( expect(await u.getGreatestPixDiff(line1, TEST_COLORS.BLUE)).toBeLessThan(3)
await u.getGreatestPixDiff(line1, TEST_COLORS.BLUE)
).toBeLessThan(3)
await expect(await u.getGreatestPixDiff(line1, [0, 0, 255])).toBeLessThan(3)
} }
// hold down shift // hold down shift
@ -145,7 +142,7 @@ async function doBasicSketch(
// Open the code pane. // Open the code pane.
await u.openKclCodePanel() await u.openKclCodePanel()
await expect(u.codeLocator) await expect(u.codeLocator)
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${ .toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
commonPoints.startAt commonPoints.startAt
}, sketch001) }, sketch001)
|> xLine(length = ${commonPoints.num1}, tag = $seg01) |> xLine(length = ${commonPoints.num1}, tag = $seg01)

View File

@ -46,7 +46,7 @@ test.describe(
}, },
} }
const code = `sketch001 = startSketchOn(${plane})profile001 = startProfileAt([0.91, -1.22], sketch001)` const code = `@settings(defaultLengthUnit = in)sketch001 = startSketchOn(${plane})profile001 = startProfileAt([0.91, -1.22], sketch001)`
await u.openDebugPanel() await u.openDebugPanel()

View File

@ -251,11 +251,11 @@ test(
]) ])
await Promise.all([ await Promise.all([
fsp.copyFile( fsp.copyFile(
executorInputPath('router-template-slate.kcl'), executorInputPath('cylinder-inches.kcl'),
join(routerTemplateDir, 'main.kcl') join(routerTemplateDir, 'main.kcl')
), ),
fsp.copyFile( fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'), executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
join(bracketDir, 'main.kcl') join(bracketDir, 'main.kcl')
), ),
]) ])

View File

@ -20,11 +20,11 @@ test(
await Promise.all([fsp.mkdir(bracketDir, { recursive: true })]) await Promise.all([fsp.mkdir(bracketDir, { recursive: true })])
await Promise.all([ await Promise.all([
fsp.copyFile( fsp.copyFile(
executorInputPath('router-template-slate.kcl'), executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'other.kcl') path.join(bracketDir, 'other.kcl')
), ),
fsp.copyFile( fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'), executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
), ),
]) ])
@ -107,7 +107,7 @@ test(
}, },
{ timeout: 15_000 } { timeout: 15_000 }
) )
.toBeGreaterThan(300_000) .toBeGreaterThan(30_000)
}) })
}) })
@ -187,7 +187,7 @@ test(
}, },
{ timeout: 15_000 } { timeout: 15_000 }
) )
.toBeGreaterThan(70_000) .toBeGreaterThan(50_000)
}) })
}) })
} }

View File

@ -32,26 +32,30 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
await page.keyboard.press('/') await page.keyboard.press('/')
await page.keyboard.up('ControlOrMeta') await page.keyboard.up('ControlOrMeta')
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content')).toHaveText(
.toHaveText(`sketch001 = startSketchOn(XY) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %) |> startProfileAt([-10, -10], %)
|> line(end = [20, 0]) |> line(end = [20, 0])
|> line(end = [0, 20]) |> line(end = [0, 20])
|> line(end = [-20, 0]) |> line(end = [-20, 0])
// |> close()`) // |> close()`.replaceAll('\n', '')
)
// uncomment the code // uncomment the code
await page.keyboard.down('ControlOrMeta') await page.keyboard.down('ControlOrMeta')
await page.keyboard.press('/') await page.keyboard.press('/')
await page.keyboard.up('ControlOrMeta') await page.keyboard.up('ControlOrMeta')
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content')).toHaveText(
.toHaveText(`sketch001 = startSketchOn(XY) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %) |> startProfileAt([-10, -10], %)
|> line(end = [20, 0]) |> line(end = [20, 0])
|> line(end = [0, 20]) |> line(end = [0, 20])
|> line(end = [-20, 0]) |> line(end = [-20, 0])
|> close()`) |> close()`.replaceAll('\n', '')
)
}) })
test('ensure we use the cache, and do not re-execute', async ({ test('ensure we use the cache, and do not re-execute', async ({
@ -178,13 +182,15 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
await page.locator('#code-pane button:first-child').click() await page.locator('#code-pane button:first-child').click()
await page.locator('button:has-text("Format code")').click() await page.locator('button:has-text("Format code")').click()
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content')).toHaveText(
.toHaveText(`sketch001 = startSketchOn(XY) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %) |> startProfileAt([-10, -10], %)
|> line(end = [20, 0]) |> line(end = [20, 0])
|> line(end = [0, 20]) |> line(end = [0, 20])
|> line(end = [-20, 0]) |> line(end = [-20, 0])
|> close()`) |> close()`.replaceAll('\n', '')
)
}) })
test('if you click the format button it formats your code and executes so lints are still there', async ({ test('if you click the format button it formats your code and executes so lints are still there', async ({
@ -227,13 +233,15 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel() await u.closeDebugPanel()
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content')).toHaveText(
.toHaveText(`sketch_001 = startSketchOn(XY) `@settings(defaultLengthUnit = in)
sketch_001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %) |> startProfileAt([-10, -10], %)
|> line(end = [20, 0]) |> line(end = [20, 0])
|> line(end = [0, 20]) |> line(end = [0, 20])
|> line(end = [-20, 0]) |> line(end = [-20, 0])
|> close()`) |> close()`.replaceAll('\n', '')
)
// error in guter // error in guter
await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible() await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible()
@ -815,10 +823,12 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
// there shouldn't be any auto complete options for 'lin' in the comment // there shouldn't be any auto complete options for 'lin' in the comment
await expect(page.locator('.cm-completionLabel')).not.toBeVisible() await expect(page.locator('.cm-completionLabel')).not.toBeVisible()
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content')).toHaveText(
.toHaveText(`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([3.14, 12], %) |> startProfileAt([3.14, 12], %)
|> xLine(%, length = 5) // lin`) |> xLine(%, length = 5) // lin`.replaceAll('\n', '')
)
// expect there to be no KCL errors // expect there to be no KCL errors
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(0) await expect(page.locator('.cm-lint-marker-error')).toHaveCount(0)
@ -888,10 +898,12 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
// there shouldn't be any auto complete options for 'lin' in the comment // there shouldn't be any auto complete options for 'lin' in the comment
await expect(page.locator('.cm-completionLabel')).not.toBeVisible() await expect(page.locator('.cm-completionLabel')).not.toBeVisible()
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content')).toHaveText(
.toHaveText(`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([3.14, 12], %) |> startProfileAt([3.14, 12], %)
|> xLine(%, length = 5) // lin`) |> xLine(%, length = 5) // lin`.replaceAll('\n', '')
)
}) })
}) })
test('Can undo a click and point extrude with ctrl+z', async ({ test('Can undo a click and point extrude with ctrl+z', async ({

View File

@ -310,7 +310,9 @@ export async function expectPixelColor(
.toBeTruthy() .toBeTruthy()
.catch((cause) => { .catch((cause) => {
throw new Error( throw new Error(
`ExpectPixelColor: expecting ${colour} got ${finalValue}`, `ExpectPixelColor: point ${JSON.stringify(
coords
)} was expecting ${colour} but got ${finalValue}`,
{ cause } { cause }
) )
}) })

View File

@ -11,7 +11,7 @@ test(
const bracketDir = join(dir, 'bracket') const bracketDir = join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'), executorInputPath('cylinder-inches.kcl'),
join(bracketDir, 'main.kcl') join(bracketDir, 'main.kcl')
) )
}) })
@ -51,7 +51,7 @@ test(
const bracketDir = join(dir, 'bracket') const bracketDir = join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'), executorInputPath('cylinder-inches.kcl'),
join(bracketDir, 'main.kcl') join(bracketDir, 'main.kcl')
) )
}) })

View File

@ -137,7 +137,7 @@ test.describe('Point-and-click tests', () => {
await scene.moveCameraTo(cameraPos, cameraTarget) await scene.moveCameraTo(cameraPos, cameraTarget)
await test.step('check chamfer selection changes cursor positon', async () => { await test.step('check chamfer selection changes cursor position', async () => {
await expect(async () => { await expect(async () => {
// sometimes initial click doesn't register // sometimes initial click doesn't register
await clickChamfer() await clickChamfer()
@ -173,7 +173,7 @@ test.describe('Point-and-click tests', () => {
}) })
await test.step('Check there is no errors after code created in previous steps executes', async () => { await test.step('Check there is no errors after code created in previous steps executes', async () => {
await editor.expectState({ await editor.expectState({
activeLines: ['sketch001 = startSketchOn(XZ)'], activeLines: ['@settings(defaultLengthUnit = in)'],
highlightedCode: '', highlightedCode: '',
diagnostics: [], diagnostics: [],
}) })
@ -299,7 +299,8 @@ test.describe('Point-and-click tests', () => {
await test.step('verify at the end of the test that final code is what is expected', async () => { await test.step('verify at the end of the test that final code is what is expected', async () => {
await editor.expectEditor.toContain( await editor.expectEditor.toContain(
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag] |> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|> angledLine([0, 268.43], %, $rectangleSegmentA001) |> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -369,7 +370,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
}) })
}) })
test('Works on chamfers that are non in a pipeExpression can break up multi edges in a chamfer array', async ({ test('Works on chamfers that are not in a pipeExpression can break up multi edges in a chamfer array', async ({
context, context,
page, page,
homePage, homePage,
@ -418,7 +419,8 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
|>close()`, |>close()`,
}) })
await editor.expectEditor.toContain( await editor.expectEditor.toContain(
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %) |> startProfileAt([75.8, 317.2], %)
|> angledLine([0, 268.43], %, $rectangleSegmentA001) |> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -1639,9 +1641,10 @@ loft001 = loft([sketch001, sketch002])
{ {
targetType: 'circle', targetType: 'circle',
testPoint: { x: 700, y: 250 }, testPoint: { x: 700, y: 250 },
initialCode: `sketch001 = startSketchOn('YZ') initialCode: `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(YZ)
profile001 = circle(sketch001, center = [0, 0], radius = 500) profile001 = circle(sketch001, center = [0, 0], radius = 500)
sketch002 = startSketchOn('XZ') sketch002 = startSketchOn(XZ)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> xLine(length = -500) |> xLine(length = -500)
|> tangentialArcTo([-2000, 500], %)`, |> tangentialArcTo([-2000, 500], %)`,
@ -1649,7 +1652,8 @@ sketch002 = startSketchOn('XZ')
{ {
targetType: 'rectangle', targetType: 'rectangle',
testPoint: { x: 710, y: 255 }, testPoint: { x: 710, y: 255 },
initialCode: `sketch001 = startSketchOn('YZ') initialCode: `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(YZ)
profile001 = startProfileAt([-400, -400], sketch001) profile001 = startProfileAt([-400, -400], sketch001)
|> angledLine([0, 800], %, $rectangleSegmentA001) |> angledLine([0, 800], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -1662,7 +1666,7 @@ profile001 = startProfileAt([-400, -400], sketch001)
], %) ], %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
sketch002 = startSketchOn('XZ') sketch002 = startSketchOn(XZ)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> xLine(length = -500) |> xLine(length = -500)
|> tangentialArcTo([-2000, 500], %)`, |> tangentialArcTo([-2000, 500], %)`,
@ -1806,7 +1810,8 @@ sketch002 = startSketchOn('XZ')
toolbar, toolbar,
cmdBar, cmdBar,
}) => { }) => {
const initialCode = `sketch001 = startSketchOn(YZ) const initialCode = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(YZ)
|> circle( |> circle(
center = [0, 0], center = [0, 0],
radius = 500 radius = 500
@ -2475,7 +2480,8 @@ extrude001 = extrude(profile001, length = 5)
cmdBar, cmdBar,
}) => { }) => {
// Code samples // Code samples
const initialCode = `sketch001 = startSketchOn(XY) const initialCode = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XY)
|> startProfileAt([-12, -6], %) |> startProfileAt([-12, -6], %)
|> line(end = [0, 12]) |> line(end = [0, 12])
|> line(end = [24, 0]) |> line(end = [24, 0])
@ -2767,7 +2773,8 @@ extrude001 = extrude(sketch001, length = -12)
toolbar, toolbar,
}) => { }) => {
// Code samples // Code samples
const initialCode = `sketch001 = startSketchOn(XY) const initialCode = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XY)
|> startProfileAt([-12, -6], %) |> startProfileAt([-12, -6], %)
|> line(end = [0, 12]) |> line(end = [0, 12])
|> line(end = [24, 0], tag = $seg02) |> line(end = [24, 0], tag = $seg02)
@ -2921,7 +2928,8 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
toolbar, toolbar,
cmdBar, cmdBar,
}) => { }) => {
const initialCode = `sketch001 = startSketchOn(XZ) const initialCode = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 30) |> circle(center = [0, 0], radius = 30)
extrude001 = extrude(sketch001, length = 30) extrude001 = extrude(sketch001, length = 30)
` `
@ -3056,7 +3064,8 @@ extrude001 = extrude(sketch001, length = 30)
toolbar, toolbar,
cmdBar, cmdBar,
}) => { }) => {
const initialCode = `sketch001 = startSketchOn(XY) const initialCode = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XY)
|> startProfileAt([-20, 20], %) |> startProfileAt([-20, 20], %)
|> xLine(length = 40) |> xLine(length = 40)
|> yLine(length = -60) |> yLine(length = -60)
@ -3174,7 +3183,8 @@ extrude001 = extrude(sketch001, length = 40)
}) })
const shellSketchOnFacesCases = [ const shellSketchOnFacesCases = [
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 100) |> circle(center = [0, 0], radius = 100)
|> extrude(length = 100) |> extrude(length = 100)
@ -3182,7 +3192,8 @@ sketch002 = startSketchOn(sketch001, 'END')
|> circle(center = [0, 0], radius = 50) |> circle(center = [0, 0], radius = 50)
|> extrude(length = 50) |> extrude(length = 50)
`, `,
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 100) |> circle(center = [0, 0], radius = 100)
extrude001 = extrude(sketch001, length = 100) extrude001 = extrude(sketch001, length = 100)
@ -3578,7 +3589,8 @@ radius = 8.69
toolbar, toolbar,
cmdBar, cmdBar,
}) => { }) => {
const initialCode = `sketch001 = startSketchOn(XZ) const initialCode = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
profile001 = circle( profile001 = circle(
sketch001, sketch001,
center = [0, 0], center = [0, 0],

View File

@ -87,7 +87,7 @@ test(
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'), executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
}) })
@ -124,7 +124,7 @@ test(
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'), executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
const errorDir = path.join(dir, 'broken-code') const errorDir = path.join(dir, 'broken-code')
@ -162,7 +162,7 @@ test(
// gray at this pixel means the stream has loaded in the most // gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color) // user way we can verify it (pixel color)
await expect await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), { .poll(() => u.getGreatestPixDiff(pointOnModel, [110, 110, 110]), {
timeout: 10_000, timeout: 10_000,
}) })
.toBeLessThan(20) .toBeLessThan(20)
@ -213,7 +213,7 @@ test(
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'), executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
const emptyDir = path.join(dir, 'empty') const emptyDir = path.join(dir, 'empty')
@ -248,7 +248,7 @@ test(
// gray at this pixel means the stream has loaded in the most // gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color) // user way we can verify it (pixel color)
await expect await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), { .poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
timeout: 10_000, timeout: 10_000,
}) })
.toBeLessThan(15) .toBeLessThan(15)
@ -290,7 +290,7 @@ test(
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'), executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
@ -319,7 +319,7 @@ test(
// gray at this pixel means the stream has loaded in the most // gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color) // user way we can verify it (pixel color)
await expect await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), { .poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
timeout: 10_000, timeout: 10_000,
}) })
.toBeLessThan(15) .toBeLessThan(15)
@ -359,7 +359,7 @@ test(
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'), executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
await fsp.copyFile( await fsp.copyFile(
@ -393,7 +393,7 @@ test(
// gray at this pixel means the stream has loaded in the most // gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color) // user way we can verify it (pixel color)
await expect await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), { .poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
timeout: 10_000, timeout: 10_000,
}) })
.toBeLessThan(15) .toBeLessThan(15)
@ -443,7 +443,6 @@ test(
await page.getByText('broken-code').click() await page.getByText('broken-code').click()
// Gotcha: You can not use scene.waitForExecutionDone() since the KCL code is going to fail // Gotcha: You can not use scene.waitForExecutionDone() since the KCL code is going to fail
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({ await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000, timeout: 20_000,
}) })
@ -481,7 +480,7 @@ test.describe('Can export from electron app', () => {
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'), executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
}) })
@ -513,7 +512,7 @@ test.describe('Can export from electron app', () => {
// gray at this pixel means the stream has loaded in the most // gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color) // user way we can verify it (pixel color)
await expect await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), { .poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
timeout: 10_000, timeout: 10_000,
}) })
.toBeLessThan(15) .toBeLessThan(15)
@ -554,7 +553,7 @@ test.describe('Can export from electron app', () => {
}, },
{ timeout: 15_000 } { timeout: 15_000 }
) )
.toBeGreaterThan(300_000) .toBeGreaterThan(50_000)
// clean up exported file // clean up exported file
await fsp.rm(filepath) await fsp.rm(filepath)
@ -1507,7 +1506,12 @@ test(
await u.waitForPageLoad() await u.waitForPageLoad()
await page.locator('.cm-content').fill(`sketch001 = startSketchOn(XZ) // The file should be prepopulated with the user's unit settings.
await expect(page.locator('.cm-content')).toHaveText(
'@settings(defaultLengthUnit = in)'
)
await page.locator('.cm-content').fill(`sketch001 = startSketchOn('XZ')
|> startProfileAt([-87.4, 282.92], %) |> startProfileAt([-87.4, 282.92], %)
|> line(end = [324.07, 27.199], tag = $seg01) |> line(end = [324.07, 27.199], tag = $seg01)
|> line(end = [118.328, -291.754]) |> line(end = [118.328, -291.754])

View File

@ -4,9 +4,9 @@ import path from 'path'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import { import {
getUtils, getUtils,
executorInputPath,
TEST_COLORS, TEST_COLORS,
TestColor, TestColor,
executorInputPath,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
} from './test-utils' } from './test-utils'
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from './storageStates' import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from './storageStates'
@ -331,7 +331,7 @@ extrude001 = extrude(sketch001, length = 50)
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = mm) `@settings(defaultLengthUnit = mm)
sketch002 = startSketchOn('XY') sketch002 = startSketchOn(XY)
profile002 = startProfileAt([72.24, -52.05], sketch002) profile002 = startProfileAt([72.24, -52.05], sketch002)
|> angledLine([0, 181.26], %, $rectangleSegmentA001) |> angledLine([0, 181.26], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -582,7 +582,7 @@ extrude002 = extrude(profile002, length = 150)
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'), executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
}) })
@ -619,6 +619,7 @@ extrude002 = extrude(profile002, length = 150)
test(`View gizmo stays visible even when zoomed out all the way`, async ({ test(`View gizmo stays visible even when zoomed out all the way`, async ({
page, page,
homePage, homePage,
scene,
}) => { }) => {
const u = await getUtils(page) const u = await getUtils(page)
@ -632,7 +633,7 @@ extrude002 = extrude(profile002, length = 150)
await test.step(`Load an empty file`, async () => { await test.step(`Load an empty file`, async () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem('persistCode', '') localStorage.setItem('persistCode', '@settings(defaultLengthUnit = in)')
}) })
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
@ -646,22 +647,31 @@ extrude002 = extrude(profile002, length = 150)
timeout: 5000, timeout: 5000,
message: 'Plane color is visible', message: 'Plane color is visible',
}) })
.toBeLessThanOrEqual(15) .toBeLessThanOrEqual(20)
await expect(scene.startEditSketchBtn).toBeEnabled()
let maxZoomOuts = 10 let maxZoomOuts = 10
let middlePixelIsBackgroundColor = let middlePixelIsBackgroundColor =
(await middlePixelIsColor(bgColor)) < 10 (await middlePixelIsColor(bgColor)) < 10
console.time('pressing control')
await page.keyboard.down('Control')
while (!middlePixelIsBackgroundColor && maxZoomOuts > 0) { while (!middlePixelIsBackgroundColor && maxZoomOuts > 0) {
await page.keyboard.down('Control')
await page.mouse.move(600, 460)
await page.mouse.down({ button: 'right' })
await page.mouse.move(600, 50, { steps: 20 })
await page.mouse.up({ button: 'right' })
await page.keyboard.up('Control')
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.mouse.move(650, 460)
console.time('moved to start point')
await page.mouse.down({ button: 'right' })
console.time('moused down')
await page.mouse.move(650, 50, { steps: 20 })
console.time('moved to end point')
await page.waitForTimeout(100)
await page.mouse.up({ button: 'right' })
console.time('moused up')
maxZoomOuts-- maxZoomOuts--
middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 10 middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 15
} }
await page.keyboard.up('Control')
expect(middlePixelIsBackgroundColor, { expect(middlePixelIsBackgroundColor, {
message: 'We should not see the default planes', message: 'We should not see the default planes',
@ -678,13 +688,12 @@ extrude002 = extrude(profile002, length = 150)
homePage, homePage,
scene, scene,
toolbar, toolbar,
viewport,
}) => { }) => {
await context.folderSetupFn(async (dir) => { await context.folderSetupFn(async (dir) => {
const legoDir = path.join(dir, 'lego') const legoDir = path.join(dir, 'lego')
await fsp.mkdir(legoDir, { recursive: true }) await fsp.mkdir(legoDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('lego.kcl'), executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
path.join(legoDir, 'main.kcl') path.join(legoDir, 'main.kcl')
) )
}) })
@ -697,11 +706,8 @@ extrude002 = extrude(profile002, length = 150)
await scene.loadingIndicator.waitFor({ state: 'detached' }) await scene.loadingIndicator.waitFor({ state: 'detached' })
}) })
await test.step(`The part should start loading quickly, not waiting until execution is complete`, async () => { await test.step(`The part should start loading quickly, not waiting until execution is complete`, async () => {
await scene.expectPixelColor( // TODO: use the viewport size to pick the center point, but the `viewport` fixture's values were wrong.
[143, 143, 143], await scene.expectPixelColor([116, 116, 116], { x: 500, y: 250 }, 15)
{ x: (viewport?.width ?? 1200) / 2, y: (viewport?.height ?? 500) / 2 },
15
)
}) })
}) })

View File

@ -113,7 +113,8 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([2.61, -4.01], %) |> startProfileAt([2.61, -4.01], %)
|> xLine(length = 8.73) |> xLine(length = 8.73)
|> tangentialArcTo([8.33, -1.31], %)` |> tangentialArcTo([8.33, -1.31], %)`
@ -159,7 +160,10 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
await page.mouse.click(700, 200) await page.mouse.click(700, 200)
await expect.poll(u.normalisedEditorCode, { timeout: 1000 }) await expect.poll(u.normalisedEditorCode, { timeout: 1000 })
.toBe(`sketch002 = startSketchOn(XZ) .toBe(`@settings(defaultLengthUnit = in)
sketch002 = startSketchOn(XZ)
sketch001 = startProfileAt([12.34, -12.34], sketch002) sketch001 = startProfileAt([12.34, -12.34], sketch002)
|> yLine(length = 12.34) |> yLine(length = 12.34)
@ -789,7 +793,8 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
200 200
) )
let codeStr = 'sketch001 = startSketchOn(XY)' let codeStr =
'@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XY)'
await page.mouse.click(center.x, viewportSize.height * 0.55) await page.mouse.click(center.x, viewportSize.height * 0.55)
await expect(u.codeLocator).toHaveText(codeStr) await expect(u.codeLocator).toHaveText(codeStr)
@ -868,7 +873,8 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
await u.openDebugPanel() await u.openDebugPanel()
const code = `sketch001 = startSketchOn(-XZ) const code = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(-XZ)
profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff( profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
scale * 34.8 scale * 34.8
)}], sketch001) )}], sketch001)
@ -898,7 +904,7 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
await page.mouse.move(700, 200, { steps: 10 }) await page.mouse.move(700, 200, { steps: 10 })
await page.mouse.click(700, 200, { delay: 200 }) await page.mouse.click(700, 200, { delay: 200 })
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content')).toHaveText(
`sketch001 = startSketchOn(-XZ)` `@settings(defaultLengthUnit = in)sketch001 = startSketchOn(-XZ)`
) )
let prevContent = await page.locator('.cm-content').innerText() let prevContent = await page.locator('.cm-content').innerText()
@ -1426,7 +1432,8 @@ test.describe(`Sketching with offset planes`, () => {
await context.addInitScript(() => { await context.addInitScript(() => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`offsetPlane001 = offsetPlane(XY, offset = 10)` `@settings(defaultLengthUnit = in)
offsetPlane001 = offsetPlane(XY, offset = 10)`
) )
}) })
@ -1440,7 +1447,7 @@ test.describe(`Sketching with offset planes`, () => {
await test.step(`Hovering should highlight code`, async () => { await test.step(`Hovering should highlight code`, async () => {
await planeHover() await planeHover()
await editor.expectState({ await editor.expectState({
activeLines: [`offsetPlane001=offsetPlane(XY,offset=10)`], activeLines: [`@settings(defaultLengthUnit = in)`],
diagnostics: [], diagnostics: [],
highlightedCode: 'offsetPlane(XY, offset = 10)', highlightedCode: 'offsetPlane(XY, offset = 10)',
}) })
@ -1453,7 +1460,7 @@ test.describe(`Sketching with offset planes`, () => {
await expect(toolbar.lineBtn).toBeEnabled() await expect(toolbar.lineBtn).toBeEnabled()
await editor.expectEditor.toContain('startSketchOn(offsetPlane001)') await editor.expectEditor.toContain('startSketchOn(offsetPlane001)')
await editor.expectState({ await editor.expectState({
activeLines: [`offsetPlane001=offsetPlane(XY,offset=10)`], activeLines: [`@settings(defaultLengthUnit = in)`],
diagnostics: [], diagnostics: [],
highlightedCode: '', highlightedCode: '',
}) })
@ -1604,7 +1611,8 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
await context.addInitScript(() => { await context.addInitScript(() => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
profile002 = startProfileAt([40.68, 87.67], sketch001) profile002 = startProfileAt([40.68, 87.67], sketch001)
|> xLine(length = 239.17) |> xLine(length = 239.17)
profile003 = startProfileAt([206.63, -56.73], sketch001) profile003 = startProfileAt([206.63, -56.73], sketch001)
@ -2172,7 +2180,8 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([6.24, 4.54], sketch001) profile001 = startProfileAt([6.24, 4.54], sketch001)
|> line(end = [-0.41, 6.99]) |> line(end = [-0.41, 6.99])
|> line(end = [8.61, 0.74]) |> line(end = [8.61, 0.74])
@ -2317,7 +2326,8 @@ profile004 = circleThreePoint(sketch001, p1 = [13.44, -6.8], p2 = [13.39, -2.07]
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([6.24, 4.54], sketch001) profile001 = startProfileAt([6.24, 4.54], sketch001)
|> line(end = [-0.41, 6.99]) |> line(end = [-0.41, 6.99])
|> line(end = [8.61, 0.74]) |> line(end = [8.61, 0.74])
@ -2422,7 +2432,8 @@ profile003 = circle(sketch001, center = [6.92, -4.2], radius = 3.16)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([-63.43, 193.08], sketch001) profile001 = startProfileAt([-63.43, 193.08], sketch001)
|> line(end = [168.52, 149.87]) |> line(end = [168.52, 149.87])
|> line(end = [190.29, -39.18]) |> line(end = [190.29, -39.18])
@ -2486,7 +2497,11 @@ extrude001 = extrude(profile003, length = 5)
page, page,
}) => { }) => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem('persistCode', `myVar = 5`) localStorage.setItem(
'persistCode',
`@settings(defaultLengthUnit = in)
myVar = 5`
)
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
@ -2533,7 +2548,8 @@ extrude001 = extrude(profile003, length = 5)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([85.19, 338.59], sketch001) profile001 = startProfileAt([85.19, 338.59], sketch001)
|> line(end = [213.3, -94.52]) |> line(end = [213.3, -94.52])
|> line(end = [-230.09, -55.34]) |> line(end = [-230.09, -55.34])
@ -2575,7 +2591,8 @@ profile002 = startProfileAt([85.81, 52.55], sketch002)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`thePart = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
thePart = startSketchOn(XZ)
|> startProfileAt([7.53, 10.51], %) |> startProfileAt([7.53, 10.51], %)
|> line(end = [12.54, 1.83]) |> line(end = [12.54, 1.83])
|> line(end = [6.65, -6.91]) |> line(end = [6.65, -6.91])
@ -2636,7 +2653,8 @@ extrude001 = extrude(thePart, length = 75)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([6.71, -3.66], sketch001) profile001 = startProfileAt([6.71, -3.66], sketch001)
|> line(end = [2.65, 9.02], tag = $seg02) |> line(end = [2.65, 9.02], tag = $seg02)
|> line(end = [3.73, -9.36], tag = $seg01) |> line(end = [3.73, -9.36], tag = $seg01)
@ -2809,7 +2827,8 @@ extrude003 = extrude(profile011, length = 2.5)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([34, 42.66], sketch001) profile001 = startProfileAt([34, 42.66], sketch001)
|> line(end = [102.65, 151.99]) |> line(end = [102.65, 151.99])
|> line(end = [76, -138.66]) |> line(end = [76, -138.66])

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -1,5 +1,5 @@
{ {
"original_source_code": "sketch001 = startSketchOn('XZ')\nprofile001 = startProfileAt([57.81, 250.51], sketch001)\n |> line(end = [121.13, 56.63], tag = $seg02)\n |> line(end = [83.37, -34.61], tag = $seg01)\n |> line(end = [19.66, -116.4])\n |> line(end = [-221.8, -41.69])\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude001 = extrude(profile001, length = 200)\nsketch002 = startSketchOn('XZ')\n |> startProfileAt([-73.64, -42.89], %)\n |> xLine(length = 173.71)\n |> line(end = [-22.12, -94.4])\n |> xLine(length = -156.98)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude002 = extrude(sketch002, length = 50)\nsketch003 = startSketchOn('XY')\n |> startProfileAt([52.92, 157.81], %)\n |> angledLine([0, 176.4], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 53.4\n ], %, $rectangleSegmentB001)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %, $rectangleSegmentC001)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude003 = extrude(sketch003, length = 20)\n", "original_source_code": "sketch001 = startSketchOn('XZ')\nprofile001 = startProfileAt([57.81, 250.51], sketch001)\n |> line(end = [121.13, 56.63], tag = $seg02)\n |> line(end = [83.37, -34.61], tag = $seg01)\n |> line(end = [19.66, -116.4])\n |> line(end = [-221.8, -41.69])\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude001 = extrude(profile001, length = 200)\nsketch002 = startSketchOn('XZ')\n |> startProfileAt([-73.64, -42.89], %)\n |> xLine(length = 173.71)\n |> line(end = [-22.12, -94.4])\n |> xLine(length = -156.98)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude002 = extrude(sketch002, length = 50)\nsketch003 = startSketchOn(XY)\n |> startProfileAt([52.92, 157.81], %)\n |> angledLine([0, 176.4], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 53.4\n ], %, $rectangleSegmentB001)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %, $rectangleSegmentC001)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude003 = extrude(sketch003, length = 20)\n",
"prompt": "make this neon green please, use #39FF14", "prompt": "make this neon green please, use #39FF14",
"source_ranges": [ "source_ranges": [
{ {

View File

@ -4,7 +4,6 @@ import {
getUtils, getUtils,
TEST_COLORS, TEST_COLORS,
pollEditorLinesSelectedLength, pollEditorLinesSelectedLength,
executorInputPath,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
} from './test-utils' } from './test-utils'
import { XOR } from 'lib/utils' import { XOR } from 'lib/utils'
@ -81,7 +80,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`yo = 79 `@settings(defaultLengthUnit = in)
yo = 79
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4], tag = $seg01) |> line(end = [74.36, 130.4], tag = $seg01)
@ -145,7 +145,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`yo = 5 `@settings(defaultLengthUnit = in)
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4], tag = $seg01) |> line(end = [74.36, 130.4], tag = $seg01)
@ -277,7 +278,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`yo = 5 `@settings(defaultLengthUnit = in)
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -387,7 +389,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`yo = 5 `@settings(defaultLengthUnit = in)
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -500,7 +503,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`yo = 5 `@settings(defaultLengthUnit = in)
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -602,7 +606,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`yo = 5 `@settings(defaultLengthUnit = in)
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -688,7 +693,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`yo = 5 `@settings(defaultLengthUnit = in)
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -768,7 +774,8 @@ part002 = startSketchOn(XZ)
await page.addInitScript(async (customCode) => { await page.addInitScript(async (customCode) => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`yo = 5 `@settings(defaultLengthUnit = in)
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -869,7 +876,8 @@ part002 = startSketchOn(XZ)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`yo = 5 `@settings(defaultLengthUnit = in)
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -950,7 +958,8 @@ part002 = startSketchOn(XZ)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`yo = 5 `@settings(defaultLengthUnit = in)
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -1117,9 +1126,19 @@ test.describe('Electron constraint tests', () => {
await context.folderSetupFn(async (dir) => { await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'test-sample') const bracketDir = path.join(dir, 'test-sample')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.writeFile(
executorInputPath('angled_line.kcl'), path.join(bracketDir, 'main.kcl'),
path.join(bracketDir, 'main.kcl') `@settings(defaultLengthUnit = in)
const part001 = startSketchOn(XY)
|> startProfileAt([4.83, 12.56], %)
|> line(end = [15.1, 2.48])
|> line(end = [3.15, -9.85], tag = $seg01)
|> line(end = [-15.17, -4.1])
|> angledLine([segAng(seg01), 12.35], %)
|> line(end = [-13.02, 10.03])
|> close()
|> extrude(length = 4)`,
'utf-8'
) )
}) })

View File

@ -255,7 +255,7 @@ test.describe(`Testing gizmo, fixture-based`, () => {
await context.addInitScript(() => { await context.addInitScript(() => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
` `@settings(defaultLengthUnit = in)
const sketch002 = startSketchOn(XZ) const sketch002 = startSketchOn(XZ)
|> startProfileAt([-108.83, -57.48], %) |> startProfileAt([-108.83, -57.48], %)
|> angledLine([0, 105.13], %, $rectangleSegmentA001) |> angledLine([0, 105.13], %, $rectangleSegmentA001)

View File

@ -46,7 +46,7 @@ test.describe('Testing in-app sample loading', () => {
page.getByRole('option', { page.getByRole('option', {
name, name,
}) })
const warningText = page.getByText('Overwrite current file and units?') const warningText = page.getByText('Overwrite current file with sample?')
const confirmButton = page.getByRole('button', { name: 'Submit command' }) const confirmButton = page.getByRole('button', { name: 'Submit command' })
await test.step(`Precondition: check the initial code`, async () => { await test.step(`Precondition: check the initial code`, async () => {
@ -110,11 +110,9 @@ test.describe('Testing in-app sample loading', () => {
const commandMethodOption = page.getByRole('option', { const commandMethodOption = page.getByRole('option', {
name: 'Overwrite', name: 'Overwrite',
}) })
const newFileWarning = page.getByText( const newFileWarning = page.getByText('Create a new file from sample?')
'Create a new file, overwrite project units?'
)
const overwriteWarning = page.getByText( const overwriteWarning = page.getByText(
'Overwrite current file and units?' 'Overwrite current file with sample?'
) )
const confirmButton = page.getByRole('button', { name: 'Submit command' }) const confirmButton = page.getByRole('button', { name: 'Submit command' })
const projectMenuButton = page.getByTestId('project-sidebar-toggle') const projectMenuButton = page.getByTestId('project-sidebar-toggle')

View File

@ -210,7 +210,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`part001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
|> startProfileAt([5 + 0, 20 + 0], %) |> startProfileAt([5 + 0, 20 + 0], %)
|> line(end = [0.5, -14 + 0]) |> line(end = [0.5, -14 + 0])
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %) |> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
@ -380,7 +381,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`yRel001 = -14 `@settings(defaultLengthUnit = in)
yRel001 = -14
xRel001 = 0.5 xRel001 = 0.5
angle001 = 3 angle001 = 3
len001 = 32 len001 = 32
@ -459,7 +461,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`part001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line(end = [0.5, -14 + 0]) |> line(end = [0.5, -14 + 0])
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %) |> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
@ -590,7 +593,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`part001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line(end = [0.5, -14 + 0]) |> line(end = [0.5, -14 + 0])
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %) |> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
@ -751,7 +755,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`part001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line(end = [0.5, -14 + 0]) |> line(end = [0.5, -14 + 0])
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %) |> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
@ -831,7 +836,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([56.37, 120.33], sketch001) profile001 = startProfileAt([56.37, 120.33], sketch001)
|> line(end = [162.86, 106.48]) |> line(end = [162.86, 106.48])
|> arcTo({ |> arcTo({
@ -957,7 +963,8 @@ profile001 = startProfileAt([56.37, 120.33], sketch001)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`part001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
|> circle(center = [1 + 0, 0], radius = 8) |> circle(center = [1 + 0, 0], radius = 8)
` `
) )
@ -1077,7 +1084,8 @@ profile001 = startProfileAt([56.37, 120.33], sketch001)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`part001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
|>startProfileAt([0, 0], %) |>startProfileAt([0, 0], %)
|> line(end = [0.5, -14 + 0]) |> line(end = [0.5, -14 + 0])
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %) |> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
@ -1351,7 +1359,8 @@ profile001 = startProfileAt([56.37, 120.33], sketch001)
async ({ lineToBeDeleted, extraLine }) => { async ({ lineToBeDeleted, extraLine }) => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`part001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
|> startProfileAt([5, 6], %) |> startProfileAt([5, 6], %)
|> ${lineToBeDeleted} |> ${lineToBeDeleted}
|> line(end = [-10, -15]) |> line(end = [-10, -15])
@ -1516,7 +1525,8 @@ profile001 = startProfileAt([56.37, 120.33], sketch001)
async ({ lineToBeDeleted }) => { async ({ lineToBeDeleted }) => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`part001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
|> startProfileAt([5, 6], %) |> startProfileAt([5, 6], %)
|> ${lineToBeDeleted} |> ${lineToBeDeleted}
|> line(end = [-10, -15]) |> line(end = [-10, -15])

View File

@ -68,20 +68,20 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
await u.closeDebugPanel() await u.closeDebugPanel()
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10) await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content')).toHaveText(
`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)` `@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)`
) )
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10) await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content'))
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001) .toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)
|> xLine(length = ${commonPoints.num1})`) |> xLine(length = ${commonPoints.num1})`)
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20) await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20)
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content'))
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${ .toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
commonPoints.startAt commonPoints.startAt
}, sketch001) }, sketch001)
|> xLine(length = ${commonPoints.num1}) |> xLine(length = ${commonPoints.num1})
@ -89,7 +89,7 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.mouse.click(startXPx, 500 - PUR * 20) await page.mouse.click(startXPx, 500 - PUR * 20)
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content'))
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${ .toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
commonPoints.startAt commonPoints.startAt
}, sketch001) }, sketch001)
|> xLine(length = ${commonPoints.num1}) |> xLine(length = ${commonPoints.num1})
@ -260,7 +260,8 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([-79.26, 95.04], %) |> startProfileAt([-79.26, 95.04], %)
|> line(end = [112.54, 127.64], tag = $seg02) |> line(end = [112.54, 127.64], tag = $seg02)
|> line(end = [170.36, -121.61], tag = $seg01) |> line(end = [170.36, -121.61], tag = $seg01)
@ -528,7 +529,8 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
await page.addInitScript(async (KCL_DEFAULT_LENGTH) => { await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`part001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
|> startProfileAt([20, 0], %) |> startProfileAt([20, 0], %)
|> line(end = [7.13, 4 + 0]) |> line(end = [7.13, 4 + 0])
|> angledLine({ angle = 3 + 0, length = 3.14 + 0 }, %) |> angledLine({ angle = 3 + 0, length = 3.14 + 0 }, %)
@ -747,7 +749,8 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
await page.waitForTimeout(200) await page.waitForTimeout(200)
await u.removeCurrentCode() await u.removeCurrentCode()
await u.codeLocator.fill(`sketch001 = startSketchOn(XZ) await u.codeLocator.fill(`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag] |> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|> angledLine([0, 268.43], %, $rectangleSegmentA001) |> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -965,7 +968,8 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
async ({ cases }) => { async ({ cases }) => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`yo = 79 `@settings(defaultLengthUnit = in)
yo = 79
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> ${cases[0].expectedCode} |> ${cases[0].expectedCode}
@ -1020,7 +1024,8 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([-79.26, 95.04], %) |> startProfileAt([-79.26, 95.04], %)
|> line(end = [112.54, 127.64]) |> line(end = [112.54, 127.64])
|> line(end = [170.36, -121.61], tag = $seg01) |> line(end = [170.36, -121.61], tag = $seg01)
@ -1253,7 +1258,7 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
await page.mouse.click(700, 200) await page.mouse.click(700, 200)
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content')).toHaveText(
`sketch001 = startSketchOn(XZ)` `@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)`
) )
await page.waitForTimeout(600) await page.waitForTimeout(600)

View File

@ -271,7 +271,7 @@ test.describe('Testing settings', () => {
const bracketDir = join(dir, projectName) const bracketDir = join(dir, projectName)
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'), executorInputPath('cylinder-inches.kcl'),
join(bracketDir, 'main.kcl') join(bracketDir, 'main.kcl')
) )
} }
@ -699,19 +699,19 @@ test.describe('Testing settings', () => {
name: 'Current units are: ', name: 'Current units are: ',
}) })
await gizmo.click() await gizmo.click()
const button = page.getByRole('button', { const button = page.locator('ul').getByRole('button', {
name: copy, name: copy,
exact: true, exact: true,
}) })
await button.click() await button.click()
const toastMessage = page.getByText( const toastMessage = page.getByText(
`Set default unit to "${unitOfMeasure}" for this project` `Updated per-file units to ${unitOfMeasure}`
) )
await expect(toastMessage).toBeVisible() await expect(toastMessage).toBeVisible()
} }
await changeUnitOfMeasureInGizmo('in', 'Inches')
await changeUnitOfMeasureInGizmo('ft', 'Feet') await changeUnitOfMeasureInGizmo('ft', 'Feet')
await changeUnitOfMeasureInGizmo('in', 'Inches')
await changeUnitOfMeasureInGizmo('yd', 'Yards') await changeUnitOfMeasureInGizmo('yd', 'Yards')
await changeUnitOfMeasureInGizmo('mm', 'Millimeters') await changeUnitOfMeasureInGizmo('mm', 'Millimeters')
await changeUnitOfMeasureInGizmo('cm', 'Centimeters') await changeUnitOfMeasureInGizmo('cm', 'Centimeters')
@ -951,9 +951,9 @@ test.describe('Testing settings', () => {
) )
}) })
await test.step(`Initial units from settings`, async () => { await test.step(`Initial units from settings are ignored`, async () => {
await homePage.openProject('project-000') await homePage.openProject('project-000')
await expect(unitsIndicator).toHaveText('Current units are: in') await expect(unitsIndicator).toHaveText('Current units are: mm')
}) })
await test.step(`Manually write inline settings`, async () => { await test.step(`Manually write inline settings`, async () => {

View File

@ -483,7 +483,8 @@ test('Sketch on face', async ({ page, homePage, scene, cmdBar, toolbar }) => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn(XZ) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([3.29, 7.86], %) |> startProfileAt([3.29, 7.86], %)
|> line(end = [2.48, 2.44]) |> line(end = [2.48, 2.44])
|> line(end = [2.66, 1.17]) |> line(end = [2.66, 1.17])

View File

@ -816,7 +816,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
async fn #test_name() -> miette::Result<()> { async fn #test_name() -> miette::Result<()> {
let code = #code_block; let code = #code_block;
// Note, `crate` must be kcl_lib // Note, `crate` must be kcl_lib
let result = match crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm, None).await { let result = match crate::test_server::execute_and_snapshot(code, None).await {
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -31,13 +31,7 @@ mod test_examples_someFn {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_someFn0() -> miette::Result<()> { async fn kcl_test_example_someFn0() -> miette::Result<()> {
let code = "someFn()"; let code = "someFn()";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -31,13 +31,7 @@ mod test_examples_someFn {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_someFn0() -> miette::Result<()> { async fn kcl_test_example_someFn0() -> miette::Result<()> {
let code = "someFn()"; let code = "someFn()";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_show {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_show0() -> miette::Result<()> { async fn kcl_test_example_show0() -> miette::Result<()> {
let code = "This is another code block.\nyes sirrr.\nshow"; let code = "This is another code block.\nyes sirrr.\nshow";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_show {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_show0() -> miette::Result<()> { async fn kcl_test_example_show0() -> miette::Result<()> {
let code = "This is code.\nIt does other shit.\nshow"; let code = "This is code.\nIt does other shit.\nshow";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -33,13 +33,7 @@ mod test_examples_my_func {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_my_func0() -> miette::Result<()> { async fn kcl_test_example_my_func0() -> miette::Result<()> {
let code = "This is another code block.\nyes sirrr.\nmyFunc"; let code = "This is another code block.\nyes sirrr.\nmyFunc";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -33,13 +33,7 @@ mod test_examples_line_to {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_line_to0() -> miette::Result<()> { async fn kcl_test_example_line_to0() -> miette::Result<()> {
let code = "This is another code block.\nyes sirrr.\nlineTo"; let code = "This is another code block.\nyes sirrr.\nlineTo";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_min {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_min0() -> miette::Result<()> { async fn kcl_test_example_min0() -> miette::Result<()> {
let code = "This is another code block.\nyes sirrr.\nmin"; let code = "This is another code block.\nyes sirrr.\nmin";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_show {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_show0() -> miette::Result<()> { async fn kcl_test_example_show0() -> miette::Result<()> {
let code = "This is code.\nIt does other shit.\nshow"; let code = "This is code.\nIt does other shit.\nshow";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_import {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_import0() -> miette::Result<()> { async fn kcl_test_example_import0() -> miette::Result<()> {
let code = "This is code.\nIt does other shit.\nimport"; let code = "This is code.\nIt does other shit.\nimport";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_import {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_import0() -> miette::Result<()> { async fn kcl_test_example_import0() -> miette::Result<()> {
let code = "This is code.\nIt does other shit.\nimport"; let code = "This is code.\nIt does other shit.\nimport";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_import {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_import0() -> miette::Result<()> { async fn kcl_test_example_import0() -> miette::Result<()> {
let code = "This is code.\nIt does other shit.\nimport"; let code = "This is code.\nIt does other shit.\nimport";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_show {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_show0() -> miette::Result<()> { async fn kcl_test_example_show0() -> miette::Result<()> {
let code = "This is code.\nIt does other shit.\nshow"; let code = "This is code.\nIt does other shit.\nshow";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -31,13 +31,7 @@ mod test_examples_some_function {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_some_function0() -> miette::Result<()> { async fn kcl_test_example_some_function0() -> miette::Result<()> {
let code = "someFunction()"; let code = "someFunction()";
let result = match crate::test_server::execute_and_snapshot( let result = match crate::test_server::execute_and_snapshot(code, None).await {
code,
crate::settings::types::UnitLength::Mm,
None,
)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { return Err(miette::Report::new(crate::errors::Report {
error: e.error, error: e.error,

View File

@ -76,7 +76,7 @@ fn run_benchmarks(c: &mut Criterion) {
group.bench_function(format!("execute_{}", dir_name), |b| { group.bench_function(format!("execute_{}", dir_name), |b| {
b.iter(|| { b.iter(|| {
if let Err(err) = rt.block_on(async { if let Err(err) = rt.block_on(async {
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default()).await?; let ctx = kcl_lib::ExecutorContext::new_with_default_client().await?;
let mut exec_state = kcl_lib::ExecState::new(&ctx); let mut exec_state = kcl_lib::ExecState::new(&ctx);
ctx.run(black_box(&program), &mut exec_state).await?; ctx.run(black_box(&program), &mut exec_state).await?;
ctx.close().await; ctx.close().await;

View File

@ -51,45 +51,6 @@ async fn cache_test(
img_results img_results
} }
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cache_change_units_changes_output() {
let code = r#"part001 = startSketchOn('XY')
|> startProfileAt([5.5229, 5.25217], %)
|> line(end = [10.50433, -1.19122])
|> line(end = [8.01362, -5.48731])
|> line(end = [-1.02877, -6.76825])
|> line(end = [-11.53311, 2.81559])
|> close()
|> extrude(length = 4)
"#;
let result = cache_test(
"change_units_changes_output",
vec![
Variation {
code,
settings: &kcl_lib::ExecutorSettings {
units: kcl_lib::UnitLength::In,
..Default::default()
},
},
Variation {
code,
settings: &kcl_lib::ExecutorSettings {
units: kcl_lib::UnitLength::Mm,
..Default::default()
},
},
],
)
.await;
let first = result.first().unwrap();
let second = result.last().unwrap();
assert!(first.1 != second.1);
}
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cache_change_grid_visualizes_grid_off_to_on() { async fn kcl_test_cache_change_grid_visualizes_grid_off_to_on() {
let code = r#"part001 = startSketchOn('XY') let code = r#"part001 = startSketchOn('XY')
@ -261,9 +222,7 @@ async fn kcl_test_cache_empty_file_pop_cache_empty_file_planes_work() {
// Get the current working directory. // Get the current working directory.
let code = ""; let code = "";
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default()) let ctx = kcl_lib::ExecutorContext::new_with_default_client().await.unwrap();
.await
.unwrap();
let program = kcl_lib::Program::parse_no_errs(code).unwrap(); let program = kcl_lib::Program::parse_no_errs(code).unwrap();
let outcome = ctx.run_with_caching(program).await.unwrap(); let outcome = ctx.run_with_caching(program).await.unwrap();

View File

@ -0,0 +1,4 @@
@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 20)
extrude001 = extrude(sketch001, length = 10)

View File

@ -1,4 +1,5 @@
const sketch001 = startSketchOn(XZ) @settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %) |> startProfileAt([75.8, 317.2], %)
|> angledLine([0, 268.43], %, $rectangleSegmentA001) |> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -11,8 +12,8 @@ const sketch001 = startSketchOn(XZ)
], %, $yo) ], %, $yo)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02) |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|> close() |> close()
const extrude001 = extrude(sketch001, length = 100) extrude001 = extrude(sketch001, length = 100)
const chamf = chamfer( chamf = chamfer(
extrude001, extrude001,
length = 30, length = 30,
tags = [ tags = [

View File

@ -1,4 +1,5 @@
const sketch001 = startSketchOn(XZ) @settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag] |> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|> angledLine([0, 268.43], %, $rectangleSegmentA001) |> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -11,7 +12,7 @@ const sketch001 = startSketchOn(XZ)
], %, $yo) ], %, $yo)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02) |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|> close() |> close()
const extrude001 = extrude(sketch001, length = 100) extrude001 = extrude(sketch001, length = 100)
|> chamfer( |> chamfer(
length = 30, length = 30,
tags = [ tags = [

View File

@ -2,7 +2,7 @@ mod cache;
use kcl_lib::{ use kcl_lib::{
test_server::{execute_and_export_step, execute_and_snapshot, execute_and_snapshot_no_auth}, test_server::{execute_and_export_step, execute_and_snapshot, execute_and_snapshot_no_auth},
ExecError, UnitLength, ExecError,
}; };
/// The minimum permissible difference between asserted twenty-twenty images. /// The minimum permissible difference between asserted twenty-twenty images.
@ -26,7 +26,7 @@ pub(crate) fn assert_out(test_name: &str, result: &image::DynamicImage) -> Strin
async fn kcl_test_fillet_duplicate_tags() { async fn kcl_test_fillet_duplicate_tags() {
let code = kcl_input!("fillet_duplicate_tags"); let code = kcl_input!("fillet_duplicate_tags");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
let err = result.expect_err("Code should have failed due to the duplicate edges being filletted"); let err = result.expect_err("Code should have failed due to the duplicate edges being filletted");
let err = err.as_kcl_error().unwrap(); let err = err.as_kcl_error().unwrap();
@ -48,7 +48,7 @@ async fn kcl_test_execute_engine_error_return() {
|> extrude(length = 4) |> extrude(length = 4)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -61,7 +61,7 @@ async fn kcl_test_execute_i_shape() {
// This is some code from lee that starts a pipe expression with a variable. // This is some code from lee that starts a pipe expression with a variable.
let code = kcl_input!("i_shape"); let code = kcl_input!("i_shape");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("i_shape", &result); assert_out("i_shape", &result);
} }
@ -70,7 +70,7 @@ async fn kcl_test_execute_i_shape() {
async fn kcl_test_execute_pipes_on_pipes() { async fn kcl_test_execute_pipes_on_pipes() {
let code = kcl_input!("pipes_on_pipes"); let code = kcl_input!("pipes_on_pipes");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("pipes_on_pipes", &result); assert_out("pipes_on_pipes", &result);
} }
@ -78,7 +78,7 @@ async fn kcl_test_execute_pipes_on_pipes() {
async fn kcl_test_execute_cylinder() { async fn kcl_test_execute_cylinder() {
let code = kcl_input!("cylinder"); let code = kcl_input!("cylinder");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("cylinder", &result); assert_out("cylinder", &result);
} }
@ -86,7 +86,7 @@ async fn kcl_test_execute_cylinder() {
async fn kcl_test_execute_kittycad_svg() { async fn kcl_test_execute_kittycad_svg() {
let code = kcl_input!("kittycad_svg"); let code = kcl_input!("kittycad_svg");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("kittycad_svg", &result); assert_out("kittycad_svg", &result);
} }
@ -94,7 +94,7 @@ async fn kcl_test_execute_kittycad_svg() {
async fn kcl_test_execute_lsystem() { async fn kcl_test_execute_lsystem() {
let code = kcl_input!("lsystem"); let code = kcl_input!("lsystem");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("lsystem", &result); assert_out("lsystem", &result);
} }
@ -102,7 +102,7 @@ async fn kcl_test_execute_lsystem() {
async fn kcl_test_member_expression_sketch() { async fn kcl_test_member_expression_sketch() {
let code = kcl_input!("member_expression_sketch"); let code = kcl_input!("member_expression_sketch");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("member_expression_sketch", &result); assert_out("member_expression_sketch", &result);
} }
@ -110,7 +110,7 @@ async fn kcl_test_member_expression_sketch() {
async fn kcl_test_helix_defaults() { async fn kcl_test_helix_defaults() {
let code = kcl_input!("helix_defaults"); let code = kcl_input!("helix_defaults");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("helix_defaults", &result); assert_out("helix_defaults", &result);
} }
@ -118,7 +118,7 @@ async fn kcl_test_helix_defaults() {
async fn kcl_test_helix_defaults_negative_extrude() { async fn kcl_test_helix_defaults_negative_extrude() {
let code = kcl_input!("helix_defaults_negative_extrude"); let code = kcl_input!("helix_defaults_negative_extrude");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("helix_defaults_negative_extrude", &result); assert_out("helix_defaults_negative_extrude", &result);
} }
@ -126,7 +126,7 @@ async fn kcl_test_helix_defaults_negative_extrude() {
async fn kcl_test_helix_with_length() { async fn kcl_test_helix_with_length() {
let code = kcl_input!("helix_with_length"); let code = kcl_input!("helix_with_length");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("helix_with_length", &result); assert_out("helix_with_length", &result);
} }
@ -134,7 +134,7 @@ async fn kcl_test_helix_with_length() {
async fn kcl_test_dimensions_match() { async fn kcl_test_dimensions_match() {
let code = kcl_input!("dimensions_match"); let code = kcl_input!("dimensions_match");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("dimensions_match", &result); assert_out("dimensions_match", &result);
} }
@ -142,7 +142,7 @@ async fn kcl_test_dimensions_match() {
async fn kcl_test_close_arc() { async fn kcl_test_close_arc() {
let code = kcl_input!("close_arc"); let code = kcl_input!("close_arc");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("close_arc", &result); assert_out("close_arc", &result);
} }
@ -150,7 +150,7 @@ async fn kcl_test_close_arc() {
async fn kcl_test_negative_args() { async fn kcl_test_negative_args() {
let code = kcl_input!("negative_args"); let code = kcl_input!("negative_args");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("negative_args", &result); assert_out("negative_args", &result);
} }
@ -164,7 +164,7 @@ async fn kcl_test_basic_tangential_arc_with_point() {
|> extrude(length = 10) |> extrude(length = 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("tangential_arc_with_point", &result); assert_out("tangential_arc_with_point", &result);
} }
@ -178,7 +178,7 @@ async fn kcl_test_basic_tangential_arc_to() {
|> extrude(length = 10) |> extrude(length = 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("tangential_arc_to", &result); assert_out("tangential_arc_to", &result);
} }
@ -205,7 +205,7 @@ box(30, 43, 18, '-xy')
let thing = box(-12, -15, 10, 'yz') let thing = box(-12, -15, 10, 'yz')
box(-20, -5, 10, 'xy')"#; box(-20, -5, 10, 'xy')"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("different_planes_same_drawing", &result); assert_out("different_planes_same_drawing", &result);
} }
@ -263,7 +263,7 @@ part004 = startSketchOn(YZ)
|> close() |> close()
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("lots_of_planes", &result); assert_out("lots_of_planes", &result);
} }
@ -280,7 +280,7 @@ async fn kcl_test_holes() {
|> extrude(length = 2) |> extrude(length = 2)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("holes", &result); assert_out("holes", &result);
} }
@ -299,7 +299,7 @@ async fn optional_params() {
thing = other_circle([2, 2], 20) thing = other_circle([2, 2], 20)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("optional_params", &result); assert_out("optional_params", &result);
} }
@ -335,7 +335,7 @@ part = roundedRectangle([0, 0], 20, 20, 4)
|> extrude(length = 2) |> extrude(length = 2)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("rounded_with_holes", &result); assert_out("rounded_with_holes", &result);
} }
@ -343,7 +343,7 @@ part = roundedRectangle([0, 0], 20, 20, 4)
async fn kcl_test_top_level_expression() { async fn kcl_test_top_level_expression() {
let code = r#"startSketchOn(XY) |> circle(center = [0,0], radius= 22) |> extrude(length = 14)"#; let code = r#"startSketchOn(XY) |> circle(center = [0,0], radius= 22) |> extrude(length = 14)"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("top_level_expression", &result); assert_out("top_level_expression", &result);
} }
@ -357,7 +357,7 @@ part = startSketchOn(XY)
|> extrude(length = 1) |> extrude(length = 1)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("patterns_linear_basic_with_math", &result); assert_out("patterns_linear_basic_with_math", &result);
} }
@ -369,7 +369,7 @@ async fn kcl_test_patterns_linear_basic() {
|> extrude(length = 1) |> extrude(length = 1)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("patterns_linear_basic", &result); assert_out("patterns_linear_basic", &result);
} }
@ -385,7 +385,7 @@ async fn kcl_test_patterns_linear_basic_3d() {
|> patternLinear3d(axis = [1, 0, 1], instances = 4, distance = 6) |> patternLinear3d(axis = [1, 0, 1], instances = 4, distance = 6)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("patterns_linear_basic_3d", &result); assert_out("patterns_linear_basic_3d", &result);
} }
@ -397,7 +397,7 @@ async fn kcl_test_patterns_linear_basic_negative_distance() {
|> extrude(length = 1) |> extrude(length = 1)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("patterns_linear_basic_negative_distance", &result); assert_out("patterns_linear_basic_negative_distance", &result);
} }
@ -409,7 +409,7 @@ async fn kcl_test_patterns_linear_basic_negative_axis() {
|> extrude(length = 1) |> extrude(length = 1)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("patterns_linear_basic_negative_axis", &result); assert_out("patterns_linear_basic_negative_axis", &result);
} }
@ -430,7 +430,7 @@ rectangle = startSketchOn(XY)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("patterns_linear_basic_holes", &result); assert_out("patterns_linear_basic_holes", &result);
} }
@ -442,7 +442,7 @@ async fn kcl_test_patterns_circular_basic_2d() {
|> extrude(length = 1) |> extrude(length = 1)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("patterns_circular_basic_2d", &result); assert_out("patterns_circular_basic_2d", &result);
} }
@ -458,7 +458,7 @@ async fn kcl_test_patterns_circular_basic_3d() {
|> patternCircular3d(axis = [0,0, 1], center = [-20, -20, -20], instances = 41, arcDegrees = 360, rotateDuplicates = false) |> patternCircular3d(axis = [0,0, 1], center = [-20, -20, -20], instances = 41, arcDegrees = 360, rotateDuplicates = false)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("patterns_circular_basic_3d", &result); assert_out("patterns_circular_basic_3d", &result);
} }
@ -474,7 +474,7 @@ async fn kcl_test_patterns_circular_3d_tilted_axis() {
|> patternCircular3d(axis = [1,1,0], center = [10, 0, 10], instances = 11, arcDegrees = 360, rotateDuplicates = true) |> patternCircular3d(axis = [1,1,0], center = [10, 0, 10], instances = 11, arcDegrees = 360, rotateDuplicates = true)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("patterns_circular_3d_tilted_axis", &result); assert_out("patterns_circular_3d_tilted_axis", &result);
} }
@ -483,7 +483,7 @@ async fn kcl_test_import_file_doesnt_exist() {
let code = r#"import 'thing.obj' let code = r#"import 'thing.obj'
model = cube"#; model = cube"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -496,7 +496,7 @@ async fn kcl_test_import_obj_with_mtl() {
let code = r#"import 'e2e/executor/inputs/cube.obj' let code = r#"import 'e2e/executor/inputs/cube.obj'
model = cube"#; model = cube"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("import_obj_with_mtl", &result); assert_out("import_obj_with_mtl", &result);
} }
@ -506,7 +506,7 @@ async fn kcl_test_import_obj_with_mtl_units() {
import 'e2e/executor/inputs/cube.obj' import 'e2e/executor/inputs/cube.obj'
model = cube"#; model = cube"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("import_obj_with_mtl_units", &result); assert_out("import_obj_with_mtl_units", &result);
} }
@ -515,7 +515,7 @@ async fn kcl_test_import_stl() {
let code = r#"import 'e2e/executor/inputs/2-5-long-m8-chc-screw.stl' as screw let code = r#"import 'e2e/executor/inputs/2-5-long-m8-chc-screw.stl' as screw
model = screw"#; model = screw"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("import_stl", &result); assert_out("import_stl", &result);
} }
@ -524,7 +524,7 @@ async fn kcl_test_import_gltf_with_bin() {
let code = r#"import 'e2e/executor/inputs/cube.gltf' let code = r#"import 'e2e/executor/inputs/cube.gltf'
model = cube"#; model = cube"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("import_gltf_with_bin", &result); assert_out("import_gltf_with_bin", &result);
} }
@ -533,7 +533,7 @@ async fn kcl_test_import_gltf_embedded() {
let code = r#"import 'e2e/executor/inputs/cube-embedded.gltf' as cube let code = r#"import 'e2e/executor/inputs/cube-embedded.gltf' as cube
model = cube"#; model = cube"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("import_gltf_embedded", &result); assert_out("import_gltf_embedded", &result);
} }
@ -542,7 +542,7 @@ async fn kcl_test_import_glb() {
let code = r#"import 'e2e/executor/inputs/cube.glb' let code = r#"import 'e2e/executor/inputs/cube.glb'
model = cube"#; model = cube"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("import_glb", &result); assert_out("import_glb", &result);
} }
@ -551,7 +551,7 @@ async fn kcl_test_import_glb_no_assign() {
let code = r#"import 'e2e/executor/inputs/cube.glb' let code = r#"import 'e2e/executor/inputs/cube.glb'
cube"#; cube"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("import_glb_no_assign", &result); assert_out("import_glb_no_assign", &result);
} }
@ -561,7 +561,7 @@ async fn kcl_test_import_ext_doesnt_match() {
import 'e2e/executor/inputs/cube.gltf' import 'e2e/executor/inputs/cube.gltf'
model = cube"#; model = cube"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -586,14 +586,15 @@ async fn kcl_test_cube_mm() {
myCube = cube([0,0], 10) myCube = cube([0,0], 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("cube_mm", &result); assert_out("cube_mm", &result);
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cube_cm() { async fn kcl_test_cube_cm() {
let code = r#"fn cube = (pos, scale) => { let code = r#"@settings(defaultLengthUnit = cm)
sg = startSketchOn(XY) fn cube = (pos, scale) => {
sg = startSketchOn('XY')
|> startProfileAt(pos, %) |> startProfileAt(pos, %)
|> line(end = [0, scale]) |> line(end = [0, scale])
|> line(end = [scale, 0]) |> line(end = [scale, 0])
@ -607,14 +608,15 @@ async fn kcl_test_cube_cm() {
myCube = cube([0,0], 10) myCube = cube([0,0], 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Cm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("cube_cm", &result); assert_out("cube_cm", &result);
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cube_m() { async fn kcl_test_cube_m() {
let code = r#"fn cube = (pos, scale) => { let code = r#"@settings(defaultLengthUnit = m)
sg = startSketchOn(XY) fn cube = (pos, scale) => {
sg = startSketchOn('XY')
|> startProfileAt(pos, %) |> startProfileAt(pos, %)
|> line(end = [0, scale]) |> line(end = [0, scale])
|> line(end = [scale, 0]) |> line(end = [scale, 0])
@ -628,14 +630,15 @@ async fn kcl_test_cube_m() {
myCube = cube([0,0], 10) myCube = cube([0,0], 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::M, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("cube_m", &result); assert_out("cube_m", &result);
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cube_in() { async fn kcl_test_cube_in() {
let code = r#"fn cube = (pos, scale) => { let code = r#"@settings(defaultLengthUnit = in)
sg = startSketchOn(XY) fn cube = (pos, scale) => {
sg = startSketchOn('XY')
|> startProfileAt(pos, %) |> startProfileAt(pos, %)
|> line(end = [0, scale]) |> line(end = [0, scale])
|> line(end = [scale, 0]) |> line(end = [scale, 0])
@ -649,14 +652,15 @@ async fn kcl_test_cube_in() {
myCube = cube([0,0], 10) myCube = cube([0,0], 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::In, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("cube_in", &result); assert_out("cube_in", &result);
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cube_ft() { async fn kcl_test_cube_ft() {
let code = r#"fn cube = (pos, scale) => { let code = r#"@settings(defaultLengthUnit = ft)
sg = startSketchOn(XY) fn cube = (pos, scale) => {
sg = startSketchOn('XY')
|> startProfileAt(pos, %) |> startProfileAt(pos, %)
|> line(end = [0, scale]) |> line(end = [0, scale])
|> line(end = [scale, 0]) |> line(end = [scale, 0])
@ -670,14 +674,15 @@ async fn kcl_test_cube_ft() {
myCube = cube([0,0], 10) myCube = cube([0,0], 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Ft, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("cube_ft", &result); assert_out("cube_ft", &result);
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cube_yd() { async fn kcl_test_cube_yd() {
let code = r#"fn cube = (pos, scale) => { let code = r#"@settings(defaultLengthUnit = yd)
sg = startSketchOn(XY) fn cube = (pos, scale) => {
sg = startSketchOn('XY')
|> startProfileAt(pos, %) |> startProfileAt(pos, %)
|> line(end = [0, scale]) |> line(end = [0, scale])
|> line(end = [scale, 0]) |> line(end = [scale, 0])
@ -691,7 +696,7 @@ async fn kcl_test_cube_yd() {
myCube = cube([0,0], 10) myCube = cube([0,0], 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Yd, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("cube_yd", &result); assert_out("cube_yd", &result);
} }
@ -719,7 +724,7 @@ part002 = startSketchOn(part001, part001.sketch.tags.here)
|> extrude(length = 1) |> extrude(length = 1)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
let err = result.err().unwrap(); let err = result.err().unwrap();
let ExecError::Kcl(err) = err else { let ExecError::Kcl(err) = err else {
@ -763,7 +768,7 @@ part003 = startSketchOn(part002, "end")
|> extrude(length = 5) |> extrude(length = 5)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("sketch_on_face_of_face", &result); assert_out("sketch_on_face_of_face", &result);
} }
@ -780,7 +785,7 @@ async fn kcl_test_stdlib_kcl_error_right_code_path() {
|> extrude(length = 2) |> extrude(length = 2)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
let err = result.err().unwrap(); let err = result.err().unwrap();
let ExecError::Kcl(err) = err else { let ExecError::Kcl(err) = err else {
panic!("Expected KCL error, found {err}"); panic!("Expected KCL error, found {err}");
@ -811,7 +816,7 @@ part002 = startSketchOn(part001, "end")
|> extrude(length = 5) |> extrude(length = 5)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("sketch_on_face_circle", &result); assert_out("sketch_on_face_circle", &result);
} }
@ -853,7 +858,7 @@ part = rectShape([0, 0], 20, 20)
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
let err = result.err().unwrap(); let err = result.err().unwrap();
let ExecError::Kcl(err) = err else { let ExecError::Kcl(err) = err else {
panic!("Expected KCL error, found {err}"); panic!("Expected KCL error, found {err}");
@ -880,7 +885,7 @@ async fn kcl_test_simple_revolve() {
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("simple_revolve", &result); assert_out("simple_revolve", &result);
} }
@ -900,7 +905,7 @@ async fn kcl_test_simple_revolve_uppercase() {
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("simple_revolve_uppercase", &result); assert_out("simple_revolve_uppercase", &result);
} }
@ -920,7 +925,7 @@ async fn kcl_test_simple_revolve_negative() {
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("simple_revolve_negative", &result); assert_out("simple_revolve_negative", &result);
} }
@ -940,7 +945,7 @@ async fn kcl_test_revolve_bad_angle_low() {
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert!(result assert!(result
@ -966,7 +971,7 @@ async fn kcl_test_revolve_bad_angle_high() {
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert!(result assert!(result
@ -992,7 +997,7 @@ async fn kcl_test_simple_revolve_custom_angle() {
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("simple_revolve_custom_angle", &result); assert_out("simple_revolve_custom_angle", &result);
} }
@ -1012,7 +1017,7 @@ async fn kcl_test_simple_revolve_custom_axis() {
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("simple_revolve_custom_axis", &result); assert_out("simple_revolve_custom_axis", &result);
} }
@ -1036,7 +1041,7 @@ sketch001 = startSketchOn(box, "end")
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("revolve_on_edge", &result); assert_out("revolve_on_edge", &result);
} }
@ -1060,7 +1065,7 @@ sketch001 = startSketchOn(box, revolveAxis)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
result.unwrap_err(); result.unwrap_err();
//this fails right now, but slightly differently, lets just say its enough for it to fail - mike //this fails right now, but slightly differently, lets just say its enough for it to fail - mike
@ -1088,7 +1093,7 @@ sketch001 = startSketchOn(box, "END")
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("revolve_on_face_circle_edge", &result); assert_out("revolve_on_face_circle_edge", &result);
} }
@ -1110,7 +1115,7 @@ sketch001 = startSketchOn(box, "END")
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("revolve_on_face_circle", &result); assert_out("revolve_on_face_circle", &result);
} }
@ -1136,7 +1141,7 @@ sketch001 = startSketchOn(box, "end")
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("revolve_on_face", &result); assert_out("revolve_on_face", &result);
} }
@ -1150,7 +1155,7 @@ async fn kcl_test_basic_revolve_circle() {
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("basic_revolve_circle", &result); assert_out("basic_revolve_circle", &result);
} }
@ -1177,7 +1182,7 @@ part002 = startSketchOn(part001, 'end')
|> extrude(length = 5) |> extrude(length = 5)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("simple_revolve_sketch_on_edge", &result); assert_out("simple_revolve_sketch_on_edge", &result);
} }
@ -1240,7 +1245,7 @@ plumbus1 = circle1
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("plumbus_fillets", &result); assert_out("plumbus_fillets", &result);
} }
@ -1248,7 +1253,7 @@ plumbus1 = circle1
async fn kcl_test_empty_file_is_ok() { async fn kcl_test_empty_file_is_ok() {
let code = r#""#; let code = r#""#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
result.unwrap(); result.unwrap();
} }
@ -1278,7 +1283,7 @@ async fn kcl_test_member_expression_in_params() {
capScrew([0, 0.5, 0], 50, 37.5, 50, 25) capScrew([0, 0.5, 0], 50, 37.5, 50, 25)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("member_expression_in_params", &result); assert_out("member_expression_in_params", &result);
} }
@ -1323,7 +1328,7 @@ bracket = startSketchOn(XY)
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
result.unwrap(); result.unwrap();
} }
@ -1343,7 +1348,7 @@ secondSketch = startSketchOn(part001, '')
|> extrude(length = 20) |> extrude(length = 20)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1374,7 +1379,7 @@ extrusion = startSketchOn(XY)
|> extrude(length = height) |> extrude(length = height)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1407,7 +1412,7 @@ sketch001 = [profile001, profile002]
extrude(sketch001, length = 10) extrude(sketch001, length = 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("array_of_sketches", &result); assert_out("array_of_sketches", &result);
} }
@ -1444,7 +1449,7 @@ pattn1 = patternLinear3d(
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("pattern3d_array_of_extrudes", &result); assert_out("pattern3d_array_of_extrudes", &result);
} }
@ -1492,7 +1497,7 @@ baseExtrusion = extrude(sketch001, length = width)
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("fillets_referencing_other_fillets", &result); assert_out("fillets_referencing_other_fillets", &result);
} }
@ -1540,7 +1545,7 @@ baseExtrusion = extrude(sketch001, length = width)
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("chamfers_referencing_other_chamfers", &result); assert_out("chamfers_referencing_other_chamfers", &result);
} }
@ -1560,7 +1565,7 @@ async fn kcl_test_shell_with_tag() {
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("shell_with_tag", &result); assert_out("shell_with_tag", &result);
} }
@ -1591,7 +1596,7 @@ pattn1 = patternLinear3d(
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("linear_pattern3d_filleted_sketch", &result); assert_out("linear_pattern3d_filleted_sketch", &result);
} }
@ -1618,7 +1623,7 @@ pattn2 = patternCircular3d(part001, axis = [0,0, 1], center = [-20, -20, -20], i
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("circular_pattern3d_filleted_sketch", &result); assert_out("circular_pattern3d_filleted_sketch", &result);
} }
@ -1644,7 +1649,7 @@ part001 = cube([0,0], 20)
pattn2 = patternCircular3d(part001, axis = [0,0, 1], center = [-20, -20, -20], instances = 5, arcDegrees = 360, rotateDuplicates = false) pattn2 = patternCircular3d(part001, axis = [0,0, 1], center = [-20, -20, -20], instances = 5, arcDegrees = 360, rotateDuplicates = false)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("circular_pattern3d_chamfered_sketch", &result); assert_out("circular_pattern3d_chamfered_sketch", &result);
} }
@ -1671,7 +1676,7 @@ part001 = cube([0,0], 20)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
let err = result.err().unwrap(); let err = result.err().unwrap();
let ExecError::Kcl(err) = err else { let ExecError::Kcl(err) = err else {
panic!("Expected KCL error, found {err}"); panic!("Expected KCL error, found {err}");
@ -1701,7 +1706,7 @@ async fn kcl_test_duplicate_tags_should_error() {
let p = triangle(200) let p = triangle(200)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1712,49 +1717,49 @@ let p = triangle(200)
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_global_tags() { async fn kcl_test_global_tags() {
let code = kcl_input!("global-tags"); let code = kcl_input!("global-tags");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("global_tags", &result); assert_out("global_tags", &result);
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_extrude_inside_fn_with_tags() { async fn kcl_test_extrude_inside_fn_with_tags() {
let code = kcl_input!("extrude-inside-fn-with-tags"); let code = kcl_input!("extrude-inside-fn-with-tags");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("extrude-inside-fn-with-tags", &result); assert_out("extrude-inside-fn-with-tags", &result);
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_pattern_vase() { async fn kcl_test_pattern_vase() {
let code = kcl_input!("pattern_vase"); let code = kcl_input!("pattern_vase");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("pattern_vase", &result); assert_out("pattern_vase", &result);
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_scoped_tags() { async fn kcl_test_scoped_tags() {
let code = kcl_input!("scoped-tags"); let code = kcl_input!("scoped-tags");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("scoped_tags", &result); assert_out("scoped_tags", &result);
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_order_sketch_extrude_in_order() { async fn kcl_test_order_sketch_extrude_in_order() {
let code = kcl_input!("order-sketch-extrude-in-order"); let code = kcl_input!("order-sketch-extrude-in-order");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("order-sketch-extrude-in-order", &result); assert_out("order-sketch-extrude-in-order", &result);
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_order_sketch_extrude_out_of_order() { async fn kcl_test_order_sketch_extrude_out_of_order() {
let code = kcl_input!("order-sketch-extrude-out-of-order"); let code = kcl_input!("order-sketch-extrude-out-of-order");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("order-sketch-extrude-out-of-order", &result); assert_out("order-sketch-extrude-out-of-order", &result);
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_extrude_custom_plane() { async fn kcl_test_extrude_custom_plane() {
let code = kcl_input!("extrude-custom-plane"); let code = kcl_input!("extrude-custom-plane");
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap(); let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("extrude-custom-plane", &result); assert_out("extrude-custom-plane", &result);
} }
@ -1776,7 +1781,7 @@ async fn kcl_test_arc_error_same_start_end() {
) )
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1796,7 +1801,7 @@ async fn kcl_test_angled_line_to_x_90() {
example = extrude(exampleSketch, length = 10) example = extrude(exampleSketch, length = 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1816,7 +1821,7 @@ async fn kcl_test_angled_line_to_x_270() {
example = extrude(exampleSketch, length = 10) example = extrude(exampleSketch, length = 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1836,7 +1841,7 @@ async fn kcl_test_angled_line_to_y_0() {
example = extrude(exampleSketch, length = 10) example = extrude(exampleSketch, length = 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1856,7 +1861,7 @@ async fn kcl_test_angled_line_to_y_180() {
example = extrude(exampleSketch, length = 10) example = extrude(exampleSketch, length = 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1876,7 +1881,7 @@ async fn kcl_test_angled_line_of_x_length_90() {
extrusion = extrude(sketch001, length = 10) extrusion = extrude(sketch001, length = 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1896,7 +1901,7 @@ async fn kcl_test_angled_line_of_x_length_270() {
extrusion = extrude(sketch001, length = 10) extrusion = extrude(sketch001, length = 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1918,7 +1923,7 @@ async fn kcl_test_angled_line_of_y_length_0() {
example = extrude(exampleSketch, length = 10) example = extrude(exampleSketch, length = 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1940,7 +1945,7 @@ async fn kcl_test_angled_line_of_y_length_180() {
example = extrude(exampleSketch, length = 10) example = extrude(exampleSketch, length = 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1962,7 +1967,7 @@ async fn kcl_test_angled_line_of_y_length_negative_180() {
example = extrude(exampleSketch, length = 10) example = extrude(exampleSketch, length = 10)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -1979,7 +1984,7 @@ async fn kcl_test_error_inside_fn_also_has_source_range_of_call_site() {
someFunction('INVALID') someFunction('INVALID')
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -2000,7 +2005,7 @@ async fn kcl_test_error_inside_fn_also_has_source_range_of_call_site_recursive()
someFunction('INVALID') someFunction('INVALID')
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
@ -2024,7 +2029,7 @@ async fn kcl_test_error_no_auth_websocket() {
) )
"#; "#;
let result = execute_and_snapshot_no_auth(code, UnitLength::Mm, None).await; let result = execute_and_snapshot_no_auth(code, None).await;
assert!(result.is_err()); assert!(result.is_err());
assert!(result assert!(result
.err() .err()
@ -2050,9 +2055,7 @@ sketch000 = startSketchOn(XY)
|> line(end = [0, innerDiameter / 2]) |> line(end = [0, innerDiameter / 2])
"#; "#;
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default()) let ctx = kcl_lib::ExecutorContext::new_with_default_client().await.unwrap();
.await
.unwrap();
let mut exec_state = kcl_lib::ExecState::new(&ctx); let mut exec_state = kcl_lib::ExecState::new(&ctx);
let program = kcl_lib::Program::parse_no_errs(code).unwrap(); let program = kcl_lib::Program::parse_no_errs(code).unwrap();
ctx.run(&program, &mut exec_state).await.unwrap(); ctx.run(&program, &mut exec_state).await.unwrap();
@ -2075,9 +2078,7 @@ async fn kcl_test_ensure_nothing_left_in_batch_multi_file() {
// Change the current working directory to the test directory. // Change the current working directory to the test directory.
std::env::set_current_dir(path.parent().unwrap()).unwrap(); std::env::set_current_dir(path.parent().unwrap()).unwrap();
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default()) let ctx = kcl_lib::ExecutorContext::new_with_default_client().await.unwrap();
.await
.unwrap();
let mut exec_state = kcl_lib::ExecState::new(&ctx); let mut exec_state = kcl_lib::ExecState::new(&ctx);
let program = kcl_lib::Program::parse_no_errs(&code).unwrap(); let program = kcl_lib::Program::parse_no_errs(&code).unwrap();
ctx.run(&program, &mut exec_state).await.unwrap(); ctx.run(&program, &mut exec_state).await.unwrap();
@ -2095,7 +2096,7 @@ async fn kcl_test_better_type_names() {
|> circle(center = [-95.51, -74.7], radius = 262.23) |> circle(center = [-95.51, -74.7], radius = 262.23)
|> appearance(metalness = 0.9) |> appearance(metalness = 0.9)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await; let result = execute_and_snapshot(code, None).await;
let err = match result.err() { let err = match result.err() {
Some(x) => match x { Some(x) => match x {
@ -2114,7 +2115,7 @@ async fn kcl_test_exporting_step_file() {
// This tests export like how we do it in cli and kcl.py. // This tests export like how we do it in cli and kcl.py.
let code = kcl_input!("helix_defaults_negative_extrude"); let code = kcl_input!("helix_defaults_negative_extrude");
let (_, _, files) = execute_and_export_step(code, UnitLength::Mm, None).await.unwrap(); let (_, _, files) = execute_and_export_step(code, None).await.unwrap();
for file in files { for file in files {
expectorate::assert_contents( expectorate::assert_contents(
format!("e2e/executor/outputs/helix_defaults_negative_extrude_{}", file.name), format!("e2e/executor/outputs/helix_defaults_negative_extrude_{}", file.name),

View File

@ -1172,7 +1172,7 @@ fn find_examples(text: &str, filename: &str) -> Vec<(String, String)> {
async fn run_example(text: &str) -> Result<()> { async fn run_example(text: &str) -> Result<()> {
let program = crate::Program::parse_no_errs(text)?; let program = crate::Program::parse_no_errs(text)?;
let ctx = ExecutorContext::new_with_default_client(crate::UnitLength::Mm).await?; let ctx = ExecutorContext::new_with_default_client().await?;
let mut exec_state = crate::execution::ExecState::new(&ctx); let mut exec_state = crate::execution::ExecState::new(&ctx);
ctx.run(&program, &mut exec_state).await?; ctx.run(&program, &mut exec_state).await?;
Ok(()) Ok(())

View File

@ -1010,20 +1010,17 @@ mod test {
let std = walk_prelude(); let std = walk_prelude();
for d in std { for d in std {
for (i, eg) in d.examples().enumerate() { for (i, eg) in d.examples().enumerate() {
let result = let result = match crate::test_server::execute_and_snapshot(eg, None).await {
match crate::test_server::execute_and_snapshot(eg, crate::settings::types::UnitLength::Mm, None) Err(crate::errors::ExecError::Kcl(e)) => {
.await return Err(miette::Report::new(crate::errors::Report {
{ error: e.error,
Err(crate::errors::ExecError::Kcl(e)) => { filename: format!("{}{i}", d.name()),
return Err(miette::Report::new(crate::errors::Report { kcl_source: eg.to_string(),
error: e.error, }));
filename: format!("{}{i}", d.name()), }
kcl_source: eg.to_string(), Err(other_err) => panic!("{}", other_err),
})); Ok(img) => img,
} };
Err(other_err) => panic!("{}", other_err),
Ok(img) => img,
};
twenty_twenty::assert_image( twenty_twenty::assert_image(
format!("tests/outputs/serial_test_example_{}{i}.png", d.example_name()), format!("tests/outputs/serial_test_example_{}{i}.png", d.example_name()),
&result, &result,

View File

@ -176,6 +176,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
) )
.await?; .await?;
// Reset to the default units. Modules assume the engine starts in the
// default state.
self.set_units(Default::default(), source_range, id_generator).await?;
// Flush the batch queue, so clear is run right away. // Flush the batch queue, so clear is run right away.
// Otherwise the hooks below won't work. // Otherwise the hooks below won't work.
self.flush_batch(false, source_range).await?; self.flush_batch(false, source_range).await?;
@ -256,9 +260,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
self.set_edge_visibility(settings.highlight_edges, source_range, id_generator) self.set_edge_visibility(settings.highlight_edges, source_range, id_generator)
.await?; .await?;
// Change the units.
self.set_units(settings.units, source_range, id_generator).await?;
// Send the command to show the grid. // Send the command to show the grid.
self.modify_grid(!settings.show_grid, source_range, id_generator) self.modify_grid(!settings.show_grid, source_range, id_generator)
.await?; .await?;

View File

@ -97,15 +97,6 @@ pub(super) async fn get_changed_program(old: CacheInformation<'_>, new: CacheInf
// If the settings are different we might need to bust the cache. // If the settings are different we might need to bust the cache.
// We specifically do this before checking if they are the exact same. // We specifically do this before checking if they are the exact same.
if old.settings != new.settings { if old.settings != new.settings {
// If the units are different we need to re-execute the whole thing.
if old.settings.units != new.settings.units {
return CacheResult::ReExecute {
clear_scene: true,
reapply_settings: true,
program: new.ast.clone(),
};
}
// If anything else is different we may not need to re-execute, but rather just // If anything else is different we may not need to re-execute, but rather just
// run the settings again. // run the settings again.
reapply_settings = true; reapply_settings = true;
@ -424,50 +415,6 @@ shell(firstSketch, faces = ['end'], thickness = 0.25)"#;
assert_eq!(result, CacheResult::NoAction(false)); assert_eq!(result, CacheResult::NoAction(false));
} }
// Changing the units with the exact same file should bust the cache.
#[tokio::test(flavor = "multi_thread")]
async fn test_get_changed_program_same_code_but_different_units() {
let new = r#"// Remove the end face for the extrusion.
firstSketch = startSketchOn('XY')
|> startProfileAt([-12, 12], %)
|> line(end = [24, 0])
|> line(end = [0, -24])
|> line(end = [-24, 0])
|> close()
|> extrude(length = 6)
// Remove the end face for the extrusion.
shell(firstSketch, faces = ['end'], thickness = 0.25)"#;
let ExecTestResults {
program, mut exec_ctxt, ..
} = parse_execute(new).await.unwrap();
// Change the settings to cm.
exec_ctxt.settings.units = crate::UnitLength::Cm;
let result = get_changed_program(
CacheInformation {
ast: &program.ast,
settings: &Default::default(),
},
CacheInformation {
ast: &program.ast,
settings: &exec_ctxt.settings,
},
)
.await;
assert_eq!(
result,
CacheResult::ReExecute {
clear_scene: true,
reapply_settings: true,
program: program.ast
}
);
}
// Changing the grid settings with the exact same file should NOT bust the cache. // Changing the grid settings with the exact same file should NOT bust the cache.
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn test_get_changed_program_same_code_but_different_grid_setting() { async fn test_get_changed_program_same_code_but_different_grid_setting() {
@ -615,4 +562,42 @@ startSketchOn('XY')
} }
); );
} }
// Removing the units settings using an annotation, when it was non-default
// units, with the exact same file should bust the cache.
#[tokio::test(flavor = "multi_thread")]
async fn test_get_changed_program_same_code_but_removed_unit_setting_using_annotation() {
let old_code = r#"@settings(defaultLengthUnit = in)
startSketchOn('XY')
"#;
let new_code = r#"
startSketchOn('XY')
"#;
let ExecTestResults { program, exec_ctxt, .. } = parse_execute(old_code).await.unwrap();
let mut new_program = crate::Program::parse_no_errs(new_code).unwrap();
new_program.compute_digest();
let result = get_changed_program(
CacheInformation {
ast: &program.ast,
settings: &exec_ctxt.settings,
},
CacheInformation {
ast: &new_program.ast,
settings: &exec_ctxt.settings,
},
)
.await;
assert_eq!(
result,
CacheResult::ReExecute {
clear_scene: true,
reapply_settings: true,
program: new_program.ast
}
);
}
} }

View File

@ -110,12 +110,7 @@ impl ExecutorContext {
let old_units = exec_state.length_unit(); let old_units = exec_state.length_unit();
let original_execution = self.engine.replace_execution_kind(exec_kind).await; let original_execution = self.engine.replace_execution_kind(exec_kind).await;
let mut local_state = ModuleState::new( let mut local_state = ModuleState::new(path.std_path(), exec_state.stack().memory.clone(), Some(module_id));
&self.settings,
path.std_path(),
exec_state.stack().memory.clone(),
Some(module_id),
);
if !preserve_mem { if !preserve_mem {
std::mem::swap(&mut exec_state.mod_local, &mut local_state); std::mem::swap(&mut exec_state.mod_local, &mut local_state);
} }

View File

@ -39,7 +39,6 @@ use crate::{
fs::FileManager, fs::FileManager,
modules::{ModuleId, ModulePath}, modules::{ModuleId, ModulePath},
parsing::ast::types::{Expr, ImportPath, NodeRef}, parsing::ast::types::{Expr, ImportPath, NodeRef},
settings::types::UnitLength,
source_range::SourceRange, source_range::SourceRange,
std::StdLib, std::StdLib,
CompilationError, ExecError, ExecutionKind, KclErrorWithOutputs, CompilationError, ExecError, ExecutionKind, KclErrorWithOutputs,
@ -265,8 +264,6 @@ pub struct ExecutorContext {
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)] #[ts(export)]
pub struct ExecutorSettings { pub struct ExecutorSettings {
/// The project-default unit to use in modeling dimensions.
pub units: UnitLength,
/// Highlight edges of 3D objects? /// Highlight edges of 3D objects?
pub highlight_edges: bool, pub highlight_edges: bool,
/// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled. /// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled.
@ -287,7 +284,6 @@ pub struct ExecutorSettings {
impl Default for ExecutorSettings { impl Default for ExecutorSettings {
fn default() -> Self { fn default() -> Self {
Self { Self {
units: Default::default(),
highlight_edges: true, highlight_edges: true,
enable_ssao: false, enable_ssao: false,
show_grid: false, show_grid: false,
@ -301,7 +297,6 @@ impl Default for ExecutorSettings {
impl From<crate::settings::types::Configuration> for ExecutorSettings { impl From<crate::settings::types::Configuration> for ExecutorSettings {
fn from(config: crate::settings::types::Configuration) -> Self { fn from(config: crate::settings::types::Configuration) -> Self {
Self { Self {
units: config.settings.modeling.base_unit,
highlight_edges: config.settings.modeling.highlight_edges.into(), highlight_edges: config.settings.modeling.highlight_edges.into(),
enable_ssao: config.settings.modeling.enable_ssao.into(), enable_ssao: config.settings.modeling.enable_ssao.into(),
show_grid: config.settings.modeling.show_scale_grid, show_grid: config.settings.modeling.show_scale_grid,
@ -315,7 +310,6 @@ impl From<crate::settings::types::Configuration> for ExecutorSettings {
impl From<crate::settings::types::project::ProjectConfiguration> for ExecutorSettings { impl From<crate::settings::types::project::ProjectConfiguration> for ExecutorSettings {
fn from(config: crate::settings::types::project::ProjectConfiguration) -> Self { fn from(config: crate::settings::types::project::ProjectConfiguration) -> Self {
Self { Self {
units: config.settings.modeling.base_unit,
highlight_edges: config.settings.modeling.highlight_edges.into(), highlight_edges: config.settings.modeling.highlight_edges.into(),
enable_ssao: config.settings.modeling.enable_ssao.into(), enable_ssao: config.settings.modeling.enable_ssao.into(),
show_grid: Default::default(), show_grid: Default::default(),
@ -329,7 +323,6 @@ impl From<crate::settings::types::project::ProjectConfiguration> for ExecutorSet
impl From<crate::settings::types::ModelingSettings> for ExecutorSettings { impl From<crate::settings::types::ModelingSettings> for ExecutorSettings {
fn from(modeling: crate::settings::types::ModelingSettings) -> Self { fn from(modeling: crate::settings::types::ModelingSettings) -> Self {
Self { Self {
units: modeling.base_unit,
highlight_edges: modeling.highlight_edges.into(), highlight_edges: modeling.highlight_edges.into(),
enable_ssao: modeling.enable_ssao.into(), enable_ssao: modeling.enable_ssao.into(),
show_grid: modeling.show_scale_grid, show_grid: modeling.show_scale_grid,
@ -343,7 +336,6 @@ impl From<crate::settings::types::ModelingSettings> for ExecutorSettings {
impl From<crate::settings::types::project::ProjectModelingSettings> for ExecutorSettings { impl From<crate::settings::types::project::ProjectModelingSettings> for ExecutorSettings {
fn from(modeling: crate::settings::types::project::ProjectModelingSettings) -> Self { fn from(modeling: crate::settings::types::project::ProjectModelingSettings) -> Self {
Self { Self {
units: modeling.base_unit,
highlight_edges: modeling.highlight_edges.into(), highlight_edges: modeling.highlight_edges.into(),
enable_ssao: modeling.enable_ssao.into(), enable_ssao: modeling.enable_ssao.into(),
show_grid: Default::default(), show_grid: Default::default(),
@ -476,26 +468,17 @@ impl ExecutorContext {
/// This allows for passing in `ZOO_API_TOKEN` and `ZOO_HOST` as environment /// This allows for passing in `ZOO_API_TOKEN` and `ZOO_HOST` as environment
/// variables. /// variables.
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub async fn new_with_default_client(units: UnitLength) -> Result<Self> { pub async fn new_with_default_client() -> Result<Self> {
// Create the client. // Create the client.
let ctx = Self::new_with_client( let ctx = Self::new_with_client(Default::default(), None, None).await?;
ExecutorSettings {
units,
..Default::default()
},
None,
None,
)
.await?;
Ok(ctx) Ok(ctx)
} }
/// For executing unit tests. /// For executing unit tests.
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub async fn new_for_unit_test(units: UnitLength, engine_addr: Option<String>) -> Result<Self> { pub async fn new_for_unit_test(engine_addr: Option<String>) -> Result<Self> {
let ctx = ExecutorContext::new_with_client( let ctx = ExecutorContext::new_with_client(
ExecutorSettings { ExecutorSettings {
units,
highlight_edges: true, highlight_edges: true,
enable_ssao: false, enable_ssao: false,
show_grid: false, show_grid: false,
@ -862,11 +845,6 @@ impl ExecutorContext {
Ok(()) Ok(())
} }
/// Update the units for the executor.
pub(crate) fn update_units(&mut self, units: UnitLength) {
self.settings.units = units;
}
/// Get a snapshot of the current scene. /// Get a snapshot of the current scene.
pub async fn prepare_snapshot(&self) -> std::result::Result<TakeSnapshot, ExecError> { pub async fn prepare_snapshot(&self) -> std::result::Result<TakeSnapshot, ExecError> {
// Zoom to fit. // Zoom to fit.
@ -1008,11 +986,7 @@ mod tests {
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use super::*; use super::*;
use crate::{ use crate::{errors::KclErrorDetails, execution::memory::Stack, ModuleId};
errors::{KclErrorDetails, Severity},
execution::memory::Stack,
ModuleId,
};
/// Convenience function to get a JSON value from memory and unwrap. /// Convenience function to get a JSON value from memory and unwrap.
#[track_caller] #[track_caller]
@ -1615,34 +1589,6 @@ const inInches = 2.0 * inch()"#;
); );
} }
#[tokio::test(flavor = "multi_thread")]
async fn test_unit_suggest() {
let src = "foo = 42";
let program = crate::Program::parse_no_errs(src).unwrap();
let ctx = ExecutorContext {
engine: Arc::new(Box::new(
crate::engine::conn_mock::EngineConnection::new().await.unwrap(),
)),
fs: Arc::new(crate::fs::FileManager::new()),
stdlib: Arc::new(crate::std::StdLib::new()),
settings: ExecutorSettings {
units: UnitLength::Ft,
..Default::default()
},
context_type: ContextType::Mock,
};
let mut exec_state = ExecState::new(&ctx);
ctx.run(&program, &mut exec_state).await.unwrap();
let errs = exec_state.errors();
assert_eq!(errs.len(), 1, "{errs:?}");
let warn = &errs[0];
assert_eq!(warn.severity, Severity::Warning);
assert_eq!(
warn.apply_suggestion(src).unwrap(),
"@settings(defaultLengthUnit = ft)\nfoo = 42"
)
}
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn test_zero_param_fn() { async fn test_zero_param_fn() {
let ast = r#"const sigmaAllow = 35000 // psi let ast = r#"const sigmaAllow = 35000 // psi
@ -1971,9 +1917,7 @@ let w = f() + f()
) )
"#; "#;
let ctx = crate::test_server::new_context(UnitLength::Mm, true, None) let ctx = crate::test_server::new_context(true, None).await.unwrap();
.await
.unwrap();
let old_program = crate::Program::parse_no_errs(code).unwrap(); let old_program = crate::Program::parse_no_errs(code).unwrap();
// Execute the program. // Execute the program.
@ -2026,9 +1970,7 @@ let w = f() + f()
) )
"#; "#;
let mut ctx = crate::test_server::new_context(UnitLength::Mm, true, None) let mut ctx = crate::test_server::new_context(true, None).await.unwrap();
.await
.unwrap();
let old_program = crate::Program::parse_no_errs(code).unwrap(); let old_program = crate::Program::parse_no_errs(code).unwrap();
// Execute the program. // Execute the program.
@ -2066,7 +2008,7 @@ let w = f() + f()
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn mock_after_not_mock() { async fn mock_after_not_mock() {
let ctx = ExecutorContext::new_with_default_client(UnitLength::Mm).await.unwrap(); let ctx = ExecutorContext::new_with_default_client().await.unwrap();
let program = crate::Program::parse_no_errs("x = 2").unwrap(); let program = crate::Program::parse_no_errs("x = 2").unwrap();
let result = ctx.run_with_caching(program).await.unwrap(); let result = ctx.run_with_caching(program).await.unwrap();
assert_eq!(result.variables.get("x").unwrap().as_f64().unwrap(), 2.0); assert_eq!(result.variables.get("x").unwrap().as_f64().unwrap(), 2.0);

View File

@ -82,7 +82,7 @@ impl ExecState {
pub fn new(exec_context: &super::ExecutorContext) -> Self { pub fn new(exec_context: &super::ExecutorContext) -> Self {
ExecState { ExecState {
global: GlobalState::new(&exec_context.settings), global: GlobalState::new(&exec_context.settings),
mod_local: ModuleState::new(&exec_context.settings, None, ProgramMemory::new(), Default::default()), mod_local: ModuleState::new(None, ProgramMemory::new(), Default::default()),
exec_context: Some(exec_context.clone()), exec_context: Some(exec_context.clone()),
} }
} }
@ -92,7 +92,7 @@ impl ExecState {
*self = ExecState { *self = ExecState {
global, global,
mod_local: ModuleState::new(&exec_context.settings, None, ProgramMemory::new(), Default::default()), mod_local: ModuleState::new(None, ProgramMemory::new(), Default::default()),
exec_context: Some(exec_context.clone()), exec_context: Some(exec_context.clone()),
}; };
} }
@ -289,12 +289,7 @@ impl GlobalState {
} }
impl ModuleState { impl ModuleState {
pub(super) fn new( pub(super) fn new(std_path: Option<String>, memory: Arc<ProgramMemory>, module_id: Option<ModuleId>) -> Self {
exec_settings: &ExecutorSettings,
std_path: Option<String>,
memory: Arc<ProgramMemory>,
module_id: Option<ModuleId>,
) -> Self {
ModuleState { ModuleState {
id_generator: IdGenerator::new(module_id), id_generator: IdGenerator::new(module_id),
stack: memory.new_stack(), stack: memory.new_stack(),
@ -303,14 +298,14 @@ impl ModuleState {
explicit_length_units: false, explicit_length_units: false,
std_path, std_path,
settings: MetaSettings { settings: MetaSettings {
default_length_units: exec_settings.units.into(), default_length_units: Default::default(),
default_angle_units: Default::default(), default_angle_units: Default::default(),
}, },
} }
} }
} }
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq, ts_rs::TS, JsonSchema)]
#[ts(export)] #[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct MetaSettings { pub struct MetaSettings {

View File

@ -195,6 +195,10 @@ impl Program {
}) })
} }
pub fn is_empty_or_only_settings(&self) -> bool {
self.ast.is_empty_or_only_settings()
}
pub fn lint_all(&self) -> Result<Vec<lint::Discovered>, anyhow::Error> { pub fn lint_all(&self) -> Result<Vec<lint::Discovered>, anyhow::Error> {
self.ast.lint_all() self.ast.lint_all()
} }

View File

@ -812,56 +812,6 @@ impl Backend {
Ok(()) Ok(())
} }
pub async fn update_units(
&self,
params: custom_notifications::UpdateUnitsParams,
) -> RpcResult<Option<custom_notifications::UpdateUnitsResponse>> {
{
let mut ctx = self.executor_ctx.write().await;
// Borrow the executor context mutably.
let Some(ref mut executor_ctx) = *ctx else {
self.client
.log_message(MessageType::ERROR, "no executor context set to update units for")
.await;
return Ok(None);
};
self.client
.log_message(MessageType::INFO, format!("update units: {:?}", params))
.await;
if executor_ctx.settings.units == params.units
&& !self.has_diagnostics(params.text_document.uri.as_ref()).await
{
// Return early the units are the same.
return Ok(None);
}
// Set the engine units.
executor_ctx.update_units(params.units);
}
// Lock is dropped here since nested.
// This is IMPORTANT.
let new_params = TextDocumentItem {
uri: params.text_document.uri.clone(),
text: std::mem::take(&mut params.text.to_string()),
version: Default::default(),
language_id: Default::default(),
};
// Force re-execution.
self.inner_on_change(new_params, true).await;
// Check if we have diagnostics.
// If we do we return early, since we failed in some way.
if self.has_diagnostics(params.text_document.uri.as_ref()).await {
return Ok(None);
}
Ok(Some(custom_notifications::UpdateUnitsResponse {}))
}
pub async fn update_can_execute( pub async fn update_can_execute(
&self, &self,
params: custom_notifications::UpdateCanExecuteParams, params: custom_notifications::UpdateCanExecuteParams,

View File

@ -42,7 +42,6 @@ pub async fn kcl_lsp_server(execute: bool) -> Result<crate::lsp::kcl::Backend> {
can_execute: Arc::new(tokio::sync::RwLock::new(can_execute)), can_execute: Arc::new(tokio::sync::RwLock::new(can_execute)),
is_initialized: Default::default(), is_initialized: Default::default(),
}) })
.custom_method("kcl/updateUnits", crate::lsp::kcl::Backend::update_units)
.custom_method("kcl/updateCanExecute", crate::lsp::kcl::Backend::update_can_execute) .custom_method("kcl/updateCanExecute", crate::lsp::kcl::Backend::update_can_execute)
.finish(); .finish();

View File

@ -2324,80 +2324,6 @@ async fn kcl_test_kcl_lsp_on_change_update_memory() {
server.executor_ctx().await.clone().unwrap().close().await; server.executor_ctx().await.clone().unwrap().close().await;
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn kcl_test_kcl_lsp_update_units() {
let server = kcl_lsp_server(true).await.unwrap();
let same_text = r#"fn cube = (pos, scale) => {
sg = startSketchOn(XY)
|> startProfileAt(pos, %)
|> line(end = [0, scale])
|> line(end = [scale, 0])
|> line(end = [0, -scale])
return sg
}
part001 = cube([0,0], 20)
|> close()
|> extrude(length = 20)"#
.to_string();
// Send open file.
server
.did_open(tower_lsp::lsp_types::DidOpenTextDocumentParams {
text_document: tower_lsp::lsp_types::TextDocumentItem {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: same_text.clone(),
},
})
.await;
// Get the tokens.
let tokens = server.token_map.get("file:///test.kcl").unwrap().clone();
assert_eq!(tokens.as_slice().len(), 123);
// Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert_eq!(ast.ast.body.len(), 2);
// Send change file.
server
.did_change(tower_lsp::lsp_types::DidChangeTextDocumentParams {
text_document: tower_lsp::lsp_types::VersionedTextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
version: 1,
},
content_changes: vec![tower_lsp::lsp_types::TextDocumentContentChangeEvent {
range: None,
range_length: None,
text: same_text.clone(),
}],
})
.await;
let units = server.executor_ctx.read().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Update the units.
server
.update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
units: crate::settings::types::UnitLength::M,
text: same_text.clone(),
})
.await
.unwrap();
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::M);
server.executor_ctx().await.clone().unwrap().close().await;
}
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_kcl_lsp_empty_file_execute_ok() { async fn kcl_test_kcl_lsp_empty_file_execute_ok() {
let server = kcl_lsp_server(true).await.unwrap(); let server = kcl_lsp_server(true).await.unwrap();
@ -2733,145 +2659,6 @@ async fn kcl_test_kcl_lsp_code_and_ast_unchanged_but_has_diagnostics_reexecute()
server.executor_ctx().await.clone().unwrap().close().await; server.executor_ctx().await.clone().unwrap().close().await;
} }
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_kcl_lsp_code_and_ast_units_unchanged_but_has_diagnostics_reexecute_on_unit_change() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
|> close()
|> extrude(length = 3.14)"#;
// Send open file.
server
.did_open(tower_lsp::lsp_types::DidOpenTextDocumentParams {
text_document: tower_lsp::lsp_types::TextDocumentItem {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: code.to_string(),
},
})
.await;
// Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default());
// Assure we have no diagnostics.
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
// Add some fake diagnostics.
server.diagnostics_map.insert(
"file:///test.kcl".to_string(),
vec![tower_lsp::lsp_types::Diagnostic {
range: tower_lsp::lsp_types::Range {
start: tower_lsp::lsp_types::Position { line: 0, character: 0 },
end: tower_lsp::lsp_types::Position { line: 0, character: 0 },
},
message: "fake diagnostic".to_string(),
severity: Some(tower_lsp::lsp_types::DiagnosticSeverity::ERROR),
code: None,
source: None,
related_information: None,
tags: None,
data: None,
code_description: None,
}],
);
// Assure we have one diagnostics.
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 1);
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Update the units to the _same_ units.
server
.update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
units: crate::settings::types::UnitLength::Mm,
text: code.to_string(),
})
.await
.unwrap();
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default());
// Assure we have no diagnostics.
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
server.executor_ctx().await.clone().unwrap().close().await;
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_kcl_lsp_code_and_ast_units_unchanged_but_has_memory_reexecute_on_unit_change() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
|> close()
|> extrude(length = 3.14)"#;
// Send open file.
server
.did_open(tower_lsp::lsp_types::DidOpenTextDocumentParams {
text_document: tower_lsp::lsp_types::TextDocumentItem {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: code.to_string(),
},
})
.await;
// Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default());
// Assure we have no diagnostics.
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Update the units to the _same_ units.
server
.update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
units: crate::settings::types::UnitLength::Mm,
text: code.to_string(),
})
.await
.unwrap();
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default());
// Assure we have no diagnostics.
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
server.executor_ctx().await.clone().unwrap().close().await;
}
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_kcl_lsp_cant_execute_set() { async fn kcl_test_kcl_lsp_cant_execute_set() {
let server = kcl_lsp_server(true).await.unwrap(); let server = kcl_lsp_server(true).await.unwrap();
@ -2903,23 +2690,6 @@ async fn kcl_test_kcl_lsp_cant_execute_set() {
// Assure we have no diagnostics. // Assure we have no diagnostics.
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0); assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
// Update the units to the _same_ units.
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
server
.update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
units: crate::settings::types::UnitLength::Mm,
text: code.to_string(),
})
.await
.unwrap();
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Get the ast. // Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone(); let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default()); assert!(ast.ast != Node::<Program>::default());
@ -2936,23 +2706,6 @@ async fn kcl_test_kcl_lsp_cant_execute_set() {
.unwrap(); .unwrap();
assert_eq!(server.can_execute().await, false); assert_eq!(server.can_execute().await, false);
// Update the units to the _same_ units.
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
server
.update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
units: crate::settings::types::UnitLength::Mm,
text: code.to_string(),
})
.await
.unwrap();
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
let mut default_hashed = Node::<Program>::default(); let mut default_hashed = Node::<Program>::default();
default_hashed.compute_digest(); default_hashed.compute_digest();
@ -2970,23 +2723,6 @@ async fn kcl_test_kcl_lsp_cant_execute_set() {
.unwrap(); .unwrap();
assert_eq!(server.can_execute().await, true); assert_eq!(server.can_execute().await, true);
// Update the units to the _same_ units.
let units = server.executor_ctx.read().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
server
.update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
units: crate::settings::types::UnitLength::Mm,
text: code.to_string(),
})
.await
.unwrap();
let units = server.executor_ctx.read().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Get the ast. // Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone(); let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default()); assert!(ast.ast != Node::<Program>::default());

View File

@ -369,6 +369,26 @@ impl Node<Program> {
Ok(new_program) Ok(new_program)
} }
/// Returns true if the given KCL is empty or only contains settings that
/// would be auto-generated.
pub fn is_empty_or_only_settings(&self) -> bool {
if !self.body.is_empty() {
return false;
}
if self.non_code_meta.start_nodes.iter().any(|node| node.is_comment()) {
return false;
}
for item in &self.inner_attrs {
if item.name() != Some(annotations::SETTINGS) {
return false;
}
}
true
}
} }
impl Program { impl Program {
@ -3564,6 +3584,37 @@ mod tests {
use super::*; use super::*;
#[track_caller]
fn parse(code: &str) -> Node<Program> {
crate::parsing::top_level_parse(code).unwrap()
}
#[test]
fn test_empty_or_only_settings() {
// Empty is empty.
assert!(parse("").is_empty_or_only_settings());
// Whitespace is empty.
assert!(parse(" ").is_empty_or_only_settings());
// Settings are empty.
assert!(parse(r#"@settings(defaultLengthUnit = mm)"#).is_empty_or_only_settings());
// Only comments is not empty.
assert!(!parse("// comment").is_empty_or_only_settings());
// Any statement is not empty.
assert!(!parse("5").is_empty_or_only_settings());
// Any statement is not empty, even with settings.
let code = r#"@settings(defaultLengthUnit = mm)
5"#;
assert!(!parse(code).is_empty_or_only_settings());
// Non-settings attributes are not empty.
assert!(!parse("@foo").is_empty_or_only_settings());
}
// We have this as a test so we can ensure it never panics with an unwrap in the server. // We have this as a test so we can ensure it never panics with an unwrap in the server.
#[test] #[test]
fn test_variable_kind_to_completion() { fn test_variable_kind_to_completion() {

View File

@ -155,13 +155,9 @@ async fn execute_test(test: &Test, render_to_png: bool, export_step: bool) {
let ast = crate::Program::parse_no_errs(&input).unwrap(); let ast = crate::Program::parse_no_errs(&input).unwrap();
// Run the program. // Run the program.
let exec_res = crate::test_server::execute_and_snapshot_ast( let exec_res =
ast, crate::test_server::execute_and_snapshot_ast(ast, Some(test.input_dir.join(&test.entry_point)), export_step)
crate::settings::types::UnitLength::Mm, .await;
Some(test.input_dir.join(&test.entry_point)),
export_step,
)
.await;
match exec_res { match exec_res {
Ok((exec_state, env_ref, png, step)) => { Ok((exec_state, env_ref, png, step)) => {
let fail_path = test.output_dir.join("execution_error.snap"); let fail_path = test.output_dir.join("execution_error.snap");

View File

@ -1,7 +1,7 @@
//! Run all the KCL samples in the `kcl_samples` directory. //! Run all the KCL samples in the `kcl_samples` directory.
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::{ use std::{
fs, fs,
panic::{catch_unwind, AssertUnwindSafe},
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };

View File

@ -165,7 +165,7 @@ async fn inner_fillet(
edge_id, edge_id,
object_id: solid.id, object_id: solid.id,
radius: LengthUnit(radius), radius: LengthUnit(radius),
tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))), tolerance: LengthUnit(tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into()))),
cut_type: CutType::Fillet, cut_type: CutType::Fillet,
// We make this a none so that we can remove it in the future. // We make this a none so that we can remove it in the future.
face_id: None, face_id: None,

View File

@ -159,7 +159,7 @@ async fn inner_loft(
section_ids: sketches.iter().map(|group| group.id).collect(), section_ids: sketches.iter().map(|group| group.id).collect(),
base_curve_index, base_curve_index,
bez_approximate_rational, bez_approximate_rational,
tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))), tolerance: LengthUnit(tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into()))),
v_degree, v_degree,
}), }),
) )

View File

@ -273,7 +273,9 @@ async fn inner_revolve(
target: sketch.id.into(), target: sketch.id.into(),
axis, axis,
origin, origin,
tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))), tolerance: LengthUnit(
tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into())),
),
axis_is_2d: true, axis_is_2d: true,
}), }),
) )
@ -287,7 +289,9 @@ async fn inner_revolve(
angle, angle,
target: sketch.id.into(), target: sketch.id.into(),
edge_id, edge_id,
tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))), tolerance: LengthUnit(
tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into())),
),
}), }),
) )
.await?; .await?;

View File

@ -191,7 +191,7 @@ async fn inner_sweep(
target: sketch.id.into(), target: sketch.id.into(),
trajectory, trajectory,
sectional: sectional.unwrap_or(false), sectional: sectional.unwrap_or(false),
tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))), tolerance: LengthUnit(tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into()))),
}), }),
) )
.await?; .await?;

View File

@ -6,7 +6,6 @@ use crate::{
engine::new_zoo_client, engine::new_zoo_client,
errors::ExecErrorWithState, errors::ExecErrorWithState,
execution::{EnvironmentRef, ExecState, ExecutorContext, ExecutorSettings}, execution::{EnvironmentRef, ExecState, ExecutorContext, ExecutorSettings},
settings::types::UnitLength,
ConnectionError, ExecError, KclError, KclErrorWithOutputs, Program, ConnectionError, ExecError, KclError, KclErrorWithOutputs, Program,
}; };
@ -19,12 +18,8 @@ pub struct RequestBody {
/// Executes a kcl program and takes a snapshot of the result. /// Executes a kcl program and takes a snapshot of the result.
/// This returns the bytes of the snapshot. /// This returns the bytes of the snapshot.
pub async fn execute_and_snapshot( pub async fn execute_and_snapshot(code: &str, current_file: Option<PathBuf>) -> Result<image::DynamicImage, ExecError> {
code: &str, let ctx = new_context(true, current_file).await?;
units: UnitLength,
current_file: Option<PathBuf>,
) -> Result<image::DynamicImage, ExecError> {
let ctx = new_context(units, true, current_file).await?;
let program = Program::parse_no_errs(code).map_err(KclErrorWithOutputs::no_outputs)?; let program = Program::parse_no_errs(code).map_err(KclErrorWithOutputs::no_outputs)?;
let res = do_execute_and_snapshot(&ctx, program) let res = do_execute_and_snapshot(&ctx, program)
.await .await
@ -38,11 +33,10 @@ pub async fn execute_and_snapshot(
/// This returns the bytes of the snapshot. /// This returns the bytes of the snapshot.
pub async fn execute_and_snapshot_ast( pub async fn execute_and_snapshot_ast(
ast: Program, ast: Program,
units: UnitLength,
current_file: Option<PathBuf>, current_file: Option<PathBuf>,
with_export_step: bool, with_export_step: bool,
) -> Result<(ExecState, EnvironmentRef, image::DynamicImage, Option<Vec<u8>>), ExecErrorWithState> { ) -> Result<(ExecState, EnvironmentRef, image::DynamicImage, Option<Vec<u8>>), ExecErrorWithState> {
let ctx = new_context(units, true, current_file).await?; let ctx = new_context(true, current_file).await?;
let (exec_state, env, img) = do_execute_and_snapshot(&ctx, ast).await?; let (exec_state, env, img) = do_execute_and_snapshot(&ctx, ast).await?;
let mut step = None; let mut step = None;
if with_export_step { if with_export_step {
@ -64,10 +58,9 @@ pub async fn execute_and_snapshot_ast(
pub async fn execute_and_snapshot_no_auth( pub async fn execute_and_snapshot_no_auth(
code: &str, code: &str,
units: UnitLength,
current_file: Option<PathBuf>, current_file: Option<PathBuf>,
) -> Result<(image::DynamicImage, EnvironmentRef), ExecError> { ) -> Result<(image::DynamicImage, EnvironmentRef), ExecError> {
let ctx = new_context(units, false, current_file).await?; let ctx = new_context(false, current_file).await?;
let program = Program::parse_no_errs(code).map_err(KclErrorWithOutputs::no_outputs)?; let program = Program::parse_no_errs(code).map_err(KclErrorWithOutputs::no_outputs)?;
let res = do_execute_and_snapshot(&ctx, program) let res = do_execute_and_snapshot(&ctx, program)
.await .await
@ -111,11 +104,7 @@ async fn do_execute_and_snapshot(
Ok((exec_state, result.0, img)) Ok((exec_state, result.0, img))
} }
pub async fn new_context( pub async fn new_context(with_auth: bool, current_file: Option<PathBuf>) -> Result<ExecutorContext, ConnectionError> {
units: UnitLength,
with_auth: bool,
current_file: Option<PathBuf>,
) -> Result<ExecutorContext, ConnectionError> {
let mut client = new_zoo_client(if with_auth { None } else { Some("bad_token".to_string()) }, None) let mut client = new_zoo_client(if with_auth { None } else { Some("bad_token".to_string()) }, None)
.map_err(ConnectionError::CouldNotMakeClient)?; .map_err(ConnectionError::CouldNotMakeClient)?;
if !with_auth { if !with_auth {
@ -126,7 +115,6 @@ pub async fn new_context(
} }
let mut settings = ExecutorSettings { let mut settings = ExecutorSettings {
units,
highlight_edges: true, highlight_edges: true,
enable_ssao: false, enable_ssao: false,
show_grid: false, show_grid: false,
@ -145,7 +133,6 @@ pub async fn new_context(
pub async fn execute_and_export_step( pub async fn execute_and_export_step(
code: &str, code: &str,
units: UnitLength,
current_file: Option<PathBuf>, current_file: Option<PathBuf>,
) -> Result< ) -> Result<
( (
@ -155,7 +142,7 @@ pub async fn execute_and_export_step(
), ),
ExecErrorWithState, ExecErrorWithState,
> { > {
let ctx = new_context(units, true, current_file).await?; let ctx = new_context(true, current_file).await?;
let mut exec_state = ExecState::new(&ctx); let mut exec_state = ExecState::new(&ctx);
let program = Program::parse_no_errs(code) let program = Program::parse_no_errs(code)
.map_err(|err| ExecErrorWithState::new(KclErrorWithOutputs::no_outputs(err).into(), exec_state.clone()))?; .map_err(|err| ExecErrorWithState::new(KclErrorWithOutputs::no_outputs(err).into(), exec_state.clone()))?;

View File

@ -11,14 +11,6 @@ description: Artifact commands add_lots.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands angled_line.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands argument_error.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands array_elem_pop.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands array_elem_pop_empty_fail.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands array_elem_pop_fail.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands array_elem_push.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands array_elem_push_fail.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands array_index_oob.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands array_range_expr.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands array_range_negative_expr.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands artifact_graph_example_code1.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands artifact_graph_example_code_no_3d.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands artifact_graph_example_code_offset_planes.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands assembly_mixed_units_cubes.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands assembly_non_default_units.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands bad_units_in_annotation.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands basic_fillet_cube_close_opposite.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands basic_fillet_cube_end.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands basic_fillet_cube_next_adjacent.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -11,14 +11,6 @@ description: Artifact commands basic_fillet_cube_previous_adjacent.kcl
"hidden": false "hidden": false
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

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