diff --git a/e2e/playwright/sketch-tests.spec.ts b/e2e/playwright/sketch-tests.spec.ts index 3064423bc..3d66a92c9 100644 --- a/e2e/playwright/sketch-tests.spec.ts +++ b/e2e/playwright/sketch-tests.spec.ts @@ -1115,6 +1115,102 @@ sketch002 = startSketchOn(extrude001, 'END') ).toHaveAttribute('aria-pressed', 'true') }).toPass({ timeout: 40_000, intervals: [1_000] }) }) + + test('Can sketch on face when user defined function was used in the sketch', async ({ + page, + }) => { + const u = await getUtils(page) + await page.setViewportSize({ width: 1200, height: 500 }) + + // Checking for a regression that performs a sketch when a user defined function + // is declared at the top of the file and used in the sketch that is being drawn on. + // fn in2mm is declared at the top of the file and used rail which does a an extrusion with the function. + + await page.addInitScript(async () => { + localStorage.setItem( + 'persistCode', + `fn in2mm = (inches) => { + return inches * 25.4 +} + +const railTop = in2mm(.748) +const railSide = in2mm(.024) +const railBaseWidth = in2mm(.612) +const railWideWidth = in2mm(.835) +const railBaseLength = in2mm(.200) +const railClampable = in2mm(.200) + +const rail = startSketchOn('XZ') + |> startProfileAt([ + -railTop / 2, + railClampable + railBaseLength + ], %) + |> lineTo([ + railTop / 2, + railClampable + railBaseLength + ], %) + |> lineTo([ + railWideWidth / 2, + railClampable / 2 + railBaseLength + ], %, $seg01) + |> lineTo([railTop / 2, railBaseLength], %) + |> lineTo([railBaseWidth / 2, railBaseLength], %) + |> lineTo([railBaseWidth / 2, 0], %) + |> lineTo([-railBaseWidth / 2, 0], %) + |> lineTo([-railBaseWidth / 2, railBaseLength], %) + |> lineTo([-railTop / 2, railBaseLength], %) + |> lineTo([ + -railWideWidth / 2, + railClampable / 2 + railBaseLength + ], %) + |> lineTo([ + -railTop / 2, + railClampable + railBaseLength + ], %) + |> close(%) + |> extrude(in2mm(2), %)` + ) + }) + + const center = { x: 600, y: 250 } + const rectangleSize = 20 + await u.waitForAuthSkipAppStart() + + // Start a sketch + await page.getByRole('button', { name: 'Start Sketch' }).click() + + // Click the top face of this rail + await page.mouse.click(center.x, center.y) + await page.waitForTimeout(1000) + + // Draw a rectangle + // top left + await page.mouse.click(center.x - rectangleSize, center.y - rectangleSize) + await page.waitForTimeout(250) + // top right + await page.mouse.click(center.x + rectangleSize, center.y - rectangleSize) + await page.waitForTimeout(250) + + // bottom right + await page.mouse.click(center.x + rectangleSize, center.y + rectangleSize) + await page.waitForTimeout(250) + + // bottom left + await page.mouse.click(center.x - rectangleSize, center.y + rectangleSize) + await page.waitForTimeout(250) + + // top left + await page.mouse.click(center.x - rectangleSize, center.y - rectangleSize) + await page.waitForTimeout(250) + + // exit sketch + await page.getByRole('button', { name: 'Exit Sketch' }).click() + + // Check execution is done + await u.openDebugPanel() + await u.expectCmdLog('[data-message-type="execution-done"]') + await u.closeDebugPanel() + }) }) test2.describe('Sketch mode should be toleratant to syntax errors', () => { diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-1-Google-Chrome-win32.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-1-Google-Chrome-win32.png index 02bbd03d9..d072cf76e 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-1-Google-Chrome-win32.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-1-Google-Chrome-win32.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-2-Google-Chrome-win32.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-2-Google-Chrome-win32.png index 1b6a2353c..0a291d1b7 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-2-Google-Chrome-win32.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-2-Google-Chrome-win32.png differ diff --git a/src/editor/plugins/lsp/kcl/highlight.ts b/src/editor/plugins/lsp/kcl/highlight.ts index 122d5778f..54dab6966 100644 --- a/src/editor/plugins/lsp/kcl/highlight.ts +++ b/src/editor/plugins/lsp/kcl/highlight.ts @@ -2,6 +2,7 @@ import { styleTags, tags as t } from '@lezer/highlight' export const kclHighlight = styleTags({ 'fn var let const': t.definitionKeyword, + 'if else': t.controlKeyword, return: t.controlKeyword, 'true false': t.bool, nil: t.null, diff --git a/src/editor/plugins/lsp/kcl/kcl.grammar b/src/editor/plugins/lsp/kcl/kcl.grammar index 010196a9d..3de93e787 100644 --- a/src/editor/plugins/lsp/kcl/kcl.grammar +++ b/src/editor/plugins/lsp/kcl/kcl.grammar @@ -40,6 +40,7 @@ expression[@isGroup=Expression] { } | UnaryExpression { UnaryOp expression } | ParenthesizedExpression { "(" expression ")" } | + IfExpression { kw<"if"> expression Body kw<"else"> Body } | CallExpression { expression !call ArgumentList } | ArrayExpression { "[" commaSep "]" } | ObjectExpression { "{" commaSep "}" } |