Compare commits
4 Commits
jtran/unit
...
kcl-53
Author | SHA1 | Date | |
---|---|---|---|
3464f93a30 | |||
f6936f55d6 | |||
eef1a28ebb | |||
5aed80e930 |
@ -74,7 +74,6 @@ layout: manual
|
||||
* [`getOppositeEdge`](kcl/getOppositeEdge)
|
||||
* [`getPreviousAdjacentEdge`](kcl/getPreviousAdjacentEdge)
|
||||
* [`helix`](kcl/helix)
|
||||
* [`helixRevolutions`](kcl/helixRevolutions)
|
||||
* [`hole`](kcl/hole)
|
||||
* [`hollow`](kcl/hollow)
|
||||
* [`inch`](kcl/inch)
|
||||
|
2365
docs/kcl/std.json
@ -21,6 +21,7 @@ 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 |
|
||||
|
||||
|
||||
|
@ -85,7 +85,7 @@ async function doBasicSketch(
|
||||
await page.mouse.click(startXPx, 500 - PUR * 20)
|
||||
if (openPanes.includes('code')) {
|
||||
await expect(u.codeLocator)
|
||||
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn('XZ')profile001 = startProfileAt(${
|
||||
.toHaveText(`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(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn('XZ')profile001 = startProfileAt(${
|
||||
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
|
||||
commonPoints.startAt
|
||||
}, sketch001)
|
||||
|> xLine(length = ${commonPoints.num1}, tag = $seg01)
|
||||
|
@ -46,7 +46,7 @@ test.describe(
|
||||
},
|
||||
}
|
||||
|
||||
const code = `@settings(defaultLengthUnit = in)sketch001 = startSketchOn('${plane}')profile001 = startProfileAt([0.91, -1.22], sketch001)`
|
||||
const code = `sketch001 = startSketchOn(${plane})profile001 = startProfileAt([0.91, -1.22], sketch001)`
|
||||
|
||||
await u.openDebugPanel()
|
||||
|
||||
|
@ -250,11 +250,11 @@ test(
|
||||
])
|
||||
await Promise.all([
|
||||
fsp.copyFile(
|
||||
executorInputPath('cylinder-inches.kcl'),
|
||||
executorInputPath('router-template-slate.kcl'),
|
||||
join(routerTemplateDir, 'main.kcl')
|
||||
),
|
||||
fsp.copyFile(
|
||||
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
join(bracketDir, 'main.kcl')
|
||||
),
|
||||
])
|
||||
|
@ -20,11 +20,11 @@ test(
|
||||
await Promise.all([fsp.mkdir(bracketDir, { recursive: true })])
|
||||
await Promise.all([
|
||||
fsp.copyFile(
|
||||
executorInputPath('cylinder-inches.kcl'),
|
||||
executorInputPath('router-template-slate.kcl'),
|
||||
path.join(bracketDir, 'other.kcl')
|
||||
),
|
||||
fsp.copyFile(
|
||||
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
path.join(bracketDir, 'main.kcl')
|
||||
),
|
||||
])
|
||||
@ -107,7 +107,7 @@ test(
|
||||
},
|
||||
{ timeout: 15_000 }
|
||||
)
|
||||
.toBeGreaterThan(30_000)
|
||||
.toBeGreaterThan(300_000)
|
||||
})
|
||||
})
|
||||
|
||||
@ -187,7 +187,7 @@ test(
|
||||
},
|
||||
{ timeout: 15_000 }
|
||||
)
|
||||
.toBeGreaterThan(50_000)
|
||||
.toBeGreaterThan(70_000)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -32,30 +32,26 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
||||
await page.keyboard.press('/')
|
||||
await page.keyboard.up('ControlOrMeta')
|
||||
|
||||
await expect(page.locator('.cm-content')).toHaveText(
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn('XY')
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`sketch001 = startSketchOn(XY)
|
||||
|> startProfileAt([-10, -10], %)
|
||||
|> line(end = [20, 0])
|
||||
|> line(end = [0, 20])
|
||||
|> line(end = [-20, 0])
|
||||
// |> close()`.replaceAll('\n', '')
|
||||
)
|
||||
// |> close()`)
|
||||
|
||||
// uncomment the code
|
||||
await page.keyboard.down('ControlOrMeta')
|
||||
await page.keyboard.press('/')
|
||||
await page.keyboard.up('ControlOrMeta')
|
||||
|
||||
await expect(page.locator('.cm-content')).toHaveText(
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn('XY')
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`sketch001 = startSketchOn(XY)
|
||||
|> startProfileAt([-10, -10], %)
|
||||
|> line(end = [20, 0])
|
||||
|> line(end = [0, 20])
|
||||
|> line(end = [-20, 0])
|
||||
|> close()`.replaceAll('\n', '')
|
||||
)
|
||||
|> close()`)
|
||||
})
|
||||
|
||||
test('ensure we use the cache, and do not re-execute', async ({
|
||||
@ -182,15 +178,13 @@ sketch001 = startSketchOn('XY')
|
||||
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(
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn('XY')
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`sketch001 = startSketchOn(XY)
|
||||
|> startProfileAt([-10, -10], %)
|
||||
|> line(end = [20, 0])
|
||||
|> line(end = [0, 20])
|
||||
|> line(end = [-20, 0])
|
||||
|> close()`.replaceAll('\n', '')
|
||||
)
|
||||
|> close()`)
|
||||
})
|
||||
|
||||
test('if you click the format button it formats your code and executes so lints are still there', async ({
|
||||
@ -233,15 +227,13 @@ sketch001 = startSketchOn('XY')
|
||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||
await u.closeDebugPanel()
|
||||
|
||||
await expect(page.locator('.cm-content')).toHaveText(
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch_001 = startSketchOn('XY')
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`sketch_001 = startSketchOn(XY)
|
||||
|> startProfileAt([-10, -10], %)
|
||||
|> line(end = [20, 0])
|
||||
|> line(end = [0, 20])
|
||||
|> line(end = [-20, 0])
|
||||
|> close()`.replaceAll('\n', '')
|
||||
)
|
||||
|> close()`)
|
||||
|
||||
// error in guter
|
||||
await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible()
|
||||
@ -823,12 +815,10 @@ sketch_001 = startSketchOn('XY')
|
||||
// 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(
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn('XZ')
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`sketch001 = startSketchOn(XZ)
|
||||
|> startProfileAt([3.14, 12], %)
|
||||
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
|
||||
)
|
||||
|> xLine(%, length = 5) // lin`)
|
||||
|
||||
// expect there to be no KCL errors
|
||||
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(0)
|
||||
@ -898,12 +888,10 @@ sketch001 = startSketchOn('XZ')
|
||||
// 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(
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn('XZ')
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`sketch001 = startSketchOn(XZ)
|
||||
|> startProfileAt([3.14, 12], %)
|
||||
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
|
||||
)
|
||||
|> xLine(%, length = 5) // lin`)
|
||||
})
|
||||
})
|
||||
test('Can undo a click and point extrude with ctrl+z', async ({
|
||||
|
@ -310,9 +310,7 @@ export async function expectPixelColor(
|
||||
.toBeTruthy()
|
||||
.catch((cause) => {
|
||||
throw new Error(
|
||||
`ExpectPixelColor: point ${JSON.stringify(
|
||||
coords
|
||||
)} was expecting ${colour} but got ${finalValue}`,
|
||||
`ExpectPixelColor: expecting ${colour} got ${finalValue}`,
|
||||
{ cause }
|
||||
)
|
||||
})
|
||||
|
@ -11,7 +11,7 @@ test(
|
||||
const bracketDir = join(dir, 'bracket')
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
executorInputPath('cylinder-inches.kcl'),
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.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('cylinder-inches.kcl'),
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
join(bracketDir, 'main.kcl')
|
||||
)
|
||||
})
|
||||
|
@ -137,7 +137,7 @@ test.describe('Point-and-click tests', () => {
|
||||
|
||||
await scene.moveCameraTo(cameraPos, cameraTarget)
|
||||
|
||||
await test.step('check chamfer selection changes cursor position', async () => {
|
||||
await test.step('check chamfer selection changes cursor positon', 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: ['@settings(defaultLengthUnit = in)'],
|
||||
activeLines: ['sketch001 = startSketchOn(XZ)'],
|
||||
highlightedCode: '',
|
||||
diagnostics: [],
|
||||
})
|
||||
@ -299,8 +299,7 @@ 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(
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
`sketch001 = startSketchOn(XZ)
|
||||
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
@ -370,7 +369,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
|
||||
})
|
||||
})
|
||||
|
||||
test('Works on chamfers that are not in a pipeExpression can break up multi edges in a chamfer array', async ({
|
||||
test('Works on chamfers that are non in a pipeExpression can break up multi edges in a chamfer array', async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
@ -419,8 +418,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
|
||||
|>close()`,
|
||||
})
|
||||
await editor.expectEditor.toContain(
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
`sketch001 = startSketchOn(XZ)
|
||||
|> startProfileAt([75.8, 317.2], %)
|
||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
@ -1342,8 +1340,7 @@ loft001 = loft([sketch001, sketch002])
|
||||
{
|
||||
targetType: 'circle',
|
||||
testPoint: { x: 700, y: 250 },
|
||||
initialCode: `@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn('YZ')
|
||||
initialCode: `sketch001 = startSketchOn('YZ')
|
||||
profile001 = circle(sketch001, center = [0, 0], radius = 500)
|
||||
sketch002 = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
@ -1353,8 +1350,7 @@ sketch002 = startSketchOn('XZ')
|
||||
{
|
||||
targetType: 'rectangle',
|
||||
testPoint: { x: 710, y: 255 },
|
||||
initialCode: `@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn('YZ')
|
||||
initialCode: `sketch001 = startSketchOn('YZ')
|
||||
profile001 = startProfileAt([-400, -400], sketch001)
|
||||
|> angledLine([0, 800], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
@ -1511,8 +1507,7 @@ sketch002 = startSketchOn('XZ')
|
||||
toolbar,
|
||||
cmdBar,
|
||||
}) => {
|
||||
const initialCode = `@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(YZ)
|
||||
const initialCode = `sketch001 = startSketchOn(YZ)
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = 500
|
||||
@ -2079,8 +2074,7 @@ extrude001 = extrude(profile001, length = 5)
|
||||
cmdBar,
|
||||
}) => {
|
||||
// Code samples
|
||||
const initialCode = `@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XY)
|
||||
const initialCode = `sketch001 = startSketchOn(XY)
|
||||
|> startProfileAt([-12, -6], %)
|
||||
|> line(end = [0, 12])
|
||||
|> line(end = [24, 0])
|
||||
@ -2304,8 +2298,7 @@ extrude001 = extrude(sketch001, length = -12)
|
||||
toolbar,
|
||||
}) => {
|
||||
// Code samples
|
||||
const initialCode = `@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XY)
|
||||
const initialCode = `sketch001 = startSketchOn(XY)
|
||||
|> startProfileAt([-12, -6], %)
|
||||
|> line(end = [0, 12])
|
||||
|> line(end = [24, 0], tag = $seg02)
|
||||
@ -2459,8 +2452,7 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
||||
toolbar,
|
||||
cmdBar,
|
||||
}) => {
|
||||
const initialCode = `@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
const initialCode = `sketch001 = startSketchOn(XZ)
|
||||
|> circle(center = [0, 0], radius = 30)
|
||||
extrude001 = extrude(sketch001, length = 30)
|
||||
`
|
||||
@ -2595,8 +2587,7 @@ extrude001 = extrude(sketch001, length = 30)
|
||||
toolbar,
|
||||
cmdBar,
|
||||
}) => {
|
||||
const initialCode = `@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XY)
|
||||
const initialCode = `sketch001 = startSketchOn(XY)
|
||||
|> startProfileAt([-20, 20], %)
|
||||
|> xLine(length = 40)
|
||||
|> yLine(length = -60)
|
||||
@ -2714,8 +2705,7 @@ extrude001 = extrude(sketch001, length = 40)
|
||||
})
|
||||
|
||||
const shellSketchOnFacesCases = [
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
`sketch001 = startSketchOn(XZ)
|
||||
|> circle(center = [0, 0], radius = 100)
|
||||
|> extrude(length = 100)
|
||||
|
||||
@ -2723,8 +2713,7 @@ sketch002 = startSketchOn(sketch001, 'END')
|
||||
|> circle(center = [0, 0], radius = 50)
|
||||
|> extrude(length = 50)
|
||||
`,
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
`sketch001 = startSketchOn(XZ)
|
||||
|> circle(center = [0, 0], radius = 100)
|
||||
extrude001 = extrude(sketch001, length = 100)
|
||||
|
||||
@ -3120,8 +3109,7 @@ radius = 8.69
|
||||
toolbar,
|
||||
cmdBar,
|
||||
}) => {
|
||||
const initialCode = `@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
const initialCode = `sketch001 = startSketchOn(XZ)
|
||||
profile001 = circle(
|
||||
sketch001,
|
||||
center = [0, 0],
|
||||
|
@ -86,7 +86,7 @@ test(
|
||||
const bracketDir = path.join(dir, 'bracket')
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
executorInputPath('cylinder-inches.kcl'),
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.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('cylinder-inches.kcl'),
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.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('cylinder-inches.kcl'),
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.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('cylinder-inches.kcl'),
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.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('cylinder-inches.kcl'),
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.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('cylinder-inches.kcl'),
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
path.join(bracketDir, 'main.kcl')
|
||||
)
|
||||
})
|
||||
@ -1497,12 +1497,7 @@ test(
|
||||
|
||||
await u.waitForPageLoad()
|
||||
|
||||
// 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')
|
||||
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])
|
||||
|
@ -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('cylinder-inches.kcl'),
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
path.join(bracketDir, 'main.kcl')
|
||||
)
|
||||
})
|
||||
@ -632,13 +632,12 @@ extrude002 = extrude(profile002, length = 150)
|
||||
|
||||
await test.step(`Load an empty file`, async () => {
|
||||
await page.addInitScript(async () => {
|
||||
localStorage.setItem('persistCode', '@settings(defaultLengthUnit = in)')
|
||||
localStorage.setItem('persistCode', '')
|
||||
})
|
||||
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 () => {
|
||||
@ -647,14 +646,13 @@ extrude002 = extrude(profile002, length = 150)
|
||||
timeout: 5000,
|
||||
message: 'Plane color is visible',
|
||||
})
|
||||
.toBeLessThanOrEqual(20)
|
||||
.toBeLessThanOrEqual(15)
|
||||
|
||||
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 })
|
||||
@ -662,7 +660,7 @@ extrude002 = extrude(profile002, length = 150)
|
||||
await page.keyboard.up('Control')
|
||||
await page.waitForTimeout(100)
|
||||
maxZoomOuts--
|
||||
middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 15
|
||||
middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 10
|
||||
}
|
||||
|
||||
expect(middlePixelIsBackgroundColor, {
|
||||
@ -680,12 +678,13 @@ 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('e2e-can-sketch-on-chamfer.kcl'),
|
||||
executorInputPath('lego.kcl'),
|
||||
path.join(legoDir, 'main.kcl')
|
||||
)
|
||||
})
|
||||
@ -698,8 +697,11 @@ 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 () => {
|
||||
// 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)
|
||||
await scene.expectPixelColor(
|
||||
[143, 143, 143],
|
||||
{ x: (viewport?.width ?? 1200) / 2, y: (viewport?.height ?? 500) / 2 },
|
||||
15
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -113,8 +113,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
|
||||
await page.addInitScript(async () => {
|
||||
localStorage.setItem(
|
||||
'persistCode',
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
`sketch001 = startSketchOn(XZ)
|
||||
|> startProfileAt([2.61, -4.01], %)
|
||||
|> xLine(length = 8.73)
|
||||
|> tangentialArcTo([8.33, -1.31], %)`
|
||||
@ -160,10 +159,7 @@ sketch001 = startSketchOn(XZ)
|
||||
await page.mouse.click(700, 200)
|
||||
|
||||
await expect.poll(u.normalisedEditorCode, { timeout: 1000 })
|
||||
.toBe(`@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
sketch002 = startSketchOn(XZ)
|
||||
.toBe(`sketch002 = startSketchOn(XZ)
|
||||
sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
||||
|> yLine(length = 12.34)
|
||||
|
||||
@ -793,8 +789,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
||||
200
|
||||
)
|
||||
|
||||
let codeStr =
|
||||
'@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XY)'
|
||||
let codeStr = 'sketch001 = startSketchOn(XY)'
|
||||
|
||||
await page.mouse.click(center.x, viewportSize.height * 0.55)
|
||||
await expect(u.codeLocator).toHaveText(codeStr)
|
||||
@ -1431,8 +1426,7 @@ test.describe(`Sketching with offset planes`, () => {
|
||||
await context.addInitScript(() => {
|
||||
localStorage.setItem(
|
||||
'persistCode',
|
||||
`@settings(defaultLengthUnit = in)
|
||||
offsetPlane001 = offsetPlane(XY, offset = 10)`
|
||||
`offsetPlane001 = offsetPlane(XY, offset = 10)`
|
||||
)
|
||||
})
|
||||
|
||||
@ -1446,7 +1440,7 @@ offsetPlane001 = offsetPlane(XY, offset = 10)`
|
||||
await test.step(`Hovering should highlight code`, async () => {
|
||||
await planeHover()
|
||||
await editor.expectState({
|
||||
activeLines: [`@settings(defaultLengthUnit = in)`],
|
||||
activeLines: [`offsetPlane001=offsetPlane(XY,offset=10)`],
|
||||
diagnostics: [],
|
||||
highlightedCode: 'offsetPlane(XY, offset = 10)',
|
||||
})
|
||||
@ -1459,7 +1453,7 @@ offsetPlane001 = offsetPlane(XY, offset = 10)`
|
||||
await expect(toolbar.lineBtn).toBeEnabled()
|
||||
await editor.expectEditor.toContain('startSketchOn(offsetPlane001)')
|
||||
await editor.expectState({
|
||||
activeLines: [`@settings(defaultLengthUnit = in)`],
|
||||
activeLines: [`offsetPlane001=offsetPlane(XY,offset=10)`],
|
||||
diagnostics: [],
|
||||
highlightedCode: '',
|
||||
})
|
||||
@ -2492,11 +2486,7 @@ extrude001 = extrude(profile003, length = 5)
|
||||
page,
|
||||
}) => {
|
||||
await page.addInitScript(async () => {
|
||||
localStorage.setItem(
|
||||
'persistCode',
|
||||
`@settings(defaultLengthUnit = in)
|
||||
myVar = 5`
|
||||
)
|
||||
localStorage.setItem('persistCode', `myVar = 5`)
|
||||
})
|
||||
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 68 KiB |
@ -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_HEAD_REF !== 'all-e2e'
|
||||
return process.env.GITHUB_REF !== 'all-e2e'
|
||||
}
|
||||
|
||||
async function waitForPageLoadWithRetry(page: Page) {
|
||||
|
@ -4,6 +4,7 @@ import {
|
||||
getUtils,
|
||||
TEST_COLORS,
|
||||
pollEditorLinesSelectedLength,
|
||||
executorInputPath,
|
||||
orRunWhenFullSuiteEnabled,
|
||||
} from './test-utils'
|
||||
import { XOR } from 'lib/utils'
|
||||
@ -1116,19 +1117,9 @@ 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.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'
|
||||
await fsp.copyFile(
|
||||
executorInputPath('angled_line.kcl'),
|
||||
path.join(bracketDir, 'main.kcl')
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -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)
|
||||
|
@ -271,7 +271,7 @@ test.describe('Testing settings', () => {
|
||||
const bracketDir = join(dir, projectName)
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
executorInputPath('cylinder-inches.kcl'),
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
join(bracketDir, 'main.kcl')
|
||||
)
|
||||
}
|
||||
@ -746,6 +746,7 @@ 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)
|
||||
|
||||
@ -950,9 +951,9 @@ test.describe('Testing settings', () => {
|
||||
)
|
||||
})
|
||||
|
||||
await test.step(`Initial units from settings are ignored`, async () => {
|
||||
await test.step(`Initial units from settings`, async () => {
|
||||
await homePage.openProject('project-000')
|
||||
await expect(unitsIndicator).toHaveText('Current units are: mm')
|
||||
await expect(unitsIndicator).toHaveText('Current units are: in')
|
||||
})
|
||||
|
||||
await test.step(`Manually write inline settings`, async () => {
|
||||
|
@ -483,8 +483,7 @@ test('Sketch on face', async ({ page, homePage, scene, cmdBar, toolbar }) => {
|
||||
await page.addInitScript(async () => {
|
||||
localStorage.setItem(
|
||||
'persistCode',
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
`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
@ -1780,7 +1780,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-bumper"
|
||||
version = "0.1.52"
|
||||
version = "0.1.53"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1791,7 +1791,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-derive-docs"
|
||||
version = "0.1.52"
|
||||
version = "0.1.53"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"anyhow",
|
||||
@ -1810,7 +1810,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-directory-test-macro"
|
||||
version = "0.1.52"
|
||||
version = "0.1.53"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1819,7 +1819,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-language-server"
|
||||
version = "0.2.52"
|
||||
version = "0.2.53"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1840,7 +1840,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-language-server-release"
|
||||
version = "0.1.52"
|
||||
version = "0.1.53"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1860,7 +1860,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.2.52"
|
||||
version = "0.2.53"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx 0.5.1",
|
||||
@ -1928,7 +1928,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-python-bindings"
|
||||
version = "0.3.52"
|
||||
version = "0.3.53"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kcl-lib",
|
||||
@ -1943,7 +1943,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-test-server"
|
||||
version = "0.1.52"
|
||||
version = "0.1.53"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hyper 0.14.32",
|
||||
@ -1956,7 +1956,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-to-core"
|
||||
version = "0.1.52"
|
||||
version = "0.1.53"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1970,7 +1970,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-wasm-lib"
|
||||
version = "0.1.52"
|
||||
version = "0.1.53"
|
||||
dependencies = [
|
||||
"bson",
|
||||
"console_error_panic_hook",
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
[package]
|
||||
name = "kcl-bumper"
|
||||
version = "0.1.52"
|
||||
version = "0.1.53"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/KittyCAD/modeling-api"
|
||||
rust-version = "1.76"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-derive-docs"
|
||||
description = "A tool for generating documentation from Rust derive macros"
|
||||
version = "0.1.52"
|
||||
version = "0.1.53"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm, None).await {
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -31,7 +31,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -31,7 +31,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -32,7 +32,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -32,7 +32,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -33,7 +33,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -33,7 +33,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -32,7 +32,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -32,7 +32,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -32,7 +32,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -32,7 +32,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -32,7 +32,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -32,7 +32,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -31,7 +31,13 @@ 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, None).await {
|
||||
let result = match crate::test_server::execute_and_snapshot(
|
||||
code,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(crate::errors::ExecError::Kcl(e)) => {
|
||||
return Err(miette::Report::new(crate::errors::Report {
|
||||
error: e.error,
|
||||
|
@ -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.52"
|
||||
version = "0.1.53"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "kcl-language-server-release"
|
||||
version = "0.1.52"
|
||||
version = "0.1.53"
|
||||
edition = "2021"
|
||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||
publish = false
|
||||
|
@ -2,7 +2,7 @@
|
||||
name = "kcl-language-server"
|
||||
description = "A language server for KCL."
|
||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||
version = "0.2.52"
|
||||
version = "0.2.53"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-lib"
|
||||
description = "KittyCAD Language implementation and tools"
|
||||
version = "0.2.52"
|
||||
version = "0.2.53"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -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().await?;
|
||||
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default()).await?;
|
||||
let mut exec_state = kcl_lib::ExecState::new(&ctx);
|
||||
ctx.run(black_box(&program), &mut exec_state).await?;
|
||||
ctx.close().await;
|
||||
|
@ -49,6 +49,45 @@ 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')
|
||||
|
@ -1,4 +0,0 @@
|
||||
@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
|> circle(center = [0, 0], radius = 20)
|
||||
extrude001 = extrude(sketch001, length = 10)
|
@ -1,5 +1,4 @@
|
||||
@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
const sketch001 = startSketchOn(XZ)
|
||||
|> startProfileAt([75.8, 317.2], %)
|
||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
@ -12,8 +11,8 @@ sketch001 = startSketchOn(XZ)
|
||||
], %, $yo)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|
||||
|> close()
|
||||
extrude001 = extrude(sketch001, length = 100)
|
||||
chamf = chamfer(
|
||||
const extrude001 = extrude(sketch001, length = 100)
|
||||
const chamf = chamfer(
|
||||
extrude001,
|
||||
length = 30,
|
||||
tags = [
|
||||
|
@ -1,5 +1,4 @@
|
||||
@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
const sketch001 = startSketchOn(XZ)
|
||||
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
@ -12,7 +11,7 @@ sketch001 = startSketchOn(XZ)
|
||||
], %, $yo)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|
||||
|> close()
|
||||
extrude001 = extrude(sketch001, length = 100)
|
||||
const extrude001 = extrude(sketch001, length = 100)
|
||||
|> chamfer(
|
||||
length = 30,
|
||||
tags = [
|
||||
|
@ -1,4 +1,4 @@
|
||||
const part001 = startSketchOn(XY)
|
||||
|> circle(center= [5, 5], radius= 10)
|
||||
|> extrude(length = 10)
|
||||
|> helixRevolutions({revolutions = 16, angleStart = 0}, %)
|
||||
|> helix(revolutions = 16, angleStart = 0, cylinder = %)
|
||||
|
@ -1,4 +1,4 @@
|
||||
const part001 = startSketchOn(XY)
|
||||
|> circle(center = [5, 5], radius = 10)
|
||||
|> extrude(length = -10)
|
||||
|> helixRevolutions({revolutions = 16, angleStart = 0}, %)
|
||||
|> helix(revolutions = 16, angleStart = 0, cylinder = %)
|
||||
|
@ -1,4 +1,4 @@
|
||||
const part001 = startSketchOn(XY)
|
||||
|> circle(center= [5, 5], radius= 10)
|
||||
|> extrude(length = 10)
|
||||
|> helixRevolutions({revolutions = 16, angleStart = 0, length = 3}, %)
|
||||
|> helix(revolutions = 16, angleStart = 0, length = 3, cylinder = %)
|
||||
|
@ -2,7 +2,7 @@ mod cache;
|
||||
|
||||
use kcl_lib::{
|
||||
test_server::{execute_and_export_step, execute_and_snapshot, execute_and_snapshot_no_auth},
|
||||
ExecError,
|
||||
ExecError, UnitLength,
|
||||
};
|
||||
|
||||
/// 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, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("different_planes_same_drawing", &result);
|
||||
}
|
||||
|
||||
@ -263,7 +263,7 @@ part004 = startSketchOn(YZ)
|
||||
|> close()
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("patterns_linear_basic_negative_axis", &result);
|
||||
}
|
||||
|
||||
@ -430,7 +430,7 @@ rectangle = startSketchOn(XY)
|
||||
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -586,15 +586,14 @@ async fn kcl_test_cube_mm() {
|
||||
myCube = cube([0,0], 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("cube_mm", &result);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn kcl_test_cube_cm() {
|
||||
let code = r#"@settings(defaultLengthUnit = cm)
|
||||
fn cube = (pos, scale) => {
|
||||
sg = startSketchOn('XY')
|
||||
let code = r#"fn cube = (pos, scale) => {
|
||||
sg = startSketchOn(XY)
|
||||
|> startProfileAt(pos, %)
|
||||
|> line(end = [0, scale])
|
||||
|> line(end = [scale, 0])
|
||||
@ -608,15 +607,14 @@ fn cube = (pos, scale) => {
|
||||
myCube = cube([0,0], 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Cm, None).await.unwrap();
|
||||
assert_out("cube_cm", &result);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn kcl_test_cube_m() {
|
||||
let code = r#"@settings(defaultLengthUnit = m)
|
||||
fn cube = (pos, scale) => {
|
||||
sg = startSketchOn('XY')
|
||||
let code = r#"fn cube = (pos, scale) => {
|
||||
sg = startSketchOn(XY)
|
||||
|> startProfileAt(pos, %)
|
||||
|> line(end = [0, scale])
|
||||
|> line(end = [scale, 0])
|
||||
@ -630,15 +628,14 @@ fn cube = (pos, scale) => {
|
||||
myCube = cube([0,0], 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::M, None).await.unwrap();
|
||||
assert_out("cube_m", &result);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn kcl_test_cube_in() {
|
||||
let code = r#"@settings(defaultLengthUnit = in)
|
||||
fn cube = (pos, scale) => {
|
||||
sg = startSketchOn('XY')
|
||||
let code = r#"fn cube = (pos, scale) => {
|
||||
sg = startSketchOn(XY)
|
||||
|> startProfileAt(pos, %)
|
||||
|> line(end = [0, scale])
|
||||
|> line(end = [scale, 0])
|
||||
@ -652,15 +649,14 @@ fn cube = (pos, scale) => {
|
||||
myCube = cube([0,0], 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::In, None).await.unwrap();
|
||||
assert_out("cube_in", &result);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn kcl_test_cube_ft() {
|
||||
let code = r#"@settings(defaultLengthUnit = ft)
|
||||
fn cube = (pos, scale) => {
|
||||
sg = startSketchOn('XY')
|
||||
let code = r#"fn cube = (pos, scale) => {
|
||||
sg = startSketchOn(XY)
|
||||
|> startProfileAt(pos, %)
|
||||
|> line(end = [0, scale])
|
||||
|> line(end = [scale, 0])
|
||||
@ -674,15 +670,14 @@ fn cube = (pos, scale) => {
|
||||
myCube = cube([0,0], 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Ft, None).await.unwrap();
|
||||
assert_out("cube_ft", &result);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn kcl_test_cube_yd() {
|
||||
let code = r#"@settings(defaultLengthUnit = yd)
|
||||
fn cube = (pos, scale) => {
|
||||
sg = startSketchOn('XY')
|
||||
let code = r#"fn cube = (pos, scale) => {
|
||||
sg = startSketchOn(XY)
|
||||
|> startProfileAt(pos, %)
|
||||
|> line(end = [0, scale])
|
||||
|> line(end = [scale, 0])
|
||||
@ -696,7 +691,7 @@ fn cube = (pos, scale) => {
|
||||
myCube = cube([0,0], 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Yd, None).await.unwrap();
|
||||
assert_out("cube_yd", &result);
|
||||
}
|
||||
|
||||
@ -724,7 +719,7 @@ part002 = startSketchOn(part001, part001.sketch.tags.here)
|
||||
|> extrude(length = 1)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
|
||||
let err = result.err().unwrap();
|
||||
let ExecError::Kcl(err) = err else {
|
||||
@ -768,7 +763,7 @@ part003 = startSketchOn(part002, "end")
|
||||
|> extrude(length = 5)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("sketch_on_face_of_face", &result);
|
||||
}
|
||||
|
||||
@ -785,7 +780,7 @@ async fn kcl_test_stdlib_kcl_error_right_code_path() {
|
||||
|> extrude(length = 2)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
let err = result.err().unwrap();
|
||||
let ExecError::Kcl(err) = err else {
|
||||
panic!("Expected KCL error, found {err}");
|
||||
@ -816,7 +811,7 @@ part002 = startSketchOn(part001, "end")
|
||||
|> extrude(length = 5)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("sketch_on_face_circle", &result);
|
||||
}
|
||||
|
||||
@ -858,7 +853,7 @@ part = rectShape([0, 0], 20, 20)
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
let err = result.err().unwrap();
|
||||
let ExecError::Kcl(err) = err else {
|
||||
panic!("Expected KCL error, found {err}");
|
||||
@ -885,7 +880,7 @@ async fn kcl_test_simple_revolve() {
|
||||
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("simple_revolve", &result);
|
||||
}
|
||||
|
||||
@ -905,7 +900,7 @@ async fn kcl_test_simple_revolve_uppercase() {
|
||||
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("simple_revolve_uppercase", &result);
|
||||
}
|
||||
|
||||
@ -925,7 +920,7 @@ async fn kcl_test_simple_revolve_negative() {
|
||||
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("simple_revolve_negative", &result);
|
||||
}
|
||||
|
||||
@ -945,7 +940,7 @@ async fn kcl_test_revolve_bad_angle_low() {
|
||||
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
assert!(result
|
||||
@ -971,7 +966,7 @@ async fn kcl_test_revolve_bad_angle_high() {
|
||||
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
assert!(result
|
||||
@ -997,7 +992,7 @@ async fn kcl_test_simple_revolve_custom_angle() {
|
||||
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("simple_revolve_custom_angle", &result);
|
||||
}
|
||||
|
||||
@ -1017,7 +1012,7 @@ async fn kcl_test_simple_revolve_custom_axis() {
|
||||
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("simple_revolve_custom_axis", &result);
|
||||
}
|
||||
|
||||
@ -1041,7 +1036,7 @@ sketch001 = startSketchOn(box, "end")
|
||||
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("revolve_on_edge", &result);
|
||||
}
|
||||
|
||||
@ -1065,7 +1060,7 @@ sketch001 = startSketchOn(box, revolveAxis)
|
||||
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
|
||||
result.unwrap_err();
|
||||
//this fails right now, but slightly differently, lets just say its enough for it to fail - mike
|
||||
@ -1093,7 +1088,7 @@ sketch001 = startSketchOn(box, "END")
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("revolve_on_face_circle_edge", &result);
|
||||
}
|
||||
|
||||
@ -1115,7 +1110,7 @@ sketch001 = startSketchOn(box, "END")
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("revolve_on_face_circle", &result);
|
||||
}
|
||||
|
||||
@ -1141,7 +1136,7 @@ sketch001 = startSketchOn(box, "end")
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("revolve_on_face", &result);
|
||||
}
|
||||
|
||||
@ -1155,7 +1150,7 @@ async fn kcl_test_basic_revolve_circle() {
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("basic_revolve_circle", &result);
|
||||
}
|
||||
|
||||
@ -1182,7 +1177,7 @@ part002 = startSketchOn(part001, 'end')
|
||||
|> extrude(length = 5)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("simple_revolve_sketch_on_edge", &result);
|
||||
}
|
||||
|
||||
@ -1245,7 +1240,7 @@ plumbus1 = circle1
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("plumbus_fillets", &result);
|
||||
}
|
||||
|
||||
@ -1253,7 +1248,7 @@ plumbus1 = circle1
|
||||
async fn kcl_test_empty_file_is_ok() {
|
||||
let code = r#""#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
result.unwrap();
|
||||
}
|
||||
|
||||
@ -1283,7 +1278,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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("member_expression_in_params", &result);
|
||||
}
|
||||
|
||||
@ -1328,7 +1323,7 @@ bracket = startSketchOn(XY)
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
result.unwrap();
|
||||
}
|
||||
|
||||
@ -1348,7 +1343,7 @@ secondSketch = startSketchOn(part001, '')
|
||||
|> extrude(length = 20)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1379,7 +1374,7 @@ extrusion = startSketchOn(XY)
|
||||
|> extrude(length = height)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1412,7 +1407,7 @@ sketch001 = [profile001, profile002]
|
||||
extrude(sketch001, length = 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("array_of_sketches", &result);
|
||||
}
|
||||
|
||||
@ -1449,7 +1444,7 @@ pattn1 = patternLinear3d(
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("pattern3d_array_of_extrudes", &result);
|
||||
}
|
||||
|
||||
@ -1497,7 +1492,7 @@ baseExtrusion = extrude(sketch001, length = width)
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("fillets_referencing_other_fillets", &result);
|
||||
}
|
||||
|
||||
@ -1545,7 +1540,7 @@ baseExtrusion = extrude(sketch001, length = width)
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("chamfers_referencing_other_chamfers", &result);
|
||||
}
|
||||
|
||||
@ -1565,7 +1560,7 @@ async fn kcl_test_shell_with_tag() {
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("shell_with_tag", &result);
|
||||
}
|
||||
|
||||
@ -1596,7 +1591,7 @@ pattn1 = patternLinear3d(
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("linear_pattern3d_filleted_sketch", &result);
|
||||
}
|
||||
|
||||
@ -1623,7 +1618,7 @@ pattn2 = patternCircular3d(part001, axis = [0,0, 1], center = [-20, -20, -20], i
|
||||
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("circular_pattern3d_filleted_sketch", &result);
|
||||
}
|
||||
|
||||
@ -1649,7 +1644,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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("circular_pattern3d_chamfered_sketch", &result);
|
||||
}
|
||||
|
||||
@ -1676,7 +1671,7 @@ part001 = cube([0,0], 20)
|
||||
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
let err = result.err().unwrap();
|
||||
let ExecError::Kcl(err) = err else {
|
||||
panic!("Expected KCL error, found {err}");
|
||||
@ -1706,7 +1701,7 @@ async fn kcl_test_duplicate_tags_should_error() {
|
||||
let p = triangle(200)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1717,49 +1712,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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, 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, None).await.unwrap();
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await.unwrap();
|
||||
assert_out("extrude-custom-plane", &result);
|
||||
}
|
||||
|
||||
@ -1781,7 +1776,7 @@ async fn kcl_test_arc_error_same_start_end() {
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1801,7 +1796,7 @@ async fn kcl_test_angled_line_to_x_90() {
|
||||
example = extrude(exampleSketch, length = 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1821,7 +1816,7 @@ async fn kcl_test_angled_line_to_x_270() {
|
||||
example = extrude(exampleSketch, length = 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1841,7 +1836,7 @@ async fn kcl_test_angled_line_to_y_0() {
|
||||
example = extrude(exampleSketch, length = 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1861,7 +1856,7 @@ async fn kcl_test_angled_line_to_y_180() {
|
||||
example = extrude(exampleSketch, length = 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1881,7 +1876,7 @@ async fn kcl_test_angled_line_of_x_length_90() {
|
||||
extrusion = extrude(sketch001, length = 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1901,7 +1896,7 @@ async fn kcl_test_angled_line_of_x_length_270() {
|
||||
extrusion = extrude(sketch001, length = 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1923,7 +1918,7 @@ async fn kcl_test_angled_line_of_y_length_0() {
|
||||
example = extrude(exampleSketch, length = 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1945,7 +1940,7 @@ async fn kcl_test_angled_line_of_y_length_180() {
|
||||
example = extrude(exampleSketch, length = 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1967,7 +1962,7 @@ async fn kcl_test_angled_line_of_y_length_negative_180() {
|
||||
example = extrude(exampleSketch, length = 10)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -1984,7 +1979,7 @@ async fn kcl_test_error_inside_fn_also_has_source_range_of_call_site() {
|
||||
someFunction('INVALID')
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -2005,7 +2000,7 @@ async fn kcl_test_error_inside_fn_also_has_source_range_of_call_site_recursive()
|
||||
someFunction('INVALID')
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
@ -2029,7 +2024,7 @@ async fn kcl_test_error_no_auth_websocket() {
|
||||
)
|
||||
"#;
|
||||
|
||||
let result = execute_and_snapshot_no_auth(code, None).await;
|
||||
let result = execute_and_snapshot_no_auth(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
assert!(result
|
||||
.err()
|
||||
@ -2055,7 +2050,9 @@ sketch000 = startSketchOn(XY)
|
||||
|> line(end = [0, innerDiameter / 2])
|
||||
"#;
|
||||
|
||||
let ctx = kcl_lib::ExecutorContext::new_with_default_client().await.unwrap();
|
||||
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default())
|
||||
.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();
|
||||
@ -2078,7 +2075,9 @@ 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().await.unwrap();
|
||||
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default())
|
||||
.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();
|
||||
@ -2096,7 +2095,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, None).await;
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
|
||||
let err = match result.err() {
|
||||
Some(x) => match x {
|
||||
@ -2115,7 +2114,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, None).await.unwrap();
|
||||
let (_, _, files) = execute_and_export_step(code, UnitLength::Mm, None).await.unwrap();
|
||||
for file in files {
|
||||
expectorate::assert_contents(
|
||||
format!("e2e/executor/outputs/helix_defaults_negative_extrude_{}", file.name),
|
||||
|
@ -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().await?;
|
||||
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default()).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;
|
||||
|
@ -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().await?;
|
||||
let ctx = ExecutorContext::new_with_default_client(crate::UnitLength::Mm).await?;
|
||||
let mut exec_state = crate::execution::ExecState::new(&ctx);
|
||||
ctx.run(&program, &mut exec_state).await?;
|
||||
Ok(())
|
||||
|
@ -897,17 +897,20 @@ 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, 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, 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,
|
||||
};
|
||||
twenty_twenty::assert_image(
|
||||
format!("tests/outputs/serial_test_example_{}{i}.png", d.example_name()),
|
||||
&result,
|
||||
|
@ -127,13 +127,14 @@ 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.type_ == "SolidOrSketchOrImportedGeometry")
|
||||
&& (self.required || self.include_in_snippet)
|
||||
{
|
||||
return Ok(Some((index, format!("{label}${{{}:{}}}", index, "%"))));
|
||||
} else if (self.type_ == "TagDeclarator" || self.type_ == "TagNode") && self.required {
|
||||
@ -1094,16 +1095,38 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
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();
|
||||
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();
|
||||
assert_eq!(
|
||||
snippet,
|
||||
r#"helixRevolutions({
|
||||
revolutions = ${0:3.14},
|
||||
angleStart = ${1:3.14},
|
||||
ccw = ${2:false},
|
||||
}, ${3:%})${}"#
|
||||
r#"getCommonEdge(faces = [{
|
||||
value = ${0:"string"},
|
||||
}])${}"#
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -176,10 +176,6 @@ 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?;
|
||||
@ -256,6 +252,9 @@ 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?;
|
||||
|
||||
|
@ -97,6 +97,15 @@ 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;
|
||||
@ -415,6 +424,50 @@ 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() {
|
||||
@ -562,42 +615,4 @@ 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
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,12 @@ 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(path.std_path(), exec_state.stack().memory.clone(), Some(module_id));
|
||||
let mut local_state = ModuleState::new(
|
||||
&self.settings,
|
||||
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);
|
||||
}
|
||||
|
@ -152,6 +152,8 @@ 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>,
|
||||
|
@ -39,6 +39,7 @@ 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,
|
||||
@ -264,6 +265,8 @@ 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.
|
||||
@ -284,6 +287,7 @@ pub struct ExecutorSettings {
|
||||
impl Default for ExecutorSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
units: Default::default(),
|
||||
highlight_edges: true,
|
||||
enable_ssao: false,
|
||||
show_grid: false,
|
||||
@ -297,6 +301,7 @@ 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,
|
||||
@ -310,6 +315,7 @@ 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(),
|
||||
@ -323,6 +329,7 @@ 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,
|
||||
@ -336,6 +343,7 @@ 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(),
|
||||
@ -468,17 +476,26 @@ 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() -> Result<Self> {
|
||||
pub async fn new_with_default_client(units: UnitLength) -> Result<Self> {
|
||||
// Create the client.
|
||||
let ctx = Self::new_with_client(Default::default(), None, None).await?;
|
||||
let ctx = Self::new_with_client(
|
||||
ExecutorSettings {
|
||||
units,
|
||||
..Default::default()
|
||||
},
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
Ok(ctx)
|
||||
}
|
||||
|
||||
/// For executing unit tests.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub async fn new_for_unit_test(engine_addr: Option<String>) -> Result<Self> {
|
||||
pub async fn new_for_unit_test(units: UnitLength, engine_addr: Option<String>) -> Result<Self> {
|
||||
let ctx = ExecutorContext::new_with_client(
|
||||
ExecutorSettings {
|
||||
units,
|
||||
highlight_edges: true,
|
||||
enable_ssao: false,
|
||||
show_grid: false,
|
||||
@ -829,6 +846,11 @@ 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.
|
||||
@ -1901,7 +1923,9 @@ let w = f() + f()
|
||||
)
|
||||
"#;
|
||||
|
||||
let ctx = crate::test_server::new_context(true, None).await.unwrap();
|
||||
let ctx = crate::test_server::new_context(UnitLength::Mm, true, None)
|
||||
.await
|
||||
.unwrap();
|
||||
let old_program = crate::Program::parse_no_errs(code).unwrap();
|
||||
|
||||
// Execute the program.
|
||||
@ -1954,7 +1978,9 @@ let w = f() + f()
|
||||
)
|
||||
"#;
|
||||
|
||||
let mut ctx = crate::test_server::new_context(true, None).await.unwrap();
|
||||
let mut ctx = crate::test_server::new_context(UnitLength::Mm, true, None)
|
||||
.await
|
||||
.unwrap();
|
||||
let old_program = crate::Program::parse_no_errs(code).unwrap();
|
||||
|
||||
// Execute the program.
|
||||
@ -1990,7 +2016,7 @@ let w = f() + f()
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn mock_after_not_mock() {
|
||||
let ctx = ExecutorContext::new_with_default_client().await.unwrap();
|
||||
let ctx = ExecutorContext::new_with_default_client(UnitLength::Mm).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);
|
||||
|
@ -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(None, ProgramMemory::new(), Default::default()),
|
||||
mod_local: ModuleState::new(&exec_context.settings, None, ProgramMemory::new(), Default::default()),
|
||||
exec_context: Some(exec_context.clone()),
|
||||
}
|
||||
}
|
||||
@ -88,7 +88,7 @@ impl ExecState {
|
||||
|
||||
*self = ExecState {
|
||||
global,
|
||||
mod_local: ModuleState::new(None, ProgramMemory::new(), Default::default()),
|
||||
mod_local: ModuleState::new(&exec_context.settings, None, ProgramMemory::new(), Default::default()),
|
||||
exec_context: Some(exec_context.clone()),
|
||||
};
|
||||
}
|
||||
@ -285,14 +285,19 @@ impl GlobalState {
|
||||
}
|
||||
|
||||
impl ModuleState {
|
||||
pub(super) fn new(std_path: Option<String>, memory: Arc<ProgramMemory>, module_id: Option<ModuleId>) -> Self {
|
||||
pub(super) fn new(
|
||||
exec_settings: &ExecutorSettings,
|
||||
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: Default::default(),
|
||||
default_length_units: exec_settings.units.into(),
|
||||
default_angle_units: Default::default(),
|
||||
std_path,
|
||||
},
|
||||
@ -300,7 +305,7 @@ impl ModuleState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq, ts_rs::TS, JsonSchema)]
|
||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MetaSettings {
|
||||
|
@ -195,10 +195,6 @@ 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()
|
||||
}
|
||||
|
@ -812,6 +812,56 @@ 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,
|
||||
|
@ -42,6 +42,7 @@ 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();
|
||||
|
||||
|
@ -2320,6 +2320,78 @@ 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();
|
||||
@ -2647,6 +2719,141 @@ 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();
|
||||
@ -2678,6 +2885,23 @@ 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());
|
||||
@ -2694,6 +2918,23 @@ 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();
|
||||
|
||||
@ -2711,6 +2952,23 @@ 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());
|
||||
|
@ -346,29 +346,6 @@ 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 {
|
||||
@ -3503,37 +3480,6 @@ 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() {
|
||||
|
@ -60,8 +60,11 @@ pub fn parse_tokens(mut tokens: TokenStream) -> ParseResult {
|
||||
return Node::<Program>::default().into();
|
||||
}
|
||||
|
||||
// Check all the tokens are whitespace.
|
||||
if tokens.iter().all(|t| t.token_type.is_whitespace()) {
|
||||
// Check all the tokens are whitespace or comments.
|
||||
if tokens
|
||||
.iter()
|
||||
.all(|t| t.token_type.is_whitespace() || t.token_type.is_comment())
|
||||
{
|
||||
return Node::<Program>::default().into();
|
||||
}
|
||||
|
||||
|
@ -153,9 +153,13 @@ 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, Some(test.input_dir.join(&test.entry_point)), export_step)
|
||||
.await;
|
||||
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;
|
||||
match exec_res {
|
||||
Ok((exec_state, env_ref, png, step)) => {
|
||||
let fail_path = test.output_dir.join("execution_error.snap");
|
||||
|
@ -1258,23 +1258,6 @@ 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() {
|
||||
|
@ -165,7 +165,7 @@ async fn inner_fillet(
|
||||
edge_id,
|
||||
object_id: solid.id,
|
||||
radius: LengthUnit(radius),
|
||||
tolerance: LengthUnit(tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into()))),
|
||||
tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
|
||||
cut_type: CutType::Fillet,
|
||||
// We make this a none so that we can remove it in the future.
|
||||
face_id: None,
|
||||
|
@ -4,8 +4,6 @@ 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,
|
||||
@ -18,11 +16,71 @@ 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("radius")?;
|
||||
let axis = args.get_kw_arg("axis")?;
|
||||
let radius = args.get_kw_arg_opt("radius")?;
|
||||
let axis = args.get_kw_arg_opt("axis")?;
|
||||
let length = args.get_kw_arg_opt("length")?;
|
||||
let cylinder = args.get_kw_arg_opt("cylinder")?;
|
||||
|
||||
let value = inner_helix(revolutions, angle_start, ccw, radius, axis, length, exec_state, args).await?;
|
||||
// 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?;
|
||||
Ok(KclValue::Helix { value })
|
||||
}
|
||||
|
||||
@ -88,6 +146,23 @@ 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,
|
||||
@ -96,9 +171,10 @@ 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."},
|
||||
axis = { docs = "Axis to use for the helix."},
|
||||
radius = { docs = "Radius of the helix.", include_in_snippet = true},
|
||||
axis = { docs = "Axis to use for the helix.", include_in_snippet = true},
|
||||
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,
|
||||
}]
|
||||
@ -107,9 +183,10 @@ async fn inner_helix(
|
||||
revolutions: f64,
|
||||
angle_start: f64,
|
||||
ccw: Option<bool>,
|
||||
radius: f64,
|
||||
axis: Axis3dOrEdgeReference,
|
||||
radius: Option<f64>,
|
||||
axis: Option<Axis3dOrEdgeReference>,
|
||||
length: Option<f64>,
|
||||
cylinder: Option<Solid>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Box<HelixValue>, KclError> {
|
||||
@ -120,6 +197,7 @@ 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()],
|
||||
@ -129,113 +207,63 @@ async fn inner_helix(
|
||||
return Ok(helix_result);
|
||||
}
|
||||
|
||||
match axis {
|
||||
Axis3dOrEdgeReference::Axis(axis) => {
|
||||
let (axis, origin) = axis.axis_and_origin()?;
|
||||
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()?;
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
@ -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_else(|| default_tolerance(&exec_state.length_unit().into()))),
|
||||
tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
|
||||
v_degree,
|
||||
}),
|
||||
)
|
||||
|
@ -114,7 +114,6 @@ 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),
|
||||
|
@ -273,9 +273,7 @@ async fn inner_revolve(
|
||||
target: sketch.id.into(),
|
||||
axis,
|
||||
origin,
|
||||
tolerance: LengthUnit(
|
||||
tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into())),
|
||||
),
|
||||
tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
|
||||
axis_is_2d: true,
|
||||
}),
|
||||
)
|
||||
@ -289,9 +287,7 @@ async fn inner_revolve(
|
||||
angle,
|
||||
target: sketch.id.into(),
|
||||
edge_id,
|
||||
tolerance: LengthUnit(
|
||||
tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into())),
|
||||
),
|
||||
tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
@ -192,7 +192,7 @@ async fn inner_sweep(
|
||||
target: sketch.id.into(),
|
||||
trajectory,
|
||||
sectional: sectional.unwrap_or(false),
|
||||
tolerance: LengthUnit(tolerance.unwrap_or_else(|| default_tolerance(&exec_state.length_unit().into()))),
|
||||
tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
@ -6,6 +6,7 @@ use crate::{
|
||||
engine::new_zoo_client,
|
||||
errors::ExecErrorWithState,
|
||||
execution::{EnvironmentRef, ExecState, ExecutorContext, ExecutorSettings},
|
||||
settings::types::UnitLength,
|
||||
ConnectionError, ExecError, KclError, KclErrorWithOutputs, Program,
|
||||
};
|
||||
|
||||
@ -18,8 +19,12 @@ 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, current_file: Option<PathBuf>) -> Result<image::DynamicImage, ExecError> {
|
||||
let ctx = new_context(true, current_file).await?;
|
||||
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?;
|
||||
let program = Program::parse_no_errs(code).map_err(KclErrorWithOutputs::no_outputs)?;
|
||||
let res = do_execute_and_snapshot(&ctx, program)
|
||||
.await
|
||||
@ -33,10 +38,11 @@ pub async fn execute_and_snapshot(code: &str, current_file: Option<PathBuf>) ->
|
||||
/// 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(true, current_file).await?;
|
||||
let ctx = new_context(units, true, current_file).await?;
|
||||
let (exec_state, env, img) = do_execute_and_snapshot(&ctx, ast).await?;
|
||||
let mut step = None;
|
||||
if with_export_step {
|
||||
@ -58,9 +64,10 @@ 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(false, current_file).await?;
|
||||
let ctx = new_context(units, 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
|
||||
@ -104,7 +111,11 @@ async fn do_execute_and_snapshot(
|
||||
Ok((exec_state, result.0, img))
|
||||
}
|
||||
|
||||
pub async fn new_context(with_auth: bool, current_file: Option<PathBuf>) -> Result<ExecutorContext, ConnectionError> {
|
||||
pub async fn new_context(
|
||||
units: UnitLength,
|
||||
with_auth: bool,
|
||||
current_file: Option<PathBuf>,
|
||||
) -> Result<ExecutorContext, ConnectionError> {
|
||||
let mut client = new_zoo_client(if with_auth { None } else { Some("bad_token".to_string()) }, None)
|
||||
.map_err(ConnectionError::CouldNotMakeClient)?;
|
||||
if !with_auth {
|
||||
@ -115,6 +126,7 @@ pub async fn new_context(with_auth: bool, current_file: Option<PathBuf>) -> Resu
|
||||
}
|
||||
|
||||
let mut settings = ExecutorSettings {
|
||||
units,
|
||||
highlight_edges: true,
|
||||
enable_ssao: false,
|
||||
show_grid: false,
|
||||
@ -133,6 +145,7 @@ pub async fn new_context(with_auth: bool, current_file: Option<PathBuf>) -> Resu
|
||||
|
||||
pub async fn execute_and_export_step(
|
||||
code: &str,
|
||||
units: UnitLength,
|
||||
current_file: Option<PathBuf>,
|
||||
) -> Result<
|
||||
(
|
||||
@ -142,7 +155,7 @@ pub async fn execute_and_export_step(
|
||||
),
|
||||
ExecErrorWithState,
|
||||
> {
|
||||
let ctx = new_context(true, current_file).await?;
|
||||
let ctx = new_context(units, 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()))?;
|
||||
|
@ -2039,15 +2039,6 @@ 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#"
|
||||
|
@ -11,6 +11,14 @@ description: Artifact commands add_lots.kcl
|
||||
"hidden": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "set_scene_units",
|
||||
"unit": "mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
|
@ -11,6 +11,14 @@ description: Artifact commands angled_line.kcl
|
||||
"hidden": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "set_scene_units",
|
||||
"unit": "mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
|
@ -11,6 +11,14 @@ description: Artifact commands argument_error.kcl
|
||||
"hidden": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "set_scene_units",
|
||||
"unit": "mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
|
@ -11,6 +11,14 @@ description: Artifact commands array_elem_pop.kcl
|
||||
"hidden": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "set_scene_units",
|
||||
"unit": "mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
|