Compare commits

..

54 Commits

Author SHA1 Message Date
2204575466 Fix to not blow away files with comments 2025-03-21 16:54:19 -04:00
65f9bcc4ea Fix so that only comments doesn't format to empty 2025-03-21 16:54:19 -04:00
ced2072768 A snapshot a day keeps the bugs away! 📷🐛 2025-03-21 20:40:04 +00:00
5e1fbccaec A snapshot a day keeps the bugs away! 📷🐛 2025-03-21 20:25:24 +00:00
658700b533 A snapshot a day keeps the bugs away! 📷🐛 2025-03-21 20:01:12 +00:00
670d95e692 Merge branch 'main' into jtran/units-indicator 2025-03-21 15:46:42 -04:00
744bb254e9 Fix yarn lint 2025-03-21 12:59:13 -04:00
b9a61c83d6 Possibly the last test that needs updated with an inline unit annotation 2025-03-21 12:41:11 -04:00
b5c25fe9e7 More test updates to use inline in setting 2025-03-21 12:32:45 -04:00
a3b6da03d3 Undo kclSamplesInputPath approach.
Instead, just add a second reliable executor input file to use.
2025-03-21 12:13:19 -04:00
e6c060c410 A snapshot a day keeps the bugs away! 📷🐛 2025-03-21 16:00:35 +00:00
09dabd8fc2 I'm pretty sure our lighting is very affected by scale 2025-03-21 11:46:26 -04:00
dfac82d2aa Merge branch 'main' into jtran/units-indicator 2025-03-21 11:42:58 -04:00
cb32881cf2 Fix up more tests with setting annotations 2025-03-21 11:42:42 -04:00
a01498bf33 A snapshot a day keeps the bugs away! 📷🐛 2025-03-21 15:15:40 +00:00
d1d3caad5c A snapshot a day keeps the bugs away! 📷🐛 2025-03-21 15:02:02 +00:00
c62e0bfd64 Fix up point-and-click tests with unit setting lines 2025-03-21 10:48:01 -04:00
256b6b33f3 A snapshot a day keeps the bugs away! 📷🐛 2025-03-21 14:37:22 +00:00
35c80a78bb Merge branch 'main' into jtran/units-indicator 2025-03-21 10:23:42 -04:00
a5e682f9b0 Fix to reset to the default units when clearing the scene 2025-03-20 19:16:15 -04:00
c1319ca980 Add cache test 2025-03-20 19:16:15 -04:00
6e8fcdc088 A snapshot a day keeps the bugs away! 📷🐛 2025-03-20 22:52:01 +00:00
273b3b59e2 Merge branch 'main' into jtran/units-indicator 2025-03-20 18:38:37 -04:00
bac7ae4ff1 A snapshot a day keeps the bugs away! 📷🐛 2025-03-20 22:03:24 +00:00
9f5c2512a7 A snapshot a day keeps the bugs away! 📷🐛 2025-03-20 21:48:58 +00:00
485c5ab455 Fix chamfer e2e tests 2025-03-20 17:34:30 -04:00
d0cba2f080 Update output after new keyboard sample 2025-03-20 17:34:30 -04:00
7f1ed3b7cc A snapshot a day keeps the bugs away! 📷🐛 2025-03-20 17:34:30 -04:00
9e73987796 A snapshot a day keeps the bugs away! 📷🐛 2025-03-20 17:34:30 -04:00
01e1589cd6 A snapshot a day keeps the bugs away! 📷🐛 2025-03-20 17:34:30 -04:00
4b1901db7e A snapshot a day keeps the bugs away! 📷🐛 2025-03-20 17:34:30 -04:00
a892699b65 A snapshot a day keeps the bugs away! 📷🐛 2025-03-20 17:34:30 -04:00
76dbb4a5d3 A snapshot a day keeps the bugs away! 📷🐛 2025-03-20 17:34:30 -04:00
d6cb471791 A snapshot a day keeps the bugs away! 📷🐛 2025-03-20 17:34:29 -04:00
ac4d68a812 Fix snapshot test to use mask 2025-03-20 17:34:12 -04:00
423ab5169f Add new assertion when creating project 2025-03-20 17:34:12 -04:00
6f013ec5fe Revert "Add arrow down to try to fix tests"
This reverts commit cde90b0e058e9fd4d4b68087c971195d3843d104.
2025-03-20 17:34:12 -04:00
8c3fc51d28 Change signature to reduce wasm round-trips 2025-03-20 17:34:12 -04:00
cffb777a7b Fix lint 2025-03-20 17:34:12 -04:00
0409b3159c Fix to consider only @settings to not be worth preserving 2025-03-20 17:34:12 -04:00
27c2c50508 Fix more tests 2025-03-20 17:34:12 -04:00
8f5eb9266b Fix formatting 2025-03-20 17:34:12 -04:00
041000fbb6 Trying to fix test assertions 2025-03-20 17:34:12 -04:00
15c3f21acc Add arrow down to try to fix tests 2025-03-20 17:34:12 -04:00
626dbf46f8 Fix tests 2025-03-20 17:34:12 -04:00
dc3a17149d Regenerate derive-docs 2025-03-20 17:34:11 -04:00
98238d040b Update output after setting units differently 2025-03-20 17:34:11 -04:00
3dff5b1c30 Remove units from settings struct 2025-03-20 17:34:11 -04:00
2f362e1774 Change tolerance to use the module units 2025-03-20 17:34:11 -04:00
fd45574652 Fix loading samples 2025-03-20 17:34:11 -04:00
1e23f37287 Change so that the new file in new projects get the units 2025-03-20 17:34:11 -04:00
8936a885c3 Move definition so that all units stuff is together and no cyclic imports 2025-03-20 17:34:09 -04:00
e94bdeb2ce Change so that new KCL files respect the length unit setting 2025-03-20 17:33:37 -04:00
494d8bdf4c Change lower-right controls units menu to be tied to only the per-file units 2025-03-20 17:33:36 -04:00
264 changed files with 3051 additions and 2763 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -74,6 +74,7 @@ layout: manual
* [`getOppositeEdge`](kcl/getOppositeEdge)
* [`getPreviousAdjacentEdge`](kcl/getPreviousAdjacentEdge)
* [`helix`](kcl/helix)
* [`helixRevolutions`](kcl/helixRevolutions)
* [`hole`](kcl/hole)
* [`hollow`](kcl/hollow)
* [`inch`](kcl/inch)

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,6 @@ A helix.
| `revolutions` |[`number`](/docs/kcl/types/number)| Number of revolutions. | No |
| `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No |
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
| `cylinderId` |[`string`](/docs/kcl/types/string)| The cylinder the helix was created on. | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |

View File

@ -85,7 +85,7 @@ async function doBasicSketch(
await page.mouse.click(startXPx, 500 - PUR * 20)
if (openPanes.includes('code')) {
await expect(u.codeLocator)
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn('XZ')profile001 = startProfileAt(${
commonPoints.startAt
}, sketch001)
|> xLine(length = ${commonPoints.num1})
@ -145,7 +145,7 @@ async function doBasicSketch(
// Open the code pane.
await u.openKclCodePanel()
await expect(u.codeLocator)
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn('XZ')profile001 = startProfileAt(${
commonPoints.startAt
}, sketch001)
|> 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()

View File

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

View File

@ -20,11 +20,11 @@ test(
await Promise.all([fsp.mkdir(bracketDir, { recursive: true })])
await Promise.all([
fsp.copyFile(
executorInputPath('router-template-slate.kcl'),
executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'other.kcl')
),
fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
path.join(bracketDir, 'main.kcl')
),
])
@ -107,7 +107,7 @@ test(
},
{ timeout: 15_000 }
)
.toBeGreaterThan(300_000)
.toBeGreaterThan(30_000)
})
})
@ -187,7 +187,7 @@ test(
},
{ 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.up('ControlOrMeta')
await expect(page.locator('.cm-content'))
.toHaveText(`sketch001 = startSketchOn(XY)
await expect(page.locator('.cm-content')).toHaveText(
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn('XY')
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
// |> close()`)
// |> close()`.replaceAll('\n', '')
)
// uncomment the code
await page.keyboard.down('ControlOrMeta')
await page.keyboard.press('/')
await page.keyboard.up('ControlOrMeta')
await expect(page.locator('.cm-content'))
.toHaveText(`sketch001 = startSketchOn(XY)
await expect(page.locator('.cm-content')).toHaveText(
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn('XY')
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
|> close()`)
|> close()`.replaceAll('\n', '')
)
})
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('button:has-text("Format code")').click()
await expect(page.locator('.cm-content'))
.toHaveText(`sketch001 = startSketchOn(XY)
await expect(page.locator('.cm-content')).toHaveText(
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn('XY')
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
|> 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 ({
@ -227,13 +233,15 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
await expect(page.locator('.cm-content'))
.toHaveText(`sketch_001 = startSketchOn(XY)
await expect(page.locator('.cm-content')).toHaveText(
`@settings(defaultLengthUnit = in)
sketch_001 = startSketchOn('XY')
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
|> close()`)
|> close()`.replaceAll('\n', '')
)
// error in guter
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
await expect(page.locator('.cm-completionLabel')).not.toBeVisible()
await expect(page.locator('.cm-content'))
.toHaveText(`sketch001 = startSketchOn(XZ)
await expect(page.locator('.cm-content')).toHaveText(
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn('XZ')
|> startProfileAt([3.14, 12], %)
|> xLine(%, length = 5) // lin`)
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
)
// expect there to be no KCL errors
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
await expect(page.locator('.cm-completionLabel')).not.toBeVisible()
await expect(page.locator('.cm-content'))
.toHaveText(`sketch001 = startSketchOn(XZ)
await expect(page.locator('.cm-content')).toHaveText(
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn('XZ')
|> 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 ({

View File

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

View File

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

View File

@ -137,7 +137,7 @@ test.describe('Point-and-click tests', () => {
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 () => {
// sometimes initial click doesn't register
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 editor.expectState({
activeLines: ['sketch001 = startSketchOn(XZ)'],
activeLines: ['@settings(defaultLengthUnit = in)'],
highlightedCode: '',
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 editor.expectEditor.toContain(
`sketch001 = startSketchOn(XZ)
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> 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,
page,
homePage,
@ -418,7 +419,8 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
|>close()`,
})
await editor.expectEditor.toContain(
`sketch001 = startSketchOn(XZ)
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %)
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([
@ -1340,7 +1342,8 @@ loft001 = loft([sketch001, sketch002])
{
targetType: 'circle',
testPoint: { x: 700, y: 250 },
initialCode: `sketch001 = startSketchOn('YZ')
initialCode: `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn('YZ')
profile001 = circle(sketch001, center = [0, 0], radius = 500)
sketch002 = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
@ -1350,7 +1353,8 @@ sketch002 = startSketchOn('XZ')
{
targetType: 'rectangle',
testPoint: { x: 710, y: 255 },
initialCode: `sketch001 = startSketchOn('YZ')
initialCode: `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn('YZ')
profile001 = startProfileAt([-400, -400], sketch001)
|> angledLine([0, 800], %, $rectangleSegmentA001)
|> angledLine([
@ -1507,7 +1511,8 @@ sketch002 = startSketchOn('XZ')
toolbar,
cmdBar,
}) => {
const initialCode = `sketch001 = startSketchOn(YZ)
const initialCode = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(YZ)
|> circle(
center = [0, 0],
radius = 500
@ -2074,7 +2079,8 @@ extrude001 = extrude(profile001, length = 5)
cmdBar,
}) => {
// Code samples
const initialCode = `sketch001 = startSketchOn(XY)
const initialCode = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XY)
|> startProfileAt([-12, -6], %)
|> line(end = [0, 12])
|> line(end = [24, 0])
@ -2298,7 +2304,8 @@ extrude001 = extrude(sketch001, length = -12)
toolbar,
}) => {
// Code samples
const initialCode = `sketch001 = startSketchOn(XY)
const initialCode = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XY)
|> startProfileAt([-12, -6], %)
|> line(end = [0, 12])
|> line(end = [24, 0], tag = $seg02)
@ -2452,7 +2459,8 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
toolbar,
cmdBar,
}) => {
const initialCode = `sketch001 = startSketchOn(XZ)
const initialCode = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 30)
extrude001 = extrude(sketch001, length = 30)
`
@ -2587,7 +2595,8 @@ extrude001 = extrude(sketch001, length = 30)
toolbar,
cmdBar,
}) => {
const initialCode = `sketch001 = startSketchOn(XY)
const initialCode = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XY)
|> startProfileAt([-20, 20], %)
|> xLine(length = 40)
|> yLine(length = -60)
@ -2705,7 +2714,8 @@ extrude001 = extrude(sketch001, length = 40)
})
const shellSketchOnFacesCases = [
`sketch001 = startSketchOn(XZ)
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 100)
|> extrude(length = 100)
@ -2713,7 +2723,8 @@ sketch002 = startSketchOn(sketch001, 'END')
|> circle(center = [0, 0], radius = 50)
|> extrude(length = 50)
`,
`sketch001 = startSketchOn(XZ)
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 100)
extrude001 = extrude(sketch001, length = 100)
@ -3109,7 +3120,8 @@ radius = 8.69
toolbar,
cmdBar,
}) => {
const initialCode = `sketch001 = startSketchOn(XZ)
const initialCode = `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
profile001 = circle(
sketch001,
center = [0, 0],

View File

@ -86,7 +86,7 @@ test(
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl')
)
})
@ -123,7 +123,7 @@ test(
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl')
)
const errorDir = path.join(dir, 'broken-code')
@ -212,7 +212,7 @@ test(
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl')
)
const emptyDir = path.join(dir, 'empty')
@ -289,7 +289,7 @@ test(
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl')
)
@ -355,7 +355,7 @@ test(
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl')
)
await fsp.copyFile(
@ -474,7 +474,7 @@ test.describe('Can export from electron app', () => {
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl')
)
})
@ -1497,7 +1497,12 @@ test(
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], %)
|> line(end = [324.07, 27.199], tag = $seg01)
|> line(end = [118.328, -291.754])

View File

@ -4,9 +4,9 @@ import path from 'path'
import * as fsp from 'fs/promises'
import {
getUtils,
executorInputPath,
TEST_COLORS,
TestColor,
executorInputPath,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from './storageStates'
@ -582,7 +582,7 @@ extrude002 = extrude(profile002, length = 150)
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl')
)
})
@ -632,12 +632,13 @@ extrude002 = extrude(profile002, length = 150)
await test.step(`Load an empty file`, async () => {
await page.addInitScript(async () => {
localStorage.setItem('persistCode', '')
localStorage.setItem('persistCode', '@settings(defaultLengthUnit = in)')
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await u.closeKclCodePanel()
await page.waitForTimeout(20)
})
await test.step(`Zoom out until you can't see the default planes`, async () => {
@ -646,13 +647,14 @@ extrude002 = extrude(profile002, length = 150)
timeout: 5000,
message: 'Plane color is visible',
})
.toBeLessThanOrEqual(15)
.toBeLessThanOrEqual(20)
let maxZoomOuts = 10
let middlePixelIsBackgroundColor =
(await middlePixelIsColor(bgColor)) < 10
while (!middlePixelIsBackgroundColor && maxZoomOuts > 0) {
await page.keyboard.down('Control')
await page.waitForTimeout(20)
await page.mouse.move(600, 460)
await page.mouse.down({ button: 'right' })
await page.mouse.move(600, 50, { steps: 20 })
@ -660,7 +662,7 @@ extrude002 = extrude(profile002, length = 150)
await page.keyboard.up('Control')
await page.waitForTimeout(100)
maxZoomOuts--
middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 10
middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 15
}
expect(middlePixelIsBackgroundColor, {
@ -678,13 +680,12 @@ extrude002 = extrude(profile002, length = 150)
homePage,
scene,
toolbar,
viewport,
}) => {
await context.folderSetupFn(async (dir) => {
const legoDir = path.join(dir, 'lego')
await fsp.mkdir(legoDir, { recursive: true })
await fsp.copyFile(
executorInputPath('lego.kcl'),
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
path.join(legoDir, 'main.kcl')
)
})
@ -697,11 +698,8 @@ extrude002 = extrude(profile002, length = 150)
await scene.loadingIndicator.waitFor({ state: 'detached' })
})
await test.step(`The part should start loading quickly, not waiting until execution is complete`, async () => {
await scene.expectPixelColor(
[143, 143, 143],
{ x: (viewport?.width ?? 1200) / 2, y: (viewport?.height ?? 500) / 2 },
15
)
// TODO: use the viewport size to pick the center point, but the `viewport` fixutre's values were wrong.
await scene.expectPixelColor([143, 143, 143], { x: 500, y: 250 }, 15)
})
})

View File

@ -113,7 +113,8 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn(XZ)
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([2.61, -4.01], %)
|> xLine(length = 8.73)
|> tangentialArcTo([8.33, -1.31], %)`
@ -159,7 +160,10 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
await page.mouse.click(700, 200)
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)
|> yLine(length = 12.34)
@ -789,7 +793,8 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
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 expect(u.codeLocator).toHaveText(codeStr)
@ -1426,7 +1431,8 @@ test.describe(`Sketching with offset planes`, () => {
await context.addInitScript(() => {
localStorage.setItem(
'persistCode',
`offsetPlane001 = offsetPlane(XY, offset = 10)`
`@settings(defaultLengthUnit = in)
offsetPlane001 = offsetPlane(XY, offset = 10)`
)
})
@ -1440,7 +1446,7 @@ test.describe(`Sketching with offset planes`, () => {
await test.step(`Hovering should highlight code`, async () => {
await planeHover()
await editor.expectState({
activeLines: [`offsetPlane001=offsetPlane(XY,offset=10)`],
activeLines: [`@settings(defaultLengthUnit = in)`],
diagnostics: [],
highlightedCode: 'offsetPlane(XY, offset = 10)',
})
@ -1453,7 +1459,7 @@ test.describe(`Sketching with offset planes`, () => {
await expect(toolbar.lineBtn).toBeEnabled()
await editor.expectEditor.toContain('startSketchOn(offsetPlane001)')
await editor.expectState({
activeLines: [`offsetPlane001=offsetPlane(XY,offset=10)`],
activeLines: [`@settings(defaultLengthUnit = in)`],
diagnostics: [],
highlightedCode: '',
})
@ -2486,7 +2492,11 @@ extrude001 = extrude(profile003, length = 5)
page,
}) => {
await page.addInitScript(async () => {
localStorage.setItem('persistCode', `myVar = 5`)
localStorage.setItem(
'persistCode',
`@settings(defaultLengthUnit = in)
myVar = 5`
)
})
await page.setBodyDimensions({ width: 1000, height: 500 })

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 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: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 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: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 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: 74 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

@ -56,7 +56,7 @@ export const editorSelector = '[role="textbox"][data-language="kcl"]'
type PaneId = 'variables' | 'code' | 'files' | 'logs'
export function orRunWhenFullSuiteEnabled() {
return process.env.GITHUB_REF !== 'all-e2e'
return process.env.GITHUB_HEAD_REF !== 'all-e2e'
}
async function waitForPageLoadWithRetry(page: Page) {

View File

@ -4,7 +4,6 @@ import {
getUtils,
TEST_COLORS,
pollEditorLinesSelectedLength,
executorInputPath,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { XOR } from 'lib/utils'
@ -1117,9 +1116,19 @@ test.describe('Electron constraint tests', () => {
await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'test-sample')
await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile(
executorInputPath('angled_line.kcl'),
path.join(bracketDir, 'main.kcl')
await fsp.writeFile(
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(() => {
localStorage.setItem(
'persistCode',
`
`@settings(defaultLengthUnit = in)
const sketch002 = startSketchOn(XZ)
|> startProfileAt([-108.83, -57.48], %)
|> angledLine([0, 105.13], %, $rectangleSegmentA001)

View File

@ -271,7 +271,7 @@ test.describe('Testing settings', () => {
const bracketDir = join(dir, projectName)
await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
executorInputPath('cylinder-inches.kcl'),
join(bracketDir, 'main.kcl')
)
}
@ -746,7 +746,6 @@ test.describe('Testing settings', () => {
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
await scene.settled(cmdBar)
await page.waitForTimeout(1000)
@ -951,9 +950,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 expect(unitsIndicator).toHaveText('Current units are: in')
await expect(unitsIndicator).toHaveText('Current units are: mm')
})
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 () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn(XZ)
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([3.29, 7.86], %)
|> line(end = [2.48, 2.44])
|> line(end = [2.66, 1.17])

20
rust/Cargo.lock generated
View File

@ -1780,7 +1780,7 @@ dependencies = [
[[package]]
name = "kcl-bumper"
version = "0.1.53"
version = "0.1.52"
dependencies = [
"anyhow",
"clap",
@ -1791,7 +1791,7 @@ dependencies = [
[[package]]
name = "kcl-derive-docs"
version = "0.1.53"
version = "0.1.52"
dependencies = [
"Inflector",
"anyhow",
@ -1810,7 +1810,7 @@ dependencies = [
[[package]]
name = "kcl-directory-test-macro"
version = "0.1.53"
version = "0.1.52"
dependencies = [
"proc-macro2",
"quote",
@ -1819,7 +1819,7 @@ dependencies = [
[[package]]
name = "kcl-language-server"
version = "0.2.53"
version = "0.2.52"
dependencies = [
"anyhow",
"clap",
@ -1840,7 +1840,7 @@ dependencies = [
[[package]]
name = "kcl-language-server-release"
version = "0.1.53"
version = "0.1.52"
dependencies = [
"anyhow",
"clap",
@ -1860,7 +1860,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.2.53"
version = "0.2.52"
dependencies = [
"anyhow",
"approx 0.5.1",
@ -1928,7 +1928,7 @@ dependencies = [
[[package]]
name = "kcl-python-bindings"
version = "0.3.53"
version = "0.3.52"
dependencies = [
"anyhow",
"kcl-lib",
@ -1943,7 +1943,7 @@ dependencies = [
[[package]]
name = "kcl-test-server"
version = "0.1.53"
version = "0.1.52"
dependencies = [
"anyhow",
"hyper 0.14.32",
@ -1956,7 +1956,7 @@ dependencies = [
[[package]]
name = "kcl-to-core"
version = "0.1.53"
version = "0.1.52"
dependencies = [
"anyhow",
"async-trait",
@ -1970,7 +1970,7 @@ dependencies = [
[[package]]
name = "kcl-wasm-lib"
version = "0.1.53"
version = "0.1.52"
dependencies = [
"bson",
"console_error_panic_hook",

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-bumper"
version = "0.1.53"
version = "0.1.52"
edition = "2021"
repository = "https://github.com/KittyCAD/modeling-api"
rust-version = "1.76"

View File

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

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<()> {
let code = #code_block;
// 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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -31,13 +31,7 @@ mod test_examples_someFn {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_someFn0() -> miette::Result<()> {
let code = "someFn()";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -31,13 +31,7 @@ mod test_examples_someFn {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_someFn0() -> miette::Result<()> {
let code = "someFn()";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_show {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_show0() -> miette::Result<()> {
let code = "This is another code block.\nyes sirrr.\nshow";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_show {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_show0() -> miette::Result<()> {
let code = "This is code.\nIt does other shit.\nshow";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -33,13 +33,7 @@ mod test_examples_my_func {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_my_func0() -> miette::Result<()> {
let code = "This is another code block.\nyes sirrr.\nmyFunc";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -33,13 +33,7 @@ mod test_examples_line_to {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_line_to0() -> miette::Result<()> {
let code = "This is another code block.\nyes sirrr.\nlineTo";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_min {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_min0() -> miette::Result<()> {
let code = "This is another code block.\nyes sirrr.\nmin";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_show {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_show0() -> miette::Result<()> {
let code = "This is code.\nIt does other shit.\nshow";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_import {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_import0() -> miette::Result<()> {
let code = "This is code.\nIt does other shit.\nimport";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_import {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_import0() -> miette::Result<()> {
let code = "This is code.\nIt does other shit.\nimport";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_import {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_import0() -> miette::Result<()> {
let code = "This is code.\nIt does other shit.\nimport";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -32,13 +32,7 @@ mod test_examples_show {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_show0() -> miette::Result<()> {
let code = "This is code.\nIt does other shit.\nshow";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -31,13 +31,7 @@ mod test_examples_some_function {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn kcl_test_example_some_function0() -> miette::Result<()> {
let code = "someFunction()";
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)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-directory-test-macro"
description = "A tool for generating tests from a directory of kcl files"
version = "0.1.53"
version = "0.1.52"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -1,6 +1,6 @@
[package]
name = "kcl-language-server-release"
version = "0.1.53"
version = "0.1.52"
edition = "2021"
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
publish = false

View File

@ -2,7 +2,7 @@
name = "kcl-language-server"
description = "A language server for KCL."
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
version = "0.2.53"
version = "0.2.52"
edition = "2021"
license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-lib"
description = "KittyCAD Language implementation and tools"
version = "0.2.53"
version = "0.2.52"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -76,7 +76,7 @@ fn run_benchmarks(c: &mut Criterion) {
group.bench_function(format!("execute_{}", dir_name), |b| {
b.iter(|| {
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);
ctx.run(black_box(&program), &mut exec_state).await?;
ctx.close().await;

View File

@ -49,45 +49,6 @@ async fn cache_test(
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")]
async fn kcl_test_cache_change_grid_visualizes_grid_off_to_on() {
let code = r#"part001 = startSketchOn('XY')

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], %)
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([
@ -11,8 +12,8 @@ const sketch001 = startSketchOn(XZ)
], %, $yo)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|> close()
const extrude001 = extrude(sketch001, length = 100)
const chamf = chamfer(
extrude001 = extrude(sketch001, length = 100)
chamf = chamfer(
extrude001,
length = 30,
tags = [

View File

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

View File

@ -1,4 +1,4 @@
const part001 = startSketchOn(XY)
|> circle(center= [5, 5], radius= 10)
|> extrude(length = 10)
|> helix(revolutions = 16, angleStart = 0, cylinder = %)
|> helixRevolutions({revolutions = 16, angleStart = 0}, %)

View File

@ -1,4 +1,4 @@
const part001 = startSketchOn(XY)
|> circle(center = [5, 5], radius = 10)
|> extrude(length = -10)
|> helix(revolutions = 16, angleStart = 0, cylinder = %)
|> helixRevolutions({revolutions = 16, angleStart = 0}, %)

View File

@ -1,4 +1,4 @@
const part001 = startSketchOn(XY)
|> circle(center= [5, 5], radius= 10)
|> extrude(length = 10)
|> helix(revolutions = 16, angleStart = 0, length = 3, cylinder = %)
|> helixRevolutions({revolutions = 16, angleStart = 0, length = 3}, %)

View File

@ -2,7 +2,7 @@ mod cache;
use kcl_lib::{
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.
@ -26,7 +26,7 @@ pub(crate) fn assert_out(test_name: &str, result: &image::DynamicImage) -> Strin
async fn kcl_test_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 = err.as_kcl_error().unwrap();
@ -48,7 +48,7 @@ async fn kcl_test_execute_engine_error_return() {
|> 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_eq!(
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.
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);
}
@ -70,7 +70,7 @@ async fn kcl_test_execute_i_shape() {
async fn kcl_test_execute_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);
}
@ -78,7 +78,7 @@ async fn kcl_test_execute_pipes_on_pipes() {
async fn kcl_test_execute_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);
}
@ -86,7 +86,7 @@ async fn kcl_test_execute_cylinder() {
async fn kcl_test_execute_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);
}
@ -94,7 +94,7 @@ async fn kcl_test_execute_kittycad_svg() {
async fn kcl_test_execute_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);
}
@ -102,7 +102,7 @@ async fn kcl_test_execute_lsystem() {
async fn kcl_test_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);
}
@ -110,7 +110,7 @@ async fn kcl_test_member_expression_sketch() {
async fn kcl_test_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);
}
@ -118,7 +118,7 @@ async fn kcl_test_helix_defaults() {
async fn kcl_test_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);
}
@ -126,7 +126,7 @@ async fn kcl_test_helix_defaults_negative_extrude() {
async fn kcl_test_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);
}
@ -134,7 +134,7 @@ async fn kcl_test_helix_with_length() {
async fn kcl_test_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);
}
@ -142,7 +142,7 @@ async fn kcl_test_dimensions_match() {
async fn kcl_test_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);
}
@ -150,7 +150,7 @@ async fn kcl_test_close_arc() {
async fn kcl_test_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);
}
@ -164,7 +164,7 @@ async fn kcl_test_basic_tangential_arc_with_point() {
|> 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);
}
@ -178,7 +178,7 @@ async fn kcl_test_basic_tangential_arc_to() {
|> 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);
}
@ -205,7 +205,7 @@ box(30, 43, 18, '-xy')
let thing = box(-12, -15, 10, 'yz')
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);
}
@ -263,7 +263,7 @@ part004 = startSketchOn(YZ)
|> 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);
}
@ -280,7 +280,7 @@ async fn kcl_test_holes() {
|> 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);
}
@ -299,7 +299,7 @@ async fn optional_params() {
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);
}
@ -335,7 +335,7 @@ part = roundedRectangle([0, 0], 20, 20, 4)
|> 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);
}
@ -343,7 +343,7 @@ part = roundedRectangle([0, 0], 20, 20, 4)
async fn kcl_test_top_level_expression() {
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);
}
@ -357,7 +357,7 @@ part = startSketchOn(XY)
|> 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);
}
@ -369,7 +369,7 @@ async fn kcl_test_patterns_linear_basic() {
|> 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);
}
@ -385,7 +385,7 @@ async fn kcl_test_patterns_linear_basic_3d() {
|> 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);
}
@ -397,7 +397,7 @@ async fn kcl_test_patterns_linear_basic_negative_distance() {
|> 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);
}
@ -409,7 +409,7 @@ async fn kcl_test_patterns_linear_basic_negative_axis() {
|> 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);
}
@ -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);
}
@ -442,7 +442,7 @@ async fn kcl_test_patterns_circular_basic_2d() {
|> 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);
}
@ -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)
"#;
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);
}
@ -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)
"#;
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);
}
@ -483,7 +483,7 @@ async fn kcl_test_import_file_doesnt_exist() {
let code = r#"import 'thing.obj'
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_eq!(
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'
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);
}
@ -506,7 +506,7 @@ async fn kcl_test_import_obj_with_mtl_units() {
import 'e2e/executor/inputs/cube.obj'
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);
}
@ -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
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);
}
@ -524,7 +524,7 @@ async fn kcl_test_import_gltf_with_bin() {
let code = r#"import 'e2e/executor/inputs/cube.gltf'
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);
}
@ -533,7 +533,7 @@ async fn kcl_test_import_gltf_embedded() {
let code = r#"import 'e2e/executor/inputs/cube-embedded.gltf' as 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);
}
@ -542,7 +542,7 @@ async fn kcl_test_import_glb() {
let code = r#"import 'e2e/executor/inputs/cube.glb'
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);
}
@ -551,7 +551,7 @@ async fn kcl_test_import_glb_no_assign() {
let code = r#"import 'e2e/executor/inputs/cube.glb'
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);
}
@ -561,7 +561,7 @@ async fn kcl_test_import_ext_doesnt_match() {
import 'e2e/executor/inputs/cube.gltf'
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_eq!(
result.err().unwrap().to_string(),
@ -586,14 +586,15 @@ async fn kcl_test_cube_mm() {
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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cube_cm() {
let code = r#"fn cube = (pos, scale) => {
sg = startSketchOn(XY)
let code = r#"@settings(defaultLengthUnit = cm)
fn cube = (pos, scale) => {
sg = startSketchOn('XY')
|> startProfileAt(pos, %)
|> line(end = [0, scale])
|> line(end = [scale, 0])
@ -607,14 +608,15 @@ async fn kcl_test_cube_cm() {
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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cube_m() {
let code = r#"fn cube = (pos, scale) => {
sg = startSketchOn(XY)
let code = r#"@settings(defaultLengthUnit = m)
fn cube = (pos, scale) => {
sg = startSketchOn('XY')
|> startProfileAt(pos, %)
|> line(end = [0, scale])
|> line(end = [scale, 0])
@ -628,14 +630,15 @@ async fn kcl_test_cube_m() {
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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cube_in() {
let code = r#"fn cube = (pos, scale) => {
sg = startSketchOn(XY)
let code = r#"@settings(defaultLengthUnit = in)
fn cube = (pos, scale) => {
sg = startSketchOn('XY')
|> startProfileAt(pos, %)
|> line(end = [0, scale])
|> line(end = [scale, 0])
@ -649,14 +652,15 @@ async fn kcl_test_cube_in() {
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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cube_ft() {
let code = r#"fn cube = (pos, scale) => {
sg = startSketchOn(XY)
let code = r#"@settings(defaultLengthUnit = ft)
fn cube = (pos, scale) => {
sg = startSketchOn('XY')
|> startProfileAt(pos, %)
|> line(end = [0, scale])
|> line(end = [scale, 0])
@ -670,14 +674,15 @@ async fn kcl_test_cube_ft() {
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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cube_yd() {
let code = r#"fn cube = (pos, scale) => {
sg = startSketchOn(XY)
let code = r#"@settings(defaultLengthUnit = yd)
fn cube = (pos, scale) => {
sg = startSketchOn('XY')
|> startProfileAt(pos, %)
|> line(end = [0, scale])
|> line(end = [scale, 0])
@ -691,7 +696,7 @@ async fn kcl_test_cube_yd() {
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);
}
@ -719,7 +724,7 @@ part002 = startSketchOn(part001, part001.sketch.tags.here)
|> 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 ExecError::Kcl(err) = err else {
@ -763,7 +768,7 @@ part003 = startSketchOn(part002, "end")
|> 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);
}
@ -780,7 +785,7 @@ async fn kcl_test_stdlib_kcl_error_right_code_path() {
|> 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 ExecError::Kcl(err) = err else {
panic!("Expected KCL error, found {err}");
@ -811,7 +816,7 @@ part002 = startSketchOn(part001, "end")
|> 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);
}
@ -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 ExecError::Kcl(err) = err else {
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);
}
@ -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);
}
@ -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);
}
@ -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
@ -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
@ -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);
}
@ -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);
}
@ -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);
}
@ -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();
//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);
}
@ -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);
}
@ -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);
}
@ -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);
}
@ -1177,7 +1182,7 @@ part002 = startSketchOn(part001, 'end')
|> 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);
}
@ -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);
}
@ -1248,7 +1253,7 @@ plumbus1 = circle1
async fn kcl_test_empty_file_is_ok() {
let code = r#""#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
let result = execute_and_snapshot(code, None).await;
result.unwrap();
}
@ -1278,7 +1283,7 @@ async fn kcl_test_member_expression_in_params() {
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);
}
@ -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();
}
@ -1343,7 +1348,7 @@ secondSketch = startSketchOn(part001, '')
|> 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_eq!(
result.err().unwrap().to_string(),
@ -1374,7 +1379,7 @@ extrusion = startSketchOn(XY)
|> 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_eq!(
result.err().unwrap().to_string(),
@ -1407,7 +1412,7 @@ sketch001 = [profile001, profile002]
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);
}
@ -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);
}
@ -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);
}
@ -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);
}
@ -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);
}
@ -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);
}
@ -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);
}
@ -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)
"#;
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);
}
@ -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 ExecError::Kcl(err) = err else {
panic!("Expected KCL error, found {err}");
@ -1701,7 +1706,7 @@ async fn kcl_test_duplicate_tags_should_error() {
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_eq!(
result.err().unwrap().to_string(),
@ -1712,49 +1717,49 @@ let p = triangle(200)
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_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);
}
@ -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_eq!(
result.err().unwrap().to_string(),
@ -1796,7 +1801,7 @@ async fn kcl_test_angled_line_to_x_90() {
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_eq!(
result.err().unwrap().to_string(),
@ -1816,7 +1821,7 @@ async fn kcl_test_angled_line_to_x_270() {
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_eq!(
result.err().unwrap().to_string(),
@ -1836,7 +1841,7 @@ async fn kcl_test_angled_line_to_y_0() {
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_eq!(
result.err().unwrap().to_string(),
@ -1856,7 +1861,7 @@ async fn kcl_test_angled_line_to_y_180() {
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_eq!(
result.err().unwrap().to_string(),
@ -1876,7 +1881,7 @@ async fn kcl_test_angled_line_of_x_length_90() {
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_eq!(
result.err().unwrap().to_string(),
@ -1896,7 +1901,7 @@ async fn kcl_test_angled_line_of_x_length_270() {
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_eq!(
result.err().unwrap().to_string(),
@ -1918,7 +1923,7 @@ async fn kcl_test_angled_line_of_y_length_0() {
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_eq!(
result.err().unwrap().to_string(),
@ -1940,7 +1945,7 @@ async fn kcl_test_angled_line_of_y_length_180() {
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_eq!(
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)
"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
let result = execute_and_snapshot(code, None).await;
assert!(result.is_err());
assert_eq!(
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')
"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
let result = execute_and_snapshot(code, None).await;
assert!(result.is_err());
assert_eq!(
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')
"#;
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
let result = execute_and_snapshot(code, None).await;
assert!(result.is_err());
assert_eq!(
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
.err()
@ -2050,9 +2055,7 @@ sketch000 = startSketchOn(XY)
|> line(end = [0, innerDiameter / 2])
"#;
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default())
.await
.unwrap();
let ctx = kcl_lib::ExecutorContext::new_with_default_client().await.unwrap();
let mut exec_state = kcl_lib::ExecState::new(&ctx);
let program = kcl_lib::Program::parse_no_errs(code).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.
std::env::set_current_dir(path.parent().unwrap()).unwrap();
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default())
.await
.unwrap();
let ctx = kcl_lib::ExecutorContext::new_with_default_client().await.unwrap();
let mut exec_state = kcl_lib::ExecState::new(&ctx);
let program = kcl_lib::Program::parse_no_errs(&code).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)
|> 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() {
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.
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 {
expectorate::assert_contents(
format!("e2e/executor/outputs/helix_defaults_negative_extrude_{}", file.name),

View File

@ -9,7 +9,7 @@ use pretty_assertions::assert_eq;
/// Setup the engine and parse code for an ast.
async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, ModuleId, uuid::Uuid)> {
let program = Program::parse_no_errs(code)?;
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 = ExecState::new(&ctx);
let result = ctx.run(&program, &mut exec_state).await?;
let outcome = exec_state.to_wasm_outcome(result.0).await;

View File

@ -1155,7 +1155,7 @@ fn find_examples(text: &str, filename: &str) -> Vec<(String, String)> {
async fn run_example(text: &str) -> Result<()> {
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);
ctx.run(&program, &mut exec_state).await?;
Ok(())

View File

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

View File

@ -127,14 +127,13 @@ impl StdLibFnArg {
} else {
""
};
if (self.type_ == "Sketch"
if self.type_ == "Sketch"
|| self.type_ == "[Sketch]"
|| self.type_ == "Solid"
|| self.type_ == "[Solid]"
|| self.type_ == "SketchSurface"
|| self.type_ == "SketchOrSurface"
|| self.type_ == "SolidOrSketchOrImportedGeometry")
&& (self.required || self.include_in_snippet)
|| self.type_ == "SolidOrSketchOrImportedGeometry"
{
return Ok(Some((index, format!("{label}${{{}:{}}}", index, "%"))));
} else if (self.type_ == "TagDeclarator" || self.type_ == "TagNode") && self.required {
@ -1095,38 +1094,16 @@ mod tests {
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_union() {
let union_fn: Box<dyn StdLibFn> = Box::new(crate::std::csg::Union);
let snippet = union_fn.to_autocomplete_snippet().unwrap();
assert_eq!(snippet, r#"union(${0:%})${}"#);
}
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_subtract() {
let subtract_fn: Box<dyn StdLibFn> = Box::new(crate::std::csg::Subtract);
let snippet = subtract_fn.to_autocomplete_snippet().unwrap();
assert_eq!(snippet, r#"subtract(${0:%}, tools = ${1:%})${}"#);
}
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_intersect() {
let intersect_fn: Box<dyn StdLibFn> = Box::new(crate::std::csg::Intersect);
let snippet = intersect_fn.to_autocomplete_snippet().unwrap();
assert_eq!(snippet, r#"intersect(${0:%})${}"#);
}
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_get_common_edge() {
let get_common_edge_fn: Box<dyn StdLibFn> = Box::new(crate::std::edge::GetCommonEdge);
let snippet = get_common_edge_fn.to_autocomplete_snippet().unwrap();
fn get_autocomplete_snippet_helix_revolutions() {
let helix_fn: Box<dyn StdLibFn> = Box::new(crate::std::helix::HelixRevolutions);
let snippet = helix_fn.to_autocomplete_snippet().unwrap();
assert_eq!(
snippet,
r#"getCommonEdge(faces = [{
value = ${0:"string"},
}])${}"#
r#"helixRevolutions({
revolutions = ${0:3.14},
angleStart = ${1:3.14},
ccw = ${2:false},
}, ${3:%})${}"#
);
}

View File

@ -176,6 +176,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
)
.await?;
// Reset to the default units. Modules assume the engine starts in the
// default state.
self.set_units(Default::default(), source_range).await?;
// Flush the batch queue, so clear is run right away.
// Otherwise the hooks below won't work.
self.flush_batch(false, source_range).await?;
@ -252,9 +256,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
// Set the edge visibility.
self.set_edge_visibility(settings.highlight_edges, source_range).await?;
// Change the units.
self.set_units(settings.units, source_range).await?;
// Send the command to show the grid.
self.modify_grid(!settings.show_grid, source_range).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.
// We specifically do this before checking if they are the exact same.
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
// run the settings again.
reapply_settings = true;
@ -424,50 +415,6 @@ shell(firstSketch, faces = ['end'], thickness = 0.25)"#;
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.
#[tokio::test(flavor = "multi_thread")]
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

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

View File

@ -152,8 +152,6 @@ pub struct Helix {
pub angle_start: f64,
/// Is the helix rotation counter clockwise?
pub ccw: bool,
/// The cylinder the helix was created on.
pub cylinder_id: Option<uuid::Uuid>,
pub units: UnitLen,
#[serde(skip)]
pub meta: Vec<Metadata>,

View File

@ -39,7 +39,6 @@ use crate::{
fs::FileManager,
modules::{ModuleId, ModulePath},
parsing::ast::types::{Expr, ImportPath, NodeRef},
settings::types::UnitLength,
source_range::SourceRange,
std::StdLib,
CompilationError, ExecError, ExecutionKind, KclErrorWithOutputs,
@ -265,8 +264,6 @@ pub struct ExecutorContext {
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
pub struct ExecutorSettings {
/// The project-default unit to use in modeling dimensions.
pub units: UnitLength,
/// Highlight edges of 3D objects?
pub highlight_edges: bool,
/// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled.
@ -287,7 +284,6 @@ pub struct ExecutorSettings {
impl Default for ExecutorSettings {
fn default() -> Self {
Self {
units: Default::default(),
highlight_edges: true,
enable_ssao: false,
show_grid: false,
@ -301,7 +297,6 @@ impl Default for ExecutorSettings {
impl From<crate::settings::types::Configuration> for ExecutorSettings {
fn from(config: crate::settings::types::Configuration) -> Self {
Self {
units: config.settings.modeling.base_unit,
highlight_edges: config.settings.modeling.highlight_edges.into(),
enable_ssao: config.settings.modeling.enable_ssao.into(),
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 {
fn from(config: crate::settings::types::project::ProjectConfiguration) -> Self {
Self {
units: config.settings.modeling.base_unit,
highlight_edges: config.settings.modeling.highlight_edges.into(),
enable_ssao: config.settings.modeling.enable_ssao.into(),
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 {
fn from(modeling: crate::settings::types::ModelingSettings) -> Self {
Self {
units: modeling.base_unit,
highlight_edges: modeling.highlight_edges.into(),
enable_ssao: modeling.enable_ssao.into(),
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 {
fn from(modeling: crate::settings::types::project::ProjectModelingSettings) -> Self {
Self {
units: modeling.base_unit,
highlight_edges: modeling.highlight_edges.into(),
enable_ssao: modeling.enable_ssao.into(),
show_grid: Default::default(),
@ -476,26 +468,17 @@ impl ExecutorContext {
/// This allows for passing in `ZOO_API_TOKEN` and `ZOO_HOST` as environment
/// variables.
#[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.
let ctx = Self::new_with_client(
ExecutorSettings {
units,
..Default::default()
},
None,
None,
)
.await?;
let ctx = Self::new_with_client(Default::default(), None, None).await?;
Ok(ctx)
}
/// For executing unit tests.
#[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(
ExecutorSettings {
units,
highlight_edges: true,
enable_ssao: false,
show_grid: false,
@ -846,11 +829,6 @@ impl ExecutorContext {
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.
pub async fn prepare_snapshot(&self) -> std::result::Result<TakeSnapshot, ExecError> {
// Zoom to fit.
@ -1923,9 +1901,7 @@ let w = f() + f()
)
"#;
let ctx = crate::test_server::new_context(UnitLength::Mm, true, None)
.await
.unwrap();
let ctx = crate::test_server::new_context(true, None).await.unwrap();
let old_program = crate::Program::parse_no_errs(code).unwrap();
// Execute the program.
@ -1978,9 +1954,7 @@ let w = f() + f()
)
"#;
let mut ctx = crate::test_server::new_context(UnitLength::Mm, true, None)
.await
.unwrap();
let mut ctx = crate::test_server::new_context(true, None).await.unwrap();
let old_program = crate::Program::parse_no_errs(code).unwrap();
// Execute the program.
@ -2016,7 +1990,7 @@ let w = f() + f()
#[tokio::test(flavor = "multi_thread")]
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 result = ctx.run_with_caching(program).await.unwrap();
assert_eq!(result.variables.get("x").unwrap().as_f64().unwrap(), 2.0);

View File

@ -78,7 +78,7 @@ impl ExecState {
pub fn new(exec_context: &super::ExecutorContext) -> Self {
ExecState {
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()),
}
}
@ -88,7 +88,7 @@ impl ExecState {
*self = ExecState {
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()),
};
}
@ -285,19 +285,14 @@ impl GlobalState {
}
impl ModuleState {
pub(super) fn new(
exec_settings: &ExecutorSettings,
std_path: Option<String>,
memory: Arc<ProgramMemory>,
module_id: Option<ModuleId>,
) -> Self {
pub(super) fn new(std_path: Option<String>, memory: Arc<ProgramMemory>, module_id: Option<ModuleId>) -> Self {
ModuleState {
id_generator: IdGenerator::new(module_id),
stack: memory.new_stack(),
pipe_value: Default::default(),
module_exports: Default::default(),
settings: MetaSettings {
default_length_units: exec_settings.units.into(),
default_length_units: Default::default(),
default_angle_units: Default::default(),
std_path,
},
@ -305,7 +300,7 @@ impl ModuleState {
}
}
#[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)]
#[serde(rename_all = "camelCase")]
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> {
self.ast.lint_all()
}

View File

@ -812,56 +812,6 @@ impl Backend {
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(
&self,
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)),
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)
.finish();

View File

@ -2320,78 +2320,6 @@ async fn kcl_test_kcl_lsp_on_change_update_memory() {
.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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_kcl_lsp_empty_file_execute_ok() {
let server = kcl_lsp_server(true).await.unwrap();
@ -2719,141 +2647,6 @@ async fn kcl_test_kcl_lsp_code_and_ast_unchanged_but_has_diagnostics_reexecute()
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
}
#[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);
}
#[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);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_kcl_lsp_cant_execute_set() {
let server = kcl_lsp_server(true).await.unwrap();
@ -2885,23 +2678,6 @@ async fn kcl_test_kcl_lsp_cant_execute_set() {
// Assure we have no diagnostics.
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.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default());
@ -2918,23 +2694,6 @@ async fn kcl_test_kcl_lsp_cant_execute_set() {
.unwrap();
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();
default_hashed.compute_digest();
@ -2952,23 +2711,6 @@ async fn kcl_test_kcl_lsp_cant_execute_set() {
.unwrap();
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.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default());

View File

@ -346,6 +346,29 @@ impl Node<Program> {
Ok(new_program)
}
/// Returns true if the given KCL is empty or only contains settings that
/// would be auto-generated.
///
/// TODO: Don't consider comments to be empty since they will get blown away
/// by the UI.
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 {
@ -3480,6 +3503,37 @@ mod tests {
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.
#[test]
fn test_variable_kind_to_completion() {

View File

@ -60,11 +60,8 @@ pub fn parse_tokens(mut tokens: TokenStream) -> ParseResult {
return Node::<Program>::default().into();
}
// Check all the tokens are whitespace or comments.
if tokens
.iter()
.all(|t| t.token_type.is_whitespace() || t.token_type.is_comment())
{
// Check all the tokens are whitespace.
if tokens.iter().all(|t| t.token_type.is_whitespace()) {
return Node::<Program>::default().into();
}

View File

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

View File

@ -1258,6 +1258,23 @@ impl<'a> FromKclValue<'a> for super::sketch::BezierData {
}
}
impl<'a> FromKclValue<'a> for super::helix::HelixRevolutionsData {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let obj = arg.as_object()?;
let_field_of!(obj, revolutions);
let_field_of!(obj, length?);
let_field_of!(obj, ccw?);
let ccw = ccw.unwrap_or_default();
let angle_start = obj.get("angleStart")?.as_f64()?;
Some(Self {
revolutions,
angle_start,
ccw,
length,
})
}
}
impl<'a> FromKclValue<'a> for FaceTag {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let case1 = || match arg.as_str() {

View File

@ -165,7 +165,7 @@ async fn inner_fillet(
edge_id,
object_id: solid.id,
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,
// We make this a none so that we can remove it in the future.
face_id: None,

View File

@ -4,6 +4,8 @@ use anyhow::Result;
use kcl_derive_docs::stdlib;
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
use kittycad_modeling_cmds as kcmc;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{
errors::KclError,
@ -16,71 +18,11 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
let angle_start = args.get_kw_arg("angleStart")?;
let revolutions = args.get_kw_arg("revolutions")?;
let ccw = args.get_kw_arg_opt("ccw")?;
let radius = args.get_kw_arg_opt("radius")?;
let axis = args.get_kw_arg_opt("axis")?;
let radius = args.get_kw_arg("radius")?;
let axis = args.get_kw_arg("axis")?;
let length = args.get_kw_arg_opt("length")?;
let cylinder = args.get_kw_arg_opt("cylinder")?;
// Make sure we have a radius if we don't have a cylinder.
if radius.is_none() && cylinder.is_none() {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Radius is required when creating a helix without a cylinder.".to_string(),
source_ranges: vec![args.source_range],
}));
}
// Make sure we don't have a radius if we have a cylinder.
if radius.is_some() && cylinder.is_some() {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Radius is not allowed when creating a helix with a cylinder.".to_string(),
source_ranges: vec![args.source_range],
}));
}
// Make sure we have an axis if we don't have a cylinder.
if axis.is_none() && cylinder.is_none() {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Axis is required when creating a helix without a cylinder.".to_string(),
source_ranges: vec![args.source_range],
}));
}
// Make sure we don't have an axis if we have a cylinder.
if axis.is_some() && cylinder.is_some() {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Axis is not allowed when creating a helix with a cylinder.".to_string(),
source_ranges: vec![args.source_range],
}));
}
// Make sure we have a radius if we have an axis.
if radius.is_none() && axis.is_some() {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Radius is required when creating a helix around an axis.".to_string(),
source_ranges: vec![args.source_range],
}));
}
// Make sure we have an axis if we have a radius.
if axis.is_none() && radius.is_some() {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Axis is required when creating a helix around an axis.".to_string(),
source_ranges: vec![args.source_range],
}));
}
let value = inner_helix(
revolutions,
angle_start,
ccw,
radius,
axis,
length,
cylinder,
exec_state,
args,
)
.await?;
let value = inner_helix(revolutions, angle_start, ccw, radius, axis, length, exec_state, args).await?;
Ok(KclValue::Helix { value })
}
@ -146,23 +88,6 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// |> circle( center = [0, 0], radius = 1 )
/// |> sweep(path = helixPath)
/// ```
///
///
///
/// ```no_run
/// // Create a helix on a cylinder.
///
/// part001 = startSketchOn('XY')
/// |> circle( center= [5, 5], radius= 10 )
/// |> extrude(length = 10)
///
/// helix(
/// angleStart = 0,
/// ccw = true,
/// revolutions = 16,
/// cylinder = part001,
/// )
/// ```
#[stdlib {
name = "helix",
keywords = true,
@ -171,10 +96,9 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
revolutions = { docs = "Number of revolutions."},
angle_start = { docs = "Start angle (in degrees)."},
ccw = { docs = "Is the helix rotation counter clockwise? The default is `false`.", include_in_snippet = false},
radius = { docs = "Radius of the helix.", include_in_snippet = true},
axis = { docs = "Axis to use for the helix.", include_in_snippet = true},
radius = { docs = "Radius of the helix."},
axis = { docs = "Axis to use for the helix."},
length = { docs = "Length of the helix. This is not necessary if the helix is created around an edge. If not given the length of the edge is used.", include_in_snippet = true},
cylinder = { docs = "Cylinder to create the helix on.", include_in_snippet = false},
},
feature_tree_operation = true,
}]
@ -183,10 +107,9 @@ async fn inner_helix(
revolutions: f64,
angle_start: f64,
ccw: Option<bool>,
radius: Option<f64>,
axis: Option<Axis3dOrEdgeReference>,
radius: f64,
axis: Axis3dOrEdgeReference,
length: Option<f64>,
cylinder: Option<Solid>,
exec_state: &mut ExecState,
args: Args,
) -> Result<Box<HelixValue>, KclError> {
@ -197,7 +120,6 @@ async fn inner_helix(
artifact_id: id.into(),
revolutions,
angle_start,
cylinder_id: cylinder.as_ref().map(|c| c.id),
ccw: ccw.unwrap_or(false),
units: exec_state.length_unit(),
meta: vec![args.source_range.into()],
@ -207,63 +129,113 @@ async fn inner_helix(
return Ok(helix_result);
}
if let Some(cylinder) = cylinder {
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::EntityMakeHelix {
cylinder_id: cylinder.id,
is_clockwise: !helix_result.ccw,
length: LengthUnit(length.unwrap_or(cylinder.height)),
revolutions,
start_angle: Angle::from_degrees(angle_start),
}),
)
.await?;
} else if let (Some(axis), Some(radius)) = (axis, radius) {
match axis {
Axis3dOrEdgeReference::Axis(axis) => {
let (axis, origin) = axis.axis_and_origin()?;
match axis {
Axis3dOrEdgeReference::Axis(axis) => {
let (axis, origin) = axis.axis_and_origin()?;
// Make sure they gave us a length.
let Some(length) = length else {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Length is required when creating a helix around an axis.".to_string(),
source_ranges: vec![args.source_range],
}));
};
// Make sure they gave us a length.
let Some(length) = length else {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Length is required when creating a helix around an axis.".to_string(),
source_ranges: vec![args.source_range],
}));
};
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::EntityMakeHelixFromParams {
radius: LengthUnit(radius),
is_clockwise: !helix_result.ccw,
length: LengthUnit(length),
revolutions,
start_angle: Angle::from_degrees(angle_start),
axis,
center: origin,
}),
)
.await?;
}
Axis3dOrEdgeReference::Edge(edge) => {
let edge_id = edge.get_engine_id(exec_state, &args)?;
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::EntityMakeHelixFromParams {
radius: LengthUnit(radius),
is_clockwise: !helix_result.ccw,
length: LengthUnit(length),
revolutions,
start_angle: Angle::from_degrees(angle_start),
axis,
center: origin,
}),
)
.await?;
}
Axis3dOrEdgeReference::Edge(edge) => {
let edge_id = edge.get_engine_id(exec_state, &args)?;
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::EntityMakeHelixFromEdge {
radius: LengthUnit(radius),
is_clockwise: !helix_result.ccw,
length: length.map(LengthUnit),
revolutions,
start_angle: Angle::from_degrees(angle_start),
edge_id,
}),
)
.await?;
}
};
}
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::EntityMakeHelixFromEdge {
radius: LengthUnit(radius),
is_clockwise: !helix_result.ccw,
length: length.map(LengthUnit),
revolutions,
start_angle: Angle::from_degrees(angle_start),
edge_id,
}),
)
.await?;
}
};
Ok(helix_result)
}
/// Data for helix revolutions.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
pub struct HelixRevolutionsData {
/// Number of revolutions.
pub revolutions: f64,
/// Start angle (in degrees).
#[serde(rename = "angleStart")]
pub angle_start: f64,
/// Is the helix rotation counter clockwise?
/// The default is `false`.
#[serde(default)]
pub ccw: bool,
/// Length of the helix. If this argument is not provided, the height of
/// the solid is used.
pub length: Option<f64>,
}
/// Create a helix on a cylinder.
pub async fn helix_revolutions(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (data, solid): (HelixRevolutionsData, Box<Solid>) = args.get_data_and_solid(exec_state)?;
let value = inner_helix_revolutions(data, solid, exec_state, args).await?;
Ok(KclValue::Solid { value })
}
/// Create a helix on a cylinder.
///
/// ```no_run
/// part001 = startSketchOn('XY')
/// |> circle( center= [5, 5], radius= 10 )
/// |> extrude(length = 10)
/// |> helixRevolutions({
/// angleStart = 0,
/// ccw = true,
/// revolutions = 16,
/// }, %)
/// ```
#[stdlib {
name = "helixRevolutions",
feature_tree_operation = true,
}]
async fn inner_helix_revolutions(
data: HelixRevolutionsData,
solid: Box<Solid>,
exec_state: &mut ExecState,
args: Args,
) -> Result<Box<Solid>, KclError> {
let id = exec_state.next_uuid();
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::EntityMakeHelix {
cylinder_id: solid.id,
is_clockwise: !data.ccw,
length: LengthUnit(data.length.unwrap_or(solid.height)),
revolutions: data.revolutions,
start_angle: Angle::from_degrees(data.angle_start),
}),
)
.await?;
Ok(solid)
}

View File

@ -159,7 +159,7 @@ async fn inner_loft(
section_ids: sketches.iter().map(|group| group.id).collect(),
base_curve_index,
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,
}),
)

View File

@ -114,6 +114,7 @@ lazy_static! {
Box::new(crate::std::edge::GetPreviousAdjacentEdge),
Box::new(crate::std::edge::GetCommonEdge),
Box::new(crate::std::helix::Helix),
Box::new(crate::std::helix::HelixRevolutions),
Box::new(crate::std::shell::Shell),
Box::new(crate::std::shell::Hollow),
Box::new(crate::std::revolve::Revolve),

View File

@ -273,7 +273,9 @@ async fn inner_revolve(
target: sketch.id.into(),
axis,
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,
}),
)
@ -287,7 +289,9 @@ async fn inner_revolve(
angle,
target: sketch.id.into(),
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?;

View File

@ -192,7 +192,7 @@ async fn inner_sweep(
target: sketch.id.into(),
trajectory,
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?;

View File

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

View File

@ -2039,6 +2039,15 @@ thing = 'foo'
);
}
#[test]
fn test_recast_only_line_comments() {
let code = r#"// comment at start
"#;
let program = crate::parsing::top_level_parse(code).unwrap();
assert_eq!(program.recast(&Default::default(), 0), code);
}
#[test]
fn test_recast_comment_at_start() {
let test_program = r#"

View File

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

View File

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

View File

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

View File

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

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