Merge remote-tracking branch 'origin/main' into paultag/import

This commit is contained in:
Paul Tagliamonte
2025-04-02 11:36:59 -04:00
421 changed files with 5829 additions and 5750 deletions

103
.eslintrc
View File

@ -1,103 +0,0 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": [
"react-perf",
"css-modules",
"jest",
"jsx-a11y",
"react",
"react-hooks",
"suggest-no-throw",
"testing-library",
"@typescript-eslint"
],
"extends": [
"plugin:css-modules/recommended",
"plugin:jsx-a11y/recommended",
"plugin:react-hooks/recommended"
],
"rules": {
"no-array-constructor": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-array-delete": "error",
"@typescript-eslint/no-duplicate-enum-values": "error",
"@typescript-eslint/no-duplicate-type-constituents": "error",
"@typescript-eslint/no-empty-object-type": "error",
"@typescript-eslint/no-extra-non-null-assertion": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-for-in-array": "error",
"no-implied-eval": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-implied-eval": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
"@typescript-eslint/no-redundant-type-constituents": "error",
"@typescript-eslint/no-this-alias": "warn",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-unnecessary-type-constraint": "error",
"no-unused-vars": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-unused-vars": ["error", {
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_",
"ignoreRestSiblings": true,
"vars": "all",
"args": "none"
}],
"@typescript-eslint/no-unsafe-unary-minus": "error",
"@typescript-eslint/no-wrapper-object-types": "error",
"no-throw-literal": "off", // Use @typescript-eslint/only-throw-error instead.
"@typescript-eslint/only-throw-error": "error",
"@typescript-eslint/prefer-as-const": "warn",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-autofocus": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off",
"no-restricted-globals": [
"error",
{
"name": "isNaN",
"message": "Use Number.isNaN() instead."
}
],
"no-restricted-syntax": [
"error",
{
"selector": "CallExpression[callee.object.name='Array'][callee.property.name='isArray']",
"message": "Use isArray() in lib/utils.ts instead of Array.isArray()."
}
],
"semi": [
"error",
"never"
],
"react-hooks/exhaustive-deps": "off",
"suggest-no-throw/suggest-no-throw": "error"
},
"overrides": [
{
"files": ["e2e/**/*.ts"], // Update the pattern based on your file structure
"extends": [
"plugin:testing-library/react"
],
"rules": {
"suggest-no-throw/suggest-no-throw": "off",
"testing-library/prefer-screen-queries": "off",
"jest/valid-expect": "off"
}
},
{
"files": ["src/**/*.test.ts"],
"extends": [
"plugin:testing-library/react"
],
"rules": {
"suggest-no-throw/suggest-no-throw": "off"
}
}
]
}

127
.eslintrc.json Normal file
View File

@ -0,0 +1,127 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": [
"react-perf",
"css-modules",
"jest",
"jsx-a11y",
"react",
"react-hooks",
"suggest-no-throw",
"testing-library",
"@typescript-eslint"
],
"extends": [
"plugin:css-modules/recommended",
"plugin:jsx-a11y/recommended",
"plugin:react-hooks/recommended"
],
"rules": {
"no-array-constructor": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-array-delete": "error",
"@typescript-eslint/no-duplicate-enum-values": "error",
"@typescript-eslint/no-duplicate-type-constituents": "error",
"@typescript-eslint/no-empty-object-type": "error",
"@typescript-eslint/no-extra-non-null-assertion": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-for-in-array": "error",
"no-implied-eval": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-implied-eval": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
"@typescript-eslint/no-redundant-type-constituents": "error",
"@typescript-eslint/no-this-alias": "warn",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-unnecessary-type-constraint": "error",
"no-unused-vars": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-unused-vars": [
"error",
{
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_",
"ignoreRestSiblings": true,
"vars": "all",
"args": "none"
}
],
"@typescript-eslint/no-unsafe-unary-minus": "error",
"@typescript-eslint/no-wrapper-object-types": "error",
"no-throw-literal": "off", // Use @typescript-eslint/only-throw-error instead.
"@typescript-eslint/only-throw-error": "error",
"@typescript-eslint/prefer-as-const": "warn",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/consistent-type-imports": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-autofocus": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off",
"no-restricted-globals": [
"error",
{
"name": "isNaN",
"message": "Use Number.isNaN() instead."
}
],
"no-restricted-syntax": [
"error",
{
"selector": "CallExpression[callee.object.name='Array'][callee.property.name='isArray']",
"message": "Use isArray() in lib/utils.ts instead of Array.isArray()."
},
{
"selector": "CallExpression[callee.object.name='TOML'][callee.property.name='stringify']",
"message": "Do not use TOML.stringify directly. Use the wrappers in test-utils instead like settingsToToml."
},
{
"selector": "CallExpression[callee.object.name='TOML'][callee.property.name='parse']",
"message": "Do not use TOML.parse directly. Use the wrappers in test-utils instead like tomlToSettings."
}
],
"no-restricted-imports": [
"error",
{
"patterns": [
// Restrict all relative imports except for .css files.
{
"group": ["./*", "../*", "!./*.css", "!../*.css"],
"message": "Use absolute imports instead."
}
]
}
],
"semi": ["error", "never"],
"react-hooks/exhaustive-deps": "off",
"suggest-no-throw/suggest-no-throw": "error"
},
"overrides": [
{
"files": ["e2e/**/*.ts"], // Update the pattern based on your file structure
"extends": ["plugin:testing-library/react"],
"rules": {
"suggest-no-throw/suggest-no-throw": "off",
"testing-library/prefer-screen-queries": "off",
"jest/valid-expect": "off"
}
},
{
"files": ["src/**/*.test.ts"],
"extends": ["plugin:testing-library/react"],
"rules": {
"suggest-no-throw/suggest-no-throw": "off"
}
},
{
"files": ["packages/**/*.ts", "rust/**/*.ts"],
"extends": [],
"rules": {
"no-restricted-imports": "off"
}
}
]
}

File diff suppressed because one or more lines are too long

View File

@ -267784,9 +267784,10 @@
"type": "number", "type": "number",
"schema": { "schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema", "$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double", "title": "Nullable_double",
"type": "number", "type": "number",
"format": "double", "format": "double",
"nullable": true,
"definitions": { "definitions": {
"Solid": { "Solid": {
"type": "object", "type": "object",
@ -269371,9 +269372,9 @@
} }
} }
}, },
"required": true, "required": false,
"includeInSnippet": true, "includeInSnippet": true,
"description": "The scale factor for the x axis.", "description": "The scale factor for the x axis. Default is 1 if not provided.",
"labelRequired": true "labelRequired": true
}, },
{ {
@ -269381,9 +269382,10 @@
"type": "number", "type": "number",
"schema": { "schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema", "$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double", "title": "Nullable_double",
"type": "number", "type": "number",
"format": "double", "format": "double",
"nullable": true,
"definitions": { "definitions": {
"Solid": { "Solid": {
"type": "object", "type": "object",
@ -270968,9 +270970,9 @@
} }
} }
}, },
"required": true, "required": false,
"includeInSnippet": true, "includeInSnippet": true,
"description": "The scale factor for the y axis.", "description": "The scale factor for the y axis. Default is 1 if not provided.",
"labelRequired": true "labelRequired": true
}, },
{ {
@ -270978,9 +270980,10 @@
"type": "number", "type": "number",
"schema": { "schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema", "$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double", "title": "Nullable_double",
"type": "number", "type": "number",
"format": "double", "format": "double",
"nullable": true,
"definitions": { "definitions": {
"Solid": { "Solid": {
"type": "object", "type": "object",
@ -272565,9 +272568,9 @@
} }
} }
}, },
"required": true, "required": false,
"includeInSnippet": true, "includeInSnippet": true,
"description": "The scale factor for the z axis.", "description": "The scale factor for the z axis. Default is 1 if not provided.",
"labelRequired": true "labelRequired": true
}, },
{ {
@ -275836,9 +275839,9 @@
"unpublished": false, "unpublished": false,
"deprecated": false, "deprecated": false,
"examples": [ "examples": [
"// Scale a pipe.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> scale(x = 1.0, y = 1.0, z = 2.5)", "// Scale a pipe.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> scale(z = 2.5)",
"// Scale an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> scale(x = 1.0, y = 1.0, z = 2.5)", "// Scale an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> scale(z = 2.5)",
"// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Scale the sweep.\nscale(\n parts,\n x = 1.0,\n y = 1.0,\n z = 0.5,\n)" "// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Scale the sweep.\nscale(parts, z = 0.5)"
] ]
}, },
{ {
@ -326051,9 +326054,10 @@
"type": "number", "type": "number",
"schema": { "schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema", "$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double", "title": "Nullable_double",
"type": "number", "type": "number",
"format": "double", "format": "double",
"nullable": true,
"definitions": { "definitions": {
"Solid": { "Solid": {
"type": "object", "type": "object",
@ -327638,9 +327642,9 @@
} }
} }
}, },
"required": true, "required": false,
"includeInSnippet": true, "includeInSnippet": true,
"description": "The amount to move the solid or sketch along the x axis.", "description": "The amount to move the solid or sketch along the x axis. Defaults to 0 if not provided.",
"labelRequired": true "labelRequired": true
}, },
{ {
@ -327648,9 +327652,10 @@
"type": "number", "type": "number",
"schema": { "schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema", "$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double", "title": "Nullable_double",
"type": "number", "type": "number",
"format": "double", "format": "double",
"nullable": true,
"definitions": { "definitions": {
"Solid": { "Solid": {
"type": "object", "type": "object",
@ -329235,9 +329240,9 @@
} }
} }
}, },
"required": true, "required": false,
"includeInSnippet": true, "includeInSnippet": true,
"description": "The amount to move the solid or sketch along the y axis.", "description": "The amount to move the solid or sketch along the y axis. Defaults to 0 if not provided.",
"labelRequired": true "labelRequired": true
}, },
{ {
@ -329245,9 +329250,10 @@
"type": "number", "type": "number",
"schema": { "schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema", "$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double", "title": "Nullable_double",
"type": "number", "type": "number",
"format": "double", "format": "double",
"nullable": true,
"definitions": { "definitions": {
"Solid": { "Solid": {
"type": "object", "type": "object",
@ -330832,9 +330838,9 @@
} }
} }
}, },
"required": true, "required": false,
"includeInSnippet": true, "includeInSnippet": true,
"description": "The amount to move the solid or sketch along the z axis.", "description": "The amount to move the solid or sketch along the z axis. Defaults to 0 if not provided.",
"labelRequired": true "labelRequired": true
}, },
{ {
@ -334106,8 +334112,8 @@
"// Move a pipe.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> translate(x = 1.0, y = 1.0, z = 2.5)", "// Move a pipe.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> translate(x = 1.0, y = 1.0, z = 2.5)",
"// Move an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> translate(x = 1.0, y = 1.0, z = 2.5)", "// Move an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> translate(x = 1.0, y = 1.0, z = 2.5)",
"// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Move the sweeps.\ntranslate(\n parts,\n x = 1.0,\n y = 1.0,\n z = 2.5,\n)", "// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Move the sweeps.\ntranslate(\n parts,\n x = 1.0,\n y = 1.0,\n z = 2.5,\n)",
"// Move a sketch.\n\n\nfn square(length) {\n l = length / 2\n p0 = [-l, -l]\n p1 = [-l, l]\n p2 = [l, l]\n p3 = [l, -l]\n\n return startSketchOn(XY)\n |> startProfileAt(p0, %)\n |> line(endAbsolute = p1)\n |> line(endAbsolute = p2)\n |> line(endAbsolute = p3)\n |> close()\n}\n\nsquare(10)\n |> translate(x = 5, y = 5, z = 0)\n |> extrude(length = 10)", "// Move a sketch.\n\n\nfn square(length) {\n l = length / 2\n p0 = [-l, -l]\n p1 = [-l, l]\n p2 = [l, l]\n p3 = [l, -l]\n\n return startSketchOn(XY)\n |> startProfileAt(p0, %)\n |> line(endAbsolute = p1)\n |> line(endAbsolute = p2)\n |> line(endAbsolute = p3)\n |> close()\n}\n\nsquare(10)\n |> translate(x = 5, y = 5)\n |> extrude(length = 10)",
"// Translate and rotate a sketch to create a loft.\nsketch001 = startSketchOn(XY)\n\nfn square() {\n return startProfileAt([-10, 10], sketch001)\n |> xLine(length = 20)\n |> yLine(length = -20)\n |> xLine(length = -20)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n}\n\nprofile001 = square()\n\nprofile002 = square()\n |> translate(x = 0, y = 0, z = 20)\n |> rotate(axis = [0, 0, 1.0], angle = 45)\n\nloft([profile001, profile002])" "// Translate and rotate a sketch to create a loft.\nsketch001 = startSketchOn(XY)\n\nfn square() {\n return startProfileAt([-10, 10], sketch001)\n |> xLine(length = 20)\n |> yLine(length = -20)\n |> xLine(length = -20)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n}\n\nprofile001 = square()\n\nprofile002 = square()\n |> translate(z = 20)\n |> rotate(axis = [0, 0, 1.0], angle = 45)\n\nloft([profile001, profile002])"
] ]
}, },
{ {

View File

@ -13,9 +13,9 @@ Translate is really useful for sketches if you want to move a sketch and then ro
```js ```js
translate( translate(
objects: SolidOrSketchOrImportedGeometry, objects: SolidOrSketchOrImportedGeometry,
x: number, x?: number,
y: number, y?: number,
z: number, z?: number,
global?: bool, global?: bool,
): SolidOrSketchOrImportedGeometry ): SolidOrSketchOrImportedGeometry
``` ```
@ -26,9 +26,9 @@ translate(
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `objects` | [`SolidOrSketchOrImportedGeometry`](/docs/kcl/types/SolidOrSketchOrImportedGeometry) | The solid, sketch, or set of solids or sketches to move. | Yes | | `objects` | [`SolidOrSketchOrImportedGeometry`](/docs/kcl/types/SolidOrSketchOrImportedGeometry) | The solid, sketch, or set of solids or sketches to move. | Yes |
| `x` | [`number`](/docs/kcl/types/number) | The amount to move the solid or sketch along the x axis. | Yes | | `x` | [`number`](/docs/kcl/types/number) | The amount to move the solid or sketch along the x axis. Defaults to 0 if not provided. | No |
| `y` | [`number`](/docs/kcl/types/number) | The amount to move the solid or sketch along the y axis. | Yes | | `y` | [`number`](/docs/kcl/types/number) | The amount to move the solid or sketch along the y axis. Defaults to 0 if not provided. | No |
| `z` | [`number`](/docs/kcl/types/number) | The amount to move the solid or sketch along the z axis. | Yes | | `z` | [`number`](/docs/kcl/types/number) | The amount to move the solid or sketch along the z axis. Defaults to 0 if not provided. | No |
| `global` | [`bool`](/docs/kcl/types/bool) | If true, the transform is applied in global space. The origin of the model will move. By default, the transform is applied in local sketch axis, therefore the origin will not move. | No | | `global` | [`bool`](/docs/kcl/types/bool) | If true, the transform is applied in global space. The origin of the model will move. By default, the transform is applied in local sketch axis, therefore the origin will not move. | No |
### Returns ### Returns
@ -134,7 +134,7 @@ fn square(length) {
} }
square(10) square(10)
|> translate(x = 5, y = 5, z = 0) |> translate(x = 5, y = 5)
|> extrude(length = 10) |> extrude(length = 10)
``` ```
@ -156,7 +156,7 @@ fn square() {
profile001 = square() profile001 = square()
profile002 = square() profile002 = square()
|> translate(x = 0, y = 0, z = 20) |> translate(z = 20)
|> rotate(axis = [0, 0, 1.0], angle = 45) |> rotate(axis = [0, 0, 1.0], angle = 45)
loft([profile001, profile002]) loft([profile001, profile002])

View File

@ -1,4 +1,4 @@
import { test, expect } from './zoo-test' import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Electron app header tests', () => { test.describe('Electron app header tests', () => {
test( test(

View File

@ -1,13 +1,14 @@
import { Page } from '@playwright/test' import type { Page } from '@playwright/test'
import { test, expect } from './zoo-test'
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
import { import {
getUtils, PERSIST_MODELING_CONTEXT,
TEST_COLORS, TEST_COLORS,
commonPoints, commonPoints,
PERSIST_MODELING_CONTEXT, getUtils,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
} from './test-utils' } from '@e2e/playwright/test-utils'
import { HomePageFixture } from './fixtures/homePageFixture' import { expect, test } from '@e2e/playwright/zoo-test'
test.setTimeout(120000) test.setTimeout(120000)

View File

@ -1,7 +1,8 @@
import { test, expect } from './zoo-test'
import fs from 'node:fs/promises' import fs from 'node:fs/promises'
import path from 'node:path' import path from 'node:path'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Point and click for boolean workflows', () => { test.describe('Point and click for boolean workflows', () => {
// Boolean operations to test // Boolean operations to test
const booleanOperations = [ const booleanOperations = [

View File

@ -1,10 +1,11 @@
import { Page } from '@playwright/test' import type { Page } from '@playwright/test'
import { test, expect } from './zoo-test' import type { EngineCommand } from '@src/lang/std/artifactGraph'
import { HomePageFixture } from './fixtures/homePageFixture' import { uuidv4 } from '@src/lib/utils'
import { getUtils } from './test-utils'
import { EngineCommand } from 'lang/std/artifactGraph' import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
import { uuidv4 } from 'lib/utils' import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import { SceneFixture } from './fixtures/sceneFixture' import { getUtils } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe( test.describe(
'Can create sketches on all planes and their back sides', 'Can create sketches on all planes and their back sides',

View File

@ -1,13 +1,14 @@
import { test, expect } from './zoo-test' import { bracket } from '@src/lib/exampleKcl'
import {
orRunWhenFullSuiteEnabled,
getUtils,
executorInputPath,
} from './test-utils'
import { join } from 'path'
import { bracket } from 'lib/exampleKcl'
import { TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW } from './storageStates'
import fsp from 'fs/promises' import fsp from 'fs/promises'
import { join } from 'path'
import { TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW } from '@e2e/playwright/storageStates'
import {
executorInputPath,
getUtils,
orRunWhenFullSuiteEnabled,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => { test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => {
test('Typing KCL errors induces a badge on the code pane button', async ({ test('Typing KCL errors induces a badge on the code pane button', async ({

View File

@ -1,12 +1,13 @@
import { test, expect } from './zoo-test' import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import path, { join } from 'path'
import { import {
executorInputPath, executorInputPath,
getUtils, getUtils,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
} from './test-utils' } from '@e2e/playwright/test-utils'
import { KCL_DEFAULT_LENGTH } from 'lib/constants' import { expect, test } from '@e2e/playwright/zoo-test'
import path, { join } from 'path'
test.describe('Command bar tests', { tag: ['@skipWin'] }, () => { test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
test('Extrude from command bar selects extrude line after', async ({ test('Extrude from command bar selects extrude line after', async ({

View File

@ -1,5 +1,5 @@
import { test, expect } from './zoo-test' import { getUtils } from '@e2e/playwright/test-utils'
import { getUtils } from './test-utils' import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Copilot ghost text', () => { test.describe('Copilot ghost text', () => {
// eslint-disable-next-line jest/valid-title // eslint-disable-next-line jest/valid-title

View File

@ -1,6 +1,5 @@
import { test, expect } from './zoo-test' import { getUtils } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
import { getUtils } from './test-utils'
function countNewlines(input: string): number { function countNewlines(input: string): number {
let count = 0 let count = 0

View File

@ -1,11 +1,12 @@
import { test, expect } from './zoo-test' import fsp from 'fs/promises'
import path from 'path' import path from 'path'
import { import {
getUtils,
executorInputPath, executorInputPath,
getPlaywrightDownloadDir, getPlaywrightDownloadDir,
} from './test-utils' getUtils,
import fsp from 'fs/promises' } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test( test(
'export works on the first try', 'export works on the first try',

View File

@ -1,14 +1,14 @@
import { test, expect } from './zoo-test' import { uuidv4 } from '@src/lib/utils'
import fsp from 'fs/promises' import fsp from 'fs/promises'
import { uuidv4 } from 'lib/utils' import { join } from 'path'
import { import {
TEST_COLORS,
executorInputPath, executorInputPath,
getUtils, getUtils,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
TEST_COLORS, } from '@e2e/playwright/test-utils'
} from './test-utils' import { expect, test } from '@e2e/playwright/zoo-test'
import { join } from 'path'
test.describe('Editor tests', { tag: ['@skipWin'] }, () => { test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
test('can comment out code with ctrl+/', async ({ page, homePage }) => { test('can comment out code with ctrl+/', async ({ page, homePage }) => {

View File

@ -1,7 +1,8 @@
import { test, expect } from './zoo-test'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import { join } from 'path' import { join } from 'path'
import { expect, test } from '@e2e/playwright/zoo-test'
const FEATURE_TREE_EXAMPLE_CODE = `export fn timesFive(x) { const FEATURE_TREE_EXAMPLE_CODE = `export fn timesFive(x) {
return 5 * x return 5 * x
} }

View File

@ -1,15 +1,16 @@
import { test, expect } from './zoo-test' import { FILE_EXT } from '@src/lib/constants'
import * as fsp from 'fs/promises'
import * as fs from 'fs' import * as fs from 'fs'
import * as fsp from 'fs/promises'
import { join } from 'path'
import { import {
createProject, createProject,
executorInputPath, executorInputPath,
getUtils, getUtils,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
runningOnWindows, runningOnWindows,
} from './test-utils' } from '@e2e/playwright/test-utils'
import { join } from 'path' import { expect, test } from '@e2e/playwright/zoo-test'
import { FILE_EXT } from 'lib/constants'
test.describe('integrations tests', () => { test.describe('integrations tests', () => {
test( test(

View File

@ -1,5 +1,5 @@
import type { Page, Locator, Route, Request } from '@playwright/test' import type { Locator, Page, Request, Route, TestInfo } from '@playwright/test'
import { expect, TestInfo } from '@playwright/test' import { expect } from '@playwright/test'
import * as fs from 'fs' import * as fs from 'fs'
import * as path from 'path' import * as path from 'path'

View File

@ -1,11 +1,12 @@
import type { Page, Locator } from '@playwright/test' import type { Locator, Page } from '@playwright/test'
import { expect } from '@playwright/test' import { expect } from '@playwright/test'
import { import {
closePane,
checkIfPaneIsOpen, checkIfPaneIsOpen,
closePane,
openPane, openPane,
sansWhitespace, sansWhitespace,
} from '../test-utils' } from '@e2e/playwright/test-utils'
interface EditorState { interface EditorState {
activeLines: Array<string> activeLines: Array<string>

View File

@ -1,28 +1,28 @@
/* eslint-disable react-hooks/rules-of-hooks */ /* eslint-disable react-hooks/rules-of-hooks */
import type { import type {
BrowserContext, BrowserContext,
ElectronApplication, ElectronApplication,
TestInfo,
Page, Page,
TestInfo,
} from '@playwright/test' } from '@playwright/test'
import { _electron as electron } from '@playwright/test' import { _electron as electron } from '@playwright/test'
import * as TOML from '@iarna/toml' import { SETTINGS_FILE_NAME } from '@src/lib/constants'
import { TEST_SETTINGS } from '../storageStates' import type { DeepPartial } from '@src/lib/types'
import { SETTINGS_FILE_NAME } from 'lib/constants'
import { getUtils, setup } from '../test-utils'
import fsp from 'fs/promises' import fsp from 'fs/promises'
import fs from 'node:fs' import fs from 'node:fs'
import path from 'path' import path from 'path'
import { CmdBarFixture } from './cmdBarFixture'
import { EditorFixture } from './editorFixture' import type { Settings } from '@rust/kcl-lib/bindings/Settings'
import { ToolbarFixture } from './toolbarFixture'
import { SceneFixture } from './sceneFixture' import { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import { HomePageFixture } from './homePageFixture' import { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
import { DeepPartial } from 'lib/types' import { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
import { Settings } from '@rust/kcl-lib/bindings/Settings' import { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
import { TEST_SETTINGS } from '@e2e/playwright/storageStates'
import { getUtils, settingsToToml, setup } from '@e2e/playwright/test-utils'
export class AuthenticatedApp { export class AuthenticatedApp {
public readonly page: Page public readonly page: Page
@ -287,26 +287,30 @@ export class ElectronZoo {
let settingsOverridesToml = '' let settingsOverridesToml = ''
if (appSettings) { if (appSettings) {
settingsOverridesToml = TOML.stringify({ settingsOverridesToml = settingsToToml({
// @ts-expect-error
settings: { settings: {
...TEST_SETTINGS, ...TEST_SETTINGS,
...appSettings, ...appSettings,
app: { app: {
...TEST_SETTINGS.app, ...TEST_SETTINGS.app,
project_directory: this.projectDirName,
...appSettings.app, ...appSettings.app,
}, },
project: {
...TEST_SETTINGS.project,
directory: this.projectDirName,
},
}, },
}) })
} else { } else {
settingsOverridesToml = TOML.stringify({ settingsOverridesToml = settingsToToml({
// @ts-expect-error
settings: { settings: {
...TEST_SETTINGS, ...TEST_SETTINGS,
app: { app: {
...TEST_SETTINGS.app, ...TEST_SETTINGS.app,
project_directory: this.projectDirName, },
project: {
...TEST_SETTINGS.project,
directory: this.projectDirName,
}, },
}, },
}) })

View File

@ -1,4 +1,4 @@
import type { Page, Locator } from '@playwright/test' import type { Locator, Page } from '@playwright/test'
import { expect } from '@playwright/test' import { expect } from '@playwright/test'
interface ProjectCardState { interface ProjectCardState {

View File

@ -1,15 +1,17 @@
import type { Page, Locator } from '@playwright/test' import type { Locator, Page } from '@playwright/test'
import { expect } from '../zoo-test' import { isArray, uuidv4 } from '@src/lib/utils'
import { isArray, uuidv4 } from 'lib/utils'
import { CmdBarFixture } from './cmdBarFixture' import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import { import {
closeDebugPanel, closeDebugPanel,
doAndWaitForImageDiff, doAndWaitForImageDiff,
getPixelRGBs, getPixelRGBs,
getUtils,
openAndClearDebugPanel, openAndClearDebugPanel,
sendCustomCmd, sendCustomCmd,
getUtils, } from '@e2e/playwright/test-utils'
} from '../test-utils' import { expect } from '@e2e/playwright/zoo-test'
type MouseParams = { type MouseParams = {
pixelDiff?: number pixelDiff?: number

View File

@ -1,14 +1,15 @@
import { type Page, type Locator, test } from '@playwright/test' import { type Locator, type Page, test } from '@playwright/test'
import { expect } from '../zoo-test' import type { SidebarType } from '@src/components/ModelingSidebar/ModelingPanes'
import { SIDEBAR_BUTTON_SUFFIX } from '@src/lib/constants'
import type { ToolbarModeName } from '@src/lib/toolbar'
import { import {
checkIfPaneIsOpen, checkIfPaneIsOpen,
closePane, closePane,
doAndWaitForImageDiff, doAndWaitForImageDiff,
openPane, openPane,
} from '../test-utils' } from '@e2e/playwright/test-utils'
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes' import { expect } from '@e2e/playwright/zoo-test'
import { SIDEBAR_BUTTON_SUFFIX } from 'lib/constants'
import { ToolbarModeName } from 'lib/toolbar'
export class ToolbarFixture { export class ToolbarFixture {
public page: Page public page: Page

View File

@ -1,7 +1,8 @@
import { test, expect } from './zoo-test'
import { executorInputPath } from './test-utils'
import { join } from 'path'
import fsp from 'fs/promises' import fsp from 'fs/promises'
import { join } from 'path'
import { executorInputPath } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test( test(
'When machine-api server not found butt is disabled and shows the reason', 'When machine-api server not found butt is disabled and shows the reason',

View File

@ -1,13 +1,15 @@
import { test, expect } from './zoo-test' import { PROJECT_SETTINGS_FILE_NAME } from '@src/lib/constants'
import { PROJECT_SETTINGS_FILE_NAME } from 'lib/constants'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import { join } from 'path' import { join } from 'path'
import type { NamedView } from '@rust/kcl-lib/bindings/NamedView'
import { import {
createProject, createProject,
tomlToPerProjectSettings,
perProjectsettingsToToml, perProjectsettingsToToml,
} from './test-utils' tomlToPerProjectSettings,
import { NamedView } from '@rust/kcl-lib/bindings/NamedView' } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
// Helper function to determine if the file path on disk exists // Helper function to determine if the file path on disk exists
// Specifically this is used to check if project.toml exists on disk // Specifically this is used to check if project.toml exists on disk

View File

@ -1,4 +1,4 @@
import { test, expect } from './zoo-test' import { expect, test } from '@e2e/playwright/zoo-test'
/** /**
* Not all menu actions are tested. Some are default electron menu actions. * Not all menu actions are tested. Some are default electron menu actions.
@ -10,6 +10,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
test('File.Create project', async ({ tronApp, cmdBar, page }) => { test('File.Create project', async ({ tronApp, cmdBar, page }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const newProject = const newProject =
@ -29,6 +30,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
test('File.Open project', async ({ tronApp, cmdBar, page }) => { test('File.Open project', async ({ tronApp, cmdBar, page }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const openProject = const openProject =
@ -52,6 +54,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
}) => { }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const userSettings = app.applicationMenu.getMenuItemById( const userSettings = app.applicationMenu.getMenuItemById(
@ -75,6 +78,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
}) => { }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const keybindings = app.applicationMenu.getMenuItemById( const keybindings = app.applicationMenu.getMenuItemById(
@ -96,6 +100,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
}) => { }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById( const menu = app.applicationMenu.getMenuItemById(
@ -112,6 +117,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
test('File.Preferences.Theme', async ({ tronApp, cmdBar, page }) => { test('File.Preferences.Theme', async ({ tronApp, cmdBar, page }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById( const menu = app.applicationMenu.getMenuItemById(
@ -136,6 +142,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
}) => { }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById( const menu = app.applicationMenu.getMenuItemById(
@ -152,6 +159,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
test('File.Preferences.Sign out', async ({ tronApp, cmdBar, page }) => { test('File.Preferences.Sign out', async ({ tronApp, cmdBar, page }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById('File.Sign out') const menu = app.applicationMenu.getMenuItemById('File.Sign out')
@ -170,6 +178,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
test('Edit.Rename project', async ({ tronApp, cmdBar, page }) => { test('Edit.Rename project', async ({ tronApp, cmdBar, page }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById( const menu = app.applicationMenu.getMenuItemById(
@ -188,6 +197,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
test('Edit.Delete project', async ({ tronApp, cmdBar, page }) => { test('Edit.Delete project', async ({ tronApp, cmdBar, page }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById( const menu = app.applicationMenu.getMenuItemById(
@ -210,6 +220,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
}) => { }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById( const menu = app.applicationMenu.getMenuItemById(
@ -228,6 +239,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
test('View.Command Palette...', async ({ tronApp, cmdBar, page }) => { test('View.Command Palette...', async ({ tronApp, cmdBar, page }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById( const menu = app.applicationMenu.getMenuItemById(
@ -245,6 +257,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
test('Help.Show all commands', async ({ tronApp, cmdBar, page }) => { test('Help.Show all commands', async ({ tronApp, cmdBar, page }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById( const menu = app.applicationMenu.getMenuItemById(
@ -260,6 +273,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
test('Help.KCL code samples', async ({ tronApp, cmdBar, page }) => { test('Help.KCL code samples', async ({ tronApp, cmdBar, page }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById( const menu = app.applicationMenu.getMenuItemById(
@ -275,6 +289,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
}) => { }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById( const menu = app.applicationMenu.getMenuItemById(
@ -293,6 +308,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
test('Help.Reset onboarding', async ({ tronApp, cmdBar, page }) => { test('Help.Reset onboarding', async ({ tronApp, cmdBar, page }) => {
if (!tronApp) fail() if (!tronApp) fail()
// Run electron snippet to find the Menu! // Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => { await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail() if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById( const menu = app.applicationMenu.getMenuItemById(

View File

@ -2,8 +2,7 @@
// application, check it can make it to the project pane, and nothing more. // application, check it can make it to the project pane, and nothing more.
// It also tests our test wrappers are working. // It also tests our test wrappers are working.
// Additionally this serves as a nice minimal example. // Additionally this serves as a nice minimal example.
import { expect, test } from '@e2e/playwright/zoo-test'
import { test, expect } from './zoo-test'
test.describe('Open the application', () => { test.describe('Open the application', () => {
test('see the project view', async ({ page, context }) => { test('see the project view', async ({ page, context }) => {

View File

@ -1,22 +1,23 @@
import { test, expect } from './zoo-test' import { bracket } from '@src/lib/exampleKcl'
import { join } from 'path' import { onboardingPaths } from '@src/routes/Onboarding/paths'
import fsp from 'fs/promises' import fsp from 'fs/promises'
import { import { join } from 'path'
getUtils,
executorInputPath, import { expectPixelColor } from '@e2e/playwright/fixtures/sceneFixture'
createProject,
settingsToToml,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { bracket } from 'lib/exampleKcl'
import { onboardingPaths } from 'routes/Onboarding/paths'
import { import {
TEST_SETTINGS_KEY, TEST_SETTINGS_KEY,
TEST_SETTINGS_ONBOARDING_START,
TEST_SETTINGS_ONBOARDING_EXPORT, TEST_SETTINGS_ONBOARDING_EXPORT,
TEST_SETTINGS_ONBOARDING_START,
TEST_SETTINGS_ONBOARDING_USER_MENU, TEST_SETTINGS_ONBOARDING_USER_MENU,
} from './storageStates' } from '@e2e/playwright/storageStates'
import { expectPixelColor } from './fixtures/sceneFixture' import {
createProject,
executorInputPath,
getUtils,
orRunWhenFullSuiteEnabled,
settingsToToml,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
// Because our default test settings have the onboardingStatus set to 'dismissed', // Because our default test settings have the onboardingStatus set to 'dismissed',
// we must set it to empty for the tests where we want to see the onboarding immediately. // we must set it to empty for the tests where we want to see the onboarding immediately.

View File

@ -1,4 +1,4 @@
import { test, expect } from '@playwright/test' import { expect, test } from '@playwright/test'
/** @deprecated, import from ./fixtureSetup.ts instead */ /** @deprecated, import from ./fixtureSetup.ts instead */
export const _test = test export const _test = test

View File

@ -1,12 +1,12 @@
import { Page } from '@playwright/test' import type { Locator, Page } from '@playwright/test'
import { test, expect } from './zoo-test'
import { EditorFixture } from './fixtures/editorFixture'
import { SceneFixture } from './fixtures/sceneFixture'
import { ToolbarFixture } from './fixtures/toolbarFixture'
import fs from 'node:fs/promises' import fs from 'node:fs/promises'
import path from 'node:path' import path from 'node:path'
import { getUtils, orRunWhenFullSuiteEnabled } from './test-utils'
import { Locator } from '@playwright/test' import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
// test file is for testing point an click code gen functionality that's not sketch mode related // test file is for testing point an click code gen functionality that's not sketch mode related

View File

@ -1,19 +1,20 @@
import { test, expect } from './zoo-test' import { DEFAULT_PROJECT_KCL_FILE } from '@src/lib/constants'
import fs from 'fs'
import fsp from 'fs/promises'
import path from 'path'
import type { Paths } from '@e2e/playwright/test-utils'
import { import {
createProject,
doExport, doExport,
executorInputPath, executorInputPath,
getPlaywrightDownloadDir,
getUtils, getUtils,
isOutOfViewInScrollContainer, isOutOfViewInScrollContainer,
Paths,
createProject,
getPlaywrightDownloadDir,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
runningOnWindows, runningOnWindows,
} from './test-utils' } from '@e2e/playwright/test-utils'
import fsp from 'fs/promises' import { expect, test } from '@e2e/playwright/zoo-test'
import fs from 'fs'
import path from 'path'
import { DEFAULT_PROJECT_KCL_FILE } from 'lib/constants'
test( test(
'projects reload if a new one is created, deleted, or renamed externally', 'projects reload if a new one is created, deleted, or renamed externally',

View File

@ -1,4 +1,5 @@
import { test, expect } from './zoo-test' import { expect, test } from '@e2e/playwright/zoo-test'
/* eslint-disable jest/no-conditional-expect */ /* eslint-disable jest/no-conditional-expect */
/** /**

View File

@ -1,5 +1,5 @@
import { test, expect } from './zoo-test' import { orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { orRunWhenFullSuiteEnabled } from './test-utils' import { expect, test } from '@e2e/playwright/zoo-test'
/* eslint-disable jest/no-conditional-expect */ /* eslint-disable jest/no-conditional-expect */

View File

@ -1,17 +1,18 @@
import { Page } from '@playwright/test' import type { Page } from '@playwright/test'
import { test, expect } from './zoo-test' import { bracket } from '@src/lib/exampleKcl'
import path from 'path' import { reportRejection } from '@src/lib/trap'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import path from 'path'
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from '@e2e/playwright/storageStates'
import type { TestColor } from '@e2e/playwright/test-utils'
import { import {
getUtils,
TEST_COLORS, TEST_COLORS,
TestColor,
executorInputPath, executorInputPath,
getUtils,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
} from './test-utils' } from '@e2e/playwright/test-utils'
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from './storageStates' import { expect, test } from '@e2e/playwright/zoo-test'
import { bracket } from 'lib/exampleKcl'
import { reportRejection } from 'lib/trap'
test.describe('Regression tests', { tag: ['@skipWin'] }, () => { test.describe('Regression tests', { tag: ['@skipWin'] }, () => {
// bugs we found that don't fit neatly into other categories // bugs we found that don't fit neatly into other categories

View File

@ -1,20 +1,20 @@
import { Page } from '@playwright/test' import type { Page } from '@playwright/test'
import { test, expect } from './zoo-test' import { roundOff, uuidv4 } from '@src/lib/utils'
import fs from 'node:fs/promises' import fs from 'node:fs/promises'
import path from 'node:path' import path from 'node:path'
import { HomePageFixture } from './fixtures/homePageFixture'
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
import { import {
getMovementUtils,
getUtils,
PERSIST_MODELING_CONTEXT, PERSIST_MODELING_CONTEXT,
TEST_COLORS, TEST_COLORS,
getMovementUtils,
getUtils,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
} from './test-utils' } from '@e2e/playwright/test-utils'
import { uuidv4, roundOff } from 'lib/utils' import { expect, test } from '@e2e/playwright/zoo-test'
import { SceneFixture } from './fixtures/sceneFixture'
import { ToolbarFixture } from './fixtures/toolbarFixture'
import { CmdBarFixture } from './fixtures/cmdBarFixture'
test.describe('Sketch tests', { tag: ['@skipWin'] }, () => { test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
test('multi-sketch file shows multiple Edit Sketch buttons', async ({ test('multi-sketch file shows multiple Edit Sketch buttons', async ({

View File

@ -1,21 +1,22 @@
import { test, expect } from './zoo-test' import type { Models } from '@kittycad/lib'
import { secrets } from './secrets' import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
import {
Paths,
doExport,
getUtils,
settingsToToml,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { Models } from '@kittycad/lib'
import fsp from 'fs/promises'
import { spawn } from 'child_process' import { spawn } from 'child_process'
import { KCL_DEFAULT_LENGTH } from 'lib/constants' import fsp from 'fs/promises'
import JSZip from 'jszip' import JSZip from 'jszip'
import path from 'path' import path from 'path'
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from './storageStates'
import { SceneFixture } from './fixtures/sceneFixture' import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import { CmdBarFixture } from './fixtures/cmdBarFixture' import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import { secrets } from '@e2e/playwright/secrets'
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
import type { Paths } from '@e2e/playwright/test-utils'
import {
doExport,
getUtils,
orRunWhenFullSuiteEnabled,
settingsToToml,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.beforeEach(async ({ page, context }) => { test.beforeEach(async ({ page, context }) => {
// Make the user avatar image always 404 // Make the user avatar image always 404
@ -345,8 +346,10 @@ const extrudeDefaultPlane = async (
app: { app: {
onboarding_status: 'dismissed', onboarding_status: 'dismissed',
show_debug_panel: true, show_debug_panel: true,
appearance: {
theme: 'dark', theme: 'dark',
}, },
},
project: { project: {
default_project_name: 'project-$nnn', default_project_name: 'project-$nnn',
}, },

View File

@ -1,17 +1,19 @@
import { Settings } from '@rust/kcl-lib/bindings/Settings' import type { SaveSettingsPayload } from '@src/lib/settings/settingsTypes'
import { SaveSettingsPayload } from 'lib/settings/settingsTypes' import { Themes } from '@src/lib/theme'
import { Themes } from 'lib/theme' import type { DeepPartial } from '@src/lib/types'
import { DeepPartial } from 'lib/types' import { onboardingPaths } from '@src/routes/Onboarding/paths'
import { onboardingPaths } from 'routes/Onboarding/paths'
import type { Settings } from '@rust/kcl-lib/bindings/Settings'
export const IS_PLAYWRIGHT_KEY = 'playwright' export const IS_PLAYWRIGHT_KEY = 'playwright'
export const TEST_SETTINGS_KEY = '/settings.toml' export const TEST_SETTINGS_KEY = '/settings.toml'
export const TEST_SETTINGS: DeepPartial<Settings> = { export const TEST_SETTINGS: DeepPartial<Settings> = {
app: { app: {
appearance: {
theme: Themes.Dark, theme: Themes.Dark,
},
onboarding_status: 'dismissed', onboarding_status: 'dismissed',
project_directory: '',
show_debug_panel: true, show_debug_panel: true,
}, },
modeling: { modeling: {
@ -22,6 +24,7 @@ export const TEST_SETTINGS: DeepPartial<Settings> = {
}, },
project: { project: {
default_project_name: 'project-$nnn', default_project_name: 'project-$nnn',
directory: '',
}, },
text_editor: { text_editor: {
text_wrapping: true, text_wrapping: true,
@ -54,7 +57,7 @@ export const TEST_SETTINGS_ONBOARDING_START: DeepPartial<Settings> = {
export const TEST_SETTINGS_DEFAULT_THEME: DeepPartial<Settings> = { export const TEST_SETTINGS_DEFAULT_THEME: DeepPartial<Settings> = {
...TEST_SETTINGS, ...TEST_SETTINGS,
app: { ...TEST_SETTINGS.app, theme: Themes.System }, app: { ...TEST_SETTINGS.app, appearance: { theme: Themes.System } },
} }
export const TEST_SETTINGS_CORRUPTED = { export const TEST_SETTINGS_CORRUPTED = {

View File

@ -1,7 +1,12 @@
import { test, expect } from './zoo-test' import type { EngineCommand } from '@src/lang/std/artifactGraph'
import { commonPoints, getUtils, orRunWhenFullSuiteEnabled } from './test-utils' import { uuidv4 } from '@src/lib/utils'
import { EngineCommand } from 'lang/std/artifactGraph'
import { uuidv4 } from 'lib/utils' import {
commonPoints,
getUtils,
orRunWhenFullSuiteEnabled,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Test network and connection issues', () => { test.describe('Test network and connection issues', () => {
test( test(

View File

@ -1,9 +1,9 @@
import { import {
orRunWhenFullSuiteEnabled,
runningOnLinux, runningOnLinux,
runningOnMac, runningOnMac,
runningOnWindows, runningOnWindows,
orRunWhenFullSuiteEnabled, } from '@e2e/playwright/test-utils'
} from './test-utils'
describe('platform detection utilities', () => { describe('platform detection utilities', () => {
const originalPlatform = process.platform const originalPlatform = process.platform

View File

@ -1,32 +1,29 @@
import { import * as TOML from '@iarna/toml'
expect, import type { Models } from '@kittycad/lib'
BrowserContext, import type { BrowserContext, Locator, Page, TestInfo } from '@playwright/test'
TestInfo, import { expect } from '@playwright/test'
Locator, import type { EngineCommand } from '@src/lang/std/artifactGraph'
Page, import type { Configuration } from '@src/lang/wasm'
} from '@playwright/test' import { COOKIE_NAME } from '@src/lib/constants'
import { test } from './zoo-test' import { reportRejection } from '@src/lib/trap'
import { EngineCommand } from 'lang/std/artifactGraph' import type { DeepPartial } from '@src/lib/types'
import { isArray } from '@src/lib/utils'
import fsp from 'fs/promises' import fsp from 'fs/promises'
import path from 'path' import path from 'path'
import pixelMatch from 'pixelmatch' import pixelMatch from 'pixelmatch'
import type { Protocol } from 'playwright-core/types/protocol'
import { PNG } from 'pngjs' import { PNG } from 'pngjs'
import { Protocol } from 'playwright-core/types/protocol'
import type { Models } from '@kittycad/lib' import type { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
import { COOKIE_NAME } from 'lib/constants'
import { secrets } from './secrets' import { isErrorWhitelisted } from '@e2e/playwright/lib/console-error-whitelist'
import { secrets } from '@e2e/playwright/secrets'
import { import {
TEST_SETTINGS_KEY,
TEST_SETTINGS,
IS_PLAYWRIGHT_KEY, IS_PLAYWRIGHT_KEY,
} from './storageStates' TEST_SETTINGS,
import * as TOML from '@iarna/toml' TEST_SETTINGS_KEY,
import { isErrorWhitelisted } from './lib/console-error-whitelist' } from '@e2e/playwright/storageStates'
import { isArray } from 'lib/utils' import { test } from '@e2e/playwright/zoo-test'
import { reportRejection } from 'lib/trap'
import { DeepPartial } from 'lib/types'
import { Configuration } from 'lang/wasm'
import { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
const toNormalizedCode = (text: string) => { const toNormalizedCode = (text: string) => {
return text.replace(/\s+/g, '') return text.replace(/\s+/g, '')
@ -903,15 +900,21 @@ export async function setup(
settings: { settings: {
...TEST_SETTINGS, ...TEST_SETTINGS,
app: { app: {
...TEST_SETTINGS.project, appearance: {
project_directory: TEST_SETTINGS.app?.project_directory, ...TEST_SETTINGS.app?.appearance,
onboarding_status: 'dismissed',
theme: 'dark', theme: 'dark',
}, },
...TEST_SETTINGS.project,
onboarding_status: 'dismissed',
},
project: {
...TEST_SETTINGS.project,
directory: TEST_SETTINGS.project?.directory,
},
}, },
}), }),
IS_PLAYWRIGHT_KEY, IS_PLAYWRIGHT_KEY,
PLAYWRIGHT_TEST_DIR: TEST_SETTINGS.app?.project_directory || '', PLAYWRIGHT_TEST_DIR: TEST_SETTINGS.project?.directory || '',
PERSIST_MODELING_CONTEXT, PERSIST_MODELING_CONTEXT,
} }
) )
@ -1112,21 +1115,25 @@ export async function pollEditorLinesSelectedLength(page: Page, lines: number) {
} }
export function settingsToToml(settings: DeepPartial<Configuration>) { export function settingsToToml(settings: DeepPartial<Configuration>) {
// eslint-disable-next-line no-restricted-syntax
return TOML.stringify(settings as any) return TOML.stringify(settings as any)
} }
export function tomlToSettings(toml: string): DeepPartial<Configuration> { export function tomlToSettings(toml: string): DeepPartial<Configuration> {
// eslint-disable-next-line no-restricted-syntax
return TOML.parse(toml) return TOML.parse(toml)
} }
export function tomlToPerProjectSettings( export function tomlToPerProjectSettings(
toml: string toml: string
): DeepPartial<ProjectConfiguration> { ): DeepPartial<ProjectConfiguration> {
// eslint-disable-next-line no-restricted-syntax
return TOML.parse(toml) return TOML.parse(toml)
} }
export function perProjectsettingsToToml( export function perProjectsettingsToToml(
settings: DeepPartial<ProjectConfiguration> settings: DeepPartial<ProjectConfiguration>
) { ) {
// eslint-disable-next-line no-restricted-syntax
return TOML.stringify(settings as any) return TOML.stringify(settings as any)
} }

View File

@ -1,7 +1,8 @@
import { test, expect } from './zoo-test' import type { EngineCommand } from '@src/lang/std/artifactGraph'
import { EngineCommand } from 'lang/std/artifactGraph' import { uuidv4 } from '@src/lib/utils'
import { uuidv4 } from 'lib/utils'
import { getUtils, orRunWhenFullSuiteEnabled } from './test-utils' import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing Camera Movement', { tag: ['@skipWin'] }, () => { test.describe('Testing Camera Movement', { tag: ['@skipWin'] }, () => {
test('Can move camera reliably', async ({ page, context, homePage }) => { test('Can move camera reliably', async ({ page, context, homePage }) => {

View File

@ -1,14 +1,15 @@
import { test, expect } from './zoo-test' import { XOR } from '@src/lib/utils'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import {
getUtils,
TEST_COLORS,
pollEditorLinesSelectedLength,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { XOR } from 'lib/utils'
import path from 'node:path' import path from 'node:path'
import {
TEST_COLORS,
getUtils,
orRunWhenFullSuiteEnabled,
pollEditorLinesSelectedLength,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing constraints', { tag: ['@skipWin'] }, () => { test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
test('Can constrain line length', async ({ page, homePage }) => { test('Can constrain line length', async ({ page, homePage }) => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
@ -1097,7 +1098,7 @@ test.describe('Electron constraint tests', () => {
test( test(
'Able to double click label to set constraint', 'Able to double click label to set constraint',
{ tag: '@electron' }, { tag: '@electron' },
async ({ page, context, homePage, scene, editor, toolbar }) => { async ({ page, context, homePage, scene, editor, toolbar, cmdBar }) => {
await context.folderSetupFn(async (dir) => { await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'test-sample') const bracketDir = path.join(dir, 'test-sample')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
@ -1131,6 +1132,14 @@ test.describe('Electron constraint tests', () => {
await scene.waitForExecutionDone() await scene.waitForExecutionDone()
}) })
async function clickOnFirstSegmentLabel() {
const child = page
.locator('.segment-length-label-text')
.first()
.locator('xpath=..')
await child.dblclick()
}
await test.step('Double click to constrain', async () => { await test.step('Double click to constrain', async () => {
// Enter sketch edit mode via feature tree // Enter sketch edit mode via feature tree
await toolbar.openPane('feature-tree') await toolbar.openPane('feature-tree')
@ -1138,21 +1147,19 @@ test.describe('Electron constraint tests', () => {
await op.dblclick() await op.dblclick()
await toolbar.closePane('feature-tree') await toolbar.closePane('feature-tree')
const child = page await clickOnFirstSegmentLabel()
.locator('.segment-length-label-text') await cmdBar.progressCmdBar()
.first() await editor.expectEditor.toContain('length001 = 15.3')
.locator('xpath=..') await editor.expectEditor.toContain('|> angledLine([9, length001], %)')
await child.dblclick()
const cmdBarSubmitButton = page.getByRole('button', {
name: 'arrow right Continue',
}) })
await cmdBarSubmitButton.click()
await expect(page.locator('.cm-content')).toContainText( await test.step('Double click again and expect failure', async () => {
'length001 = 15.3' await clickOnFirstSegmentLabel()
)
await expect(page.locator('.cm-content')).toContainText( await expect(
'|> angledLine([9, length001], %)' page.getByText('Unable to constrain the length of this segment')
) ).toBeVisible()
await page.getByRole('button', { name: 'Exit Sketch' }).click() await page.getByRole('button', { name: 'Exit Sketch' }).click()
}) })
} }

View File

@ -1,7 +1,8 @@
import { test, expect } from './zoo-test' import { uuidv4 } from '@src/lib/utils'
import { getUtils } from './test-utils'
import { uuidv4 } from 'lib/utils' import { TEST_CODE_GIZMO } from '@e2e/playwright/storageStates'
import { TEST_CODE_GIZMO } from './storageStates' import { getUtils } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing Gizmo', { tag: ['@skipWin'] }, () => { test.describe('Testing Gizmo', { tag: ['@skipWin'] }, () => {
const cases = [ const cases = [

View File

@ -1,5 +1,5 @@
import { test, expect } from './zoo-test' import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { getUtils, orRunWhenFullSuiteEnabled } from './test-utils' import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Test toggling perspective', () => { test.describe('Test toggling perspective', () => {
test('via command palette and toggle', async ({ page, homePage }) => { test('via command palette and toggle', async ({ page, homePage }) => {

View File

@ -1,9 +1,10 @@
import { test, expect } from './zoo-test' import { FILE_EXT } from '@src/lib/constants'
import { getUtils } from './test-utils' import { bracket } from '@src/lib/exampleKcl'
import { bracket } from 'lib/exampleKcl'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import { join } from 'path' import { join } from 'path'
import { FILE_EXT } from 'lib/constants'
import { getUtils } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing in-app sample loading', () => { test.describe('Testing in-app sample loading', () => {
/** /**

View File

@ -1,15 +1,15 @@
import { Page } from '@playwright/test' import type { Page } from '@playwright/test'
import { test, expect } from './zoo-test' import type { LineInputsType } from '@src/lang/std/sketchcombos'
import { uuidv4 } from '@src/lib/utils'
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
import { import {
deg, deg,
getUtils, getUtils,
wiggleMove,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
} from './test-utils' wiggleMove,
import { LineInputsType } from 'lang/std/sketchcombos' } from '@e2e/playwright/test-utils'
import { uuidv4 } from 'lib/utils' import { expect, test } from '@e2e/playwright/zoo-test'
import { EditorFixture } from './fixtures/editorFixture'
test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => { test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
test('Hover over a segment should show its overlay, hovering over the input overlays should show its popover, clicking the input overlay should constrain/unconstrain it:\nfor the following segments', () => { test('Hover over a segment should show its overlay, hovering over the input overlays should show its popover, clicking the input overlay should constrain/unconstrain it:\nfor the following segments', () => {

View File

@ -1,9 +1,13 @@
import { test, expect } from './zoo-test' import type { Coords2d } from '@src/lang/std/sketch'
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
import { uuidv4 } from '@src/lib/utils'
import { commonPoints, getUtils, orRunWhenFullSuiteEnabled } from './test-utils' import {
import { Coords2d } from 'lang/std/sketch' commonPoints,
import { KCL_DEFAULT_LENGTH } from 'lib/constants' getUtils,
import { uuidv4 } from 'lib/utils' orRunWhenFullSuiteEnabled,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing selections', { tag: ['@skipWin'] }, () => { test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
test.setTimeout(90_000) test.setTimeout(90_000)

View File

@ -1,24 +1,29 @@
import { test, expect } from './zoo-test' import {
PROJECT_SETTINGS_FILE_NAME,
SETTINGS_FILE_NAME,
} from '@src/lib/constants'
import type { SettingsLevel } from '@src/lib/settings/settingsTypes'
import type { DeepPartial } from '@src/lib/types'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import { join } from 'path' import { join } from 'path'
import type { Settings } from '@rust/kcl-lib/bindings/Settings'
import { import {
getUtils,
executorInputPath,
createProject,
tomlToSettings,
TEST_COLORS,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { SettingsLevel } from 'lib/settings/settingsTypes'
import { SETTINGS_FILE_NAME, PROJECT_SETTINGS_FILE_NAME } from 'lib/constants'
import {
TEST_SETTINGS_KEY,
TEST_SETTINGS_CORRUPTED,
TEST_SETTINGS, TEST_SETTINGS,
TEST_SETTINGS_CORRUPTED,
TEST_SETTINGS_DEFAULT_THEME, TEST_SETTINGS_DEFAULT_THEME,
} from './storageStates' TEST_SETTINGS_KEY,
import { DeepPartial } from 'lib/types' } from '@e2e/playwright/storageStates'
import { Settings } from '@rust/kcl-lib/bindings/Settings' import {
TEST_COLORS,
createProject,
executorInputPath,
getUtils,
orRunWhenFullSuiteEnabled,
tomlToSettings,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing settings', () => { test.describe('Testing settings', () => {
test('Stored settings are validated and fall back to defaults', async ({ test('Stored settings are validated and fall back to defaults', async ({
@ -45,12 +50,12 @@ test.describe('Testing settings', () => {
) )
) )
expect(storedSettings.settings?.app?.theme).toBe('dark') expect(storedSettings.settings?.app?.appearance?.theme).toBe('dark')
// Check that the invalid settings were changed to good defaults // Check that the invalid settings were changed to good defaults
expect(storedSettings.settings?.modeling?.base_unit).toBe('in') expect(storedSettings.settings?.modeling?.base_unit).toBe('in')
expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo') expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo')
expect(storedSettings.settings?.app?.project_directory).toBe('') expect(storedSettings.settings?.project?.directory).toBe('')
expect(storedSettings.settings?.project?.default_project_name).toBe( expect(storedSettings.settings?.project?.default_project_name).toBe(
'project-$nnn' 'project-$nnn'
) )
@ -381,7 +386,9 @@ test.describe('Testing settings', () => {
} }
await tronApp.cleanProjectDir({ await tronApp.cleanProjectDir({
app: { app: {
theme_color: '259', appearance: {
color: 259,
},
}, },
}) })
@ -413,9 +420,12 @@ test.describe('Testing settings', () => {
await tronApp.cleanProjectDir({ await tronApp.cleanProjectDir({
app: { app: {
appearance: {
// Doesn't matter what you set it to. It will // Doesn't matter what you set it to. It will
// default to 264.5 // default to 264.5
theme_color: '0',
color: 0,
},
}, },
}) })

View File

@ -1,12 +1,13 @@
import { Page } from '@playwright/test' import type { Page } from '@playwright/test'
import { test, expect } from './zoo-test'
import {
getUtils,
createProject,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { join } from 'path'
import fs from 'fs' import fs from 'fs'
import { join } from 'path'
import {
createProject,
getUtils,
orRunWhenFullSuiteEnabled,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Text-to-CAD tests', { tag: ['@skipWin'] }, () => { test.describe('Text-to-CAD tests', { tag: ['@skipWin'] }, () => {
test('basic lego happy case', async ({ page, homePage }) => { test('basic lego happy case', async ({ page, homePage }) => {

View File

@ -1,11 +1,10 @@
import { test, expect } from './zoo-test'
import { import {
doExport, doExport,
getUtils, getUtils,
makeTemplate, makeTemplate,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
} from './test-utils' } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test('Units menu', async ({ page, homePage }) => { test('Units menu', async ({ page, homePage }) => {
test.fixme(orRunWhenFullSuiteEnabled()) test.fixme(orRunWhenFullSuiteEnabled())

View File

@ -1,12 +1,11 @@
/* eslint-disable react-hooks/rules-of-hooks */ /* eslint-disable react-hooks/rules-of-hooks */
import { test as playwrightTestFn } from '@playwright/test' import { test as playwrightTestFn } from '@playwright/test'
import type { Fixtures } from '@e2e/playwright/fixtures/fixtureSetup'
import { import {
fixturesBasedOnProcessEnvPlatform,
Fixtures,
ElectronZoo, ElectronZoo,
} from './fixtures/fixtureSetup' fixturesBasedOnProcessEnvPlatform,
} from '@e2e/playwright/fixtures/fixtureSetup'
export { expect } from '@playwright/test' export { expect } from '@playwright/test'

View File

@ -1,6 +1,6 @@
import type { ForgeConfig } from '@electron-forge/shared-types'
import { VitePlugin } from '@electron-forge/plugin-vite'
import { FusesPlugin } from '@electron-forge/plugin-fuses' import { FusesPlugin } from '@electron-forge/plugin-fuses'
import { VitePlugin } from '@electron-forge/plugin-vite'
import type { ForgeConfig } from '@electron-forge/shared-types'
import { FuseV1Options, FuseVersion } from '@electron/fuses' import { FuseV1Options, FuseVersion } from '@electron/fuses'
import path from 'path' import path from 'path'

2
forge.env.d.ts vendored
View File

@ -26,7 +26,7 @@ declare global {
declare module 'vite' { declare module 'vite' {
interface ConfigEnv< interface ConfigEnv<
K extends keyof VitePluginConfig = keyof VitePluginConfig K extends keyof VitePluginConfig = keyof VitePluginConfig,
> { > {
root: string root: string
forgeConfig: VitePluginConfig forgeConfig: VitePluginConfig

13
interface.d.ts vendored
View File

@ -1,13 +1,10 @@
import fs from 'node:fs/promises'
import fsSync from 'node:fs'
import path from 'path'
import { dialog, shell } from 'electron'
import { MachinesListing } from 'components/MachineManagerProvider' import { MachinesListing } from 'components/MachineManagerProvider'
import type { Channel } from 'src/menu/channels' import 'electron'
import { Menu, WebContents } from 'electron' import { dialog, shell } from 'electron'
import { ZooLabel, ZooMenuEvents } from 'menu/roles'
import type { MenuActionIPC } from 'menu/rules'
import type { WebContentSendPayload } from 'menu/channels' import type { WebContentSendPayload } from 'menu/channels'
import { ZooLabel } from 'menu/roles'
import fs from 'node:fs/promises'
import path from 'path'
// Extend the interface with additional custom properties // Extend the interface with additional custom properties
declare module 'electron' { declare module 'electron' {

View File

@ -26,7 +26,7 @@
"@fortawesome/react-fontawesome": "^0.2.0", "@fortawesome/react-fontawesome": "^0.2.0",
"@headlessui/react": "^1.7.19", "@headlessui/react": "^1.7.19",
"@headlessui/tailwindcss": "^0.2.2", "@headlessui/tailwindcss": "^0.2.2",
"@kittycad/lib": "2.0.23", "@kittycad/lib": "2.0.25",
"@lezer/highlight": "^1.2.1", "@lezer/highlight": "^1.2.1",
"@lezer/lr": "^1.4.1", "@lezer/lr": "^1.4.1",
"@react-hook/resize-observer": "^2.0.1", "@react-hook/resize-observer": "^2.0.1",
@ -88,9 +88,9 @@
"simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &", "simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &",
"simpleserver:bg": "yarn pretest && http-server ./public --cors -p 3000 &", "simpleserver:bg": "yarn pretest && http-server ./public --cors -p 3000 &",
"simpleserver:stop": "kill-port 3000", "simpleserver:stop": "kill-port 3000",
"fmt": "prettier --write ./src *.ts *.json *.js ./e2e ./packages ./rust/kcl-language-server ./rust/kcl-lib/bindings ./rust/kcl-wasm-lib/pkg", "fmt": "prettier --write .eslintrc.json ./src *.ts *.json *.js ./e2e ./packages ./rust/kcl-language-server ./rust/kcl-lib/bindings ./rust/kcl-wasm-lib/pkg",
"fmt:generated": "prettier --write *.ts *.json *.js ./rust/kcl-lib/bindings ./rust/kcl-wasm-lib/pkg", "fmt:generated": "prettier --write .eslintrc.json *.ts *.json *.js ./rust/kcl-lib/bindings ./rust/kcl-wasm-lib/pkg",
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e ./packages ./rust/kcl-language-server", "fmt-check": "prettier --check .eslintrc.json ./src *.ts *.json *.js ./e2e ./packages ./rust/kcl-language-server",
"fetch:wasm": "./scripts/get-latest-wasm-bundle.sh", "fetch:wasm": "./scripts/get-latest-wasm-bundle.sh",
"fetch:wasm:windows": "./scripts/get-latest-wasm-bundle.ps1", "fetch:wasm:windows": "./scripts/get-latest-wasm-bundle.ps1",
"fetch:samples": "rm -rf public/kcl-samples* && curl -L -o public/kcl-samples.zip https://github.com/KittyCAD/kcl-samples/archive/refs/heads/achalmers/kw-args-xylineto.zip && unzip -o public/kcl-samples.zip -d public && mv public/kcl-samples-* public/kcl-samples", "fetch:samples": "rm -rf public/kcl-samples* && curl -L -o public/kcl-samples.zip https://github.com/KittyCAD/kcl-samples/archive/refs/heads/achalmers/kw-args-xylineto.zip && unzip -o public/kcl-samples.zip -d public && mv public/kcl-samples-* public/kcl-samples",
@ -102,6 +102,7 @@
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\" || echo \"sed for both mac and linux\"", "remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\" || echo \"sed for both mac and linux\"",
"lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src", "lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
"lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src", "lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
"circular-deps": "dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx",
"files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json", "files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
"files:set-notes": "./scripts/set-files-notes.sh", "files:set-notes": "./scripts/set-files-notes.sh",
"files:flip-to-nightly": "./scripts/flip-files-to-nightly.sh", "files:flip-to-nightly": "./scripts/flip-files-to-nightly.sh",
@ -139,7 +140,20 @@
"trailingComma": "es5", "trailingComma": "es5",
"tabWidth": 2, "tabWidth": 2,
"semi": false, "semi": false,
"singleQuote": true "singleQuote": true,
"importOrder": [
"<THIRD_PARTY_MODULES>",
"^@rust/(.*)$",
"^@e2e/(.*)$",
"^@src/(.*)$",
"^[./]"
],
"importOrderSeparation": true,
"importOrderSortSpecifiers": true,
"plugins": [
"@trivago/prettier-plugin-sort-imports",
"prettier-plugin-organize-imports"
]
}, },
"browserslist": { "browserslist": {
"production": [ "production": [
@ -167,6 +181,7 @@
"@playwright/test": "^1.51.1", "@playwright/test": "^1.51.1",
"@testing-library/jest-dom": "^5.14.1", "@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^15.0.2", "@testing-library/react": "^15.0.2",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/diff": "^7.0.2", "@types/diff": "^7.0.2",
"@types/electron": "^1.6.10", "@types/electron": "^1.6.10",
"@types/isomorphic-fetch": "^0.0.39", "@types/isomorphic-fetch": "^0.0.39",
@ -187,6 +202,7 @@
"@vitest/web-worker": "^1.5.0", "@vitest/web-worker": "^1.5.0",
"@xstate/cli": "^0.5.17", "@xstate/cli": "^0.5.17",
"autoprefixer": "^10.4.21", "autoprefixer": "^10.4.21",
"dpdm": "^3.14.0",
"electron": "^34.1.1", "electron": "^34.1.1",
"electron-builder": "^26.0.12", "electron-builder": "^26.0.12",
"eslint": "^8.0.1", "eslint": "^8.0.1",
@ -208,7 +224,8 @@
"pngjs": "^7.0.0", "pngjs": "^7.0.0",
"postcss": "^8.4.43", "postcss": "^8.4.43",
"postinstall-postinstall": "^2.1.0", "postinstall-postinstall": "^2.1.0",
"prettier": "^2.8.8", "prettier": "^3.5.3",
"prettier-plugin-organize-imports": "^4.1.0",
"setimmediate": "^1.0.5", "setimmediate": "^1.0.5",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"ts-node": "^10.0.0", "ts-node": "^10.0.0",

View File

@ -1,6 +1,6 @@
import dts from 'rollup-plugin-dts'
import { lezer } from '@lezer/generator/rollup' import { lezer } from '@lezer/generator/rollup'
import typescript from '@rollup/plugin-typescript' import typescript from '@rollup/plugin-typescript'
import dts from 'rollup-plugin-dts'
export default [ export default [
{ {

View File

@ -1,14 +1,14 @@
// Base CodeMirror language support for kcl. // Base CodeMirror language support for kcl.
import { import {
LRLanguage, LRLanguage,
LanguageSupport, LanguageSupport,
indentNodeProp,
continuedIndent, continuedIndent,
delimitedIndent, delimitedIndent,
foldNodeProp,
foldInside, foldInside,
foldNodeProp,
indentNodeProp,
} from '@codemirror/language' } from '@codemirror/language'
// @ts-ignore: No types available // @ts-ignore: No types available
import { parser } from './kcl.grammar' import { parser } from './kcl.grammar'

View File

@ -1,9 +1,9 @@
import { KclLanguage } from '../src/index'
import { fileTests } from '@lezer/generator/dist/test' import { fileTests } from '@lezer/generator/dist/test'
import * as fs from 'fs' import * as fs from 'fs'
import * as path from 'path' import * as path from 'path'
import { KclLanguage } from '../src/index'
let caseDir = path.dirname(__filename) let caseDir = path.dirname(__filename)
for (let file of fs.readdirSync(caseDir)) { for (let file of fs.readdirSync(caseDir)) {

View File

@ -1,9 +1,8 @@
// Overrides the test options from the modeling-app config. // Overrides the test options from the modeling-app config.
import viteTsconfigPaths from 'vite-tsconfig-paths'
import { defineConfig, configDefaults } from 'vitest/config'
// @ts-ignore: No types available // @ts-ignore: No types available
import { lezer } from '@lezer/generator/rollup' import { lezer } from '@lezer/generator/rollup'
import viteTsconfigPaths from 'vite-tsconfig-paths'
import { defineConfig } from 'vitest/config'
const config = defineConfig({ const config = defineConfig({
test: { test: {

View File

@ -1,4 +1,4 @@
import { encoder, decoder } from '../codec' import { decoder, encoder } from './encode-decode'
export default class Bytes { export default class Bytes {
static encode(input: string): Uint8Array { static encode(input: string): Uint8Array {
@ -10,7 +10,7 @@ export default class Bytes {
} }
static append< static append<
T extends { length: number; set(arr: T, offset: number): void } T extends { length: number; set(arr: T, offset: number): void },
>(constructor: { new (length: number): T }, ...arrays: T[]) { >(constructor: { new (length: number): T }, ...arrays: T[]) {
let totalLength = 0 let totalLength = 0
for (const arr of arrays) { for (const arr of arrays) {

View File

@ -1,10 +1,10 @@
import * as vsrpc from 'vscode-jsonrpc' import * as vsrpc from 'vscode-jsonrpc'
import { Codec } from '.'
import Bytes from './bytes' import Bytes from './bytes'
import PromiseMap from './map'
import Queue from './queue' import Queue from './queue'
import Tracer from './tracer' import Tracer from './tracer'
import PromiseMap from './map' import { Codec } from './utils'
export default class StreamDemuxer extends Queue<Uint8Array> { export default class StreamDemuxer extends Queue<Uint8Array> {
readonly responses: PromiseMap<number | string, vsrpc.ResponseMessage> = readonly responses: PromiseMap<number | string, vsrpc.ResponseMessage> =

View File

@ -0,0 +1,2 @@
export const encoder = new TextEncoder()
export const decoder = new TextDecoder()

View File

@ -1,8 +1,7 @@
import * as jsrpc from 'json-rpc-2.0' import type * as vsrpc from 'vscode-jsonrpc'
import * as vsrpc from 'vscode-jsonrpc'
import Bytes from './bytes'
import StreamDemuxer from './demuxer' import StreamDemuxer from './demuxer'
import { decoder } from './encode-decode'
import Headers from './headers' import Headers from './headers'
import Queue from './queue' import Queue from './queue'
import Tracer from './tracer' import Tracer from './tracer'
@ -12,25 +11,6 @@ export enum LspWorkerEventType {
Call = 'call', Call = 'call',
} }
export const encoder = new TextEncoder()
export const decoder = new TextDecoder()
export class Codec {
static encode(
json: jsrpc.JSONRPCRequest | jsrpc.JSONRPCResponse
): Uint8Array {
const message = JSON.stringify(json)
const delimited = Headers.add(message)
return Bytes.encode(delimited)
}
static decode<T>(data: Uint8Array): T {
const delimited = Bytes.decode(data)
const message = Headers.remove(delimited)
return JSON.parse(message) as T
}
}
// FIXME: tracing efficiency // FIXME: tracing efficiency
export class IntoServer export class IntoServer
extends Queue<Uint8Array> extends Queue<Uint8Array>

View File

@ -1,4 +1,4 @@
import { Message } from 'vscode-languageserver-protocol' import type { Message } from 'vscode-languageserver-protocol'
export default class Tracer { export default class Tracer {
static client(message: string): void { static client(message: string): void {

View File

@ -0,0 +1,20 @@
import type * as jsrpc from 'json-rpc-2.0'
import Bytes from './bytes'
import Headers from './headers'
export class Codec {
static encode(
json: jsrpc.JSONRPCRequest | jsrpc.JSONRPCResponse
): Uint8Array {
const message = JSON.stringify(json)
const delimited = Headers.add(message)
return Bytes.encode(delimited)
}
static decode<T>(data: Uint8Array): T {
const delimited = Bytes.decode(data)
const message = Headers.remove(delimited)
return JSON.parse(message) as T
}
}

View File

@ -1,8 +1,8 @@
import type * as LSP from 'vscode-languageserver-protocol' import type * as LSP from 'vscode-languageserver-protocol'
import { FromServer, IntoServer } from './codec' import type { LanguageServerPlugin } from '../plugin/lsp'
import type { FromServer, IntoServer } from './codec'
import Client from './jsonrpc' import Client from './jsonrpc'
import { LanguageServerPlugin } from '../plugin/lsp'
// https://microsoft.github.io/language-server-protocol/specifications/specification-current/ // https://microsoft.github.io/language-server-protocol/specifications/specification-current/
@ -12,15 +12,15 @@ interface LSPRequestMap {
'textDocument/hover': [LSP.HoverParams, LSP.Hover] 'textDocument/hover': [LSP.HoverParams, LSP.Hover]
'textDocument/completion': [ 'textDocument/completion': [
LSP.CompletionParams, LSP.CompletionParams,
LSP.CompletionItem[] | LSP.CompletionList | null LSP.CompletionItem[] | LSP.CompletionList | null,
] ]
'textDocument/semanticTokens/full': [ 'textDocument/semanticTokens/full': [
LSP.SemanticTokensParams, LSP.SemanticTokensParams,
LSP.SemanticTokens LSP.SemanticTokens,
] ]
'textDocument/formatting': [ 'textDocument/formatting': [
LSP.DocumentFormattingParams, LSP.DocumentFormattingParams,
LSP.TextEdit[] | null LSP.TextEdit[] | null,
] ]
'textDocument/foldingRange': [LSP.FoldingRangeParams, LSP.FoldingRange[]] 'textDocument/foldingRange': [LSP.FoldingRangeParams, LSP.FoldingRange[]]
} }

View File

@ -1,11 +1,12 @@
import * as jsrpc from 'json-rpc-2.0' import * as jsrpc from 'json-rpc-2.0'
import * as LSP from 'vscode-languageserver-protocol' import * as LSP from 'vscode-languageserver-protocol'
import type { FromServer, IntoServer } from './codec'
import { Codec } from './codec/utils'
import { import {
registerServerCapability, registerServerCapability,
unregisterServerCapability, unregisterServerCapability,
} from './server-capability-registration' } from './server-capability-registration'
import { Codec, FromServer, IntoServer } from './codec'
const client_capabilities: LSP.ClientCapabilities = { const client_capabilities: LSP.ClientCapabilities = {
textDocument: { textDocument: {

View File

@ -1,4 +1,4 @@
import { import type {
Registration, Registration,
ServerCapabilities, ServerCapabilities,
Unregistration, Unregistration,

View File

@ -1,36 +1,34 @@
import { foldService } from '@codemirror/language' import { foldService } from '@codemirror/language'
import { Extension, EditorState } from '@codemirror/state' import type { EditorState, Extension } from '@codemirror/state'
import { ViewPlugin } from '@codemirror/view' import { ViewPlugin } from '@codemirror/view'
import type { LanguageServerOptions } from './plugin/lsp'
import { import {
docPathFacet,
LanguageServerPlugin, LanguageServerPlugin,
LanguageServerPluginSpec, LanguageServerPluginSpec,
docPathFacet,
languageId, languageId,
workspaceFolders, workspaceFolders,
LanguageServerOptions,
} from './plugin/lsp' } from './plugin/lsp'
export type { LanguageServerClientOptions } from './client'
export { LanguageServerClient } from './client' export { LanguageServerClient } from './client'
export type { LanguageServerClientOptions } from './client'
export { FromServer, IntoServer, LspWorkerEventType } from './client/codec'
export { Codec } from './client/codec/utils'
export { export {
Codec, lspDiagnosticsEvent,
FromServer, lspFormatCodeEvent,
IntoServer, lspSemanticTokensEvent,
LspWorkerEventType, } from './plugin/annotation'
} from './client/codec'
export type { LanguageServerOptions } from './plugin/lsp'
export { export {
LanguageServerPlugin, LanguageServerPlugin,
LanguageServerPluginSpec, LanguageServerPluginSpec,
docPathFacet, docPathFacet,
languageId, languageId,
workspaceFolders, workspaceFolders,
lspSemanticTokensEvent,
lspDiagnosticsEvent,
lspFormatCodeEvent,
} from './plugin/lsp' } from './plugin/lsp'
export { posToOffset, offsetToPos } from './plugin/util' export type { LanguageServerOptions } from './plugin/lsp'
export { offsetToPos, posToOffset } from './plugin/util'
export function lspPlugin(options: LanguageServerOptions): Extension { export function lspPlugin(options: LanguageServerOptions): Extension {
let plugin: LanguageServerPlugin | null = null let plugin: LanguageServerPlugin | null = null

View File

@ -0,0 +1,12 @@
import { Annotation } from '@codemirror/state'
export enum LspAnnotation {
SemanticTokens = 'semantic-tokens',
FormatCode = 'format-code',
Diagnostics = 'diagnostics',
}
const lspEvent = Annotation.define<LspAnnotation>()
export const lspSemanticTokensEvent = lspEvent.of(LspAnnotation.SemanticTokens)
export const lspFormatCodeEvent = lspEvent.of(LspAnnotation.FormatCode)
export const lspDiagnosticsEvent = lspEvent.of(LspAnnotation.Diagnostics)

View File

@ -9,17 +9,18 @@ import {
prevSnippetField, prevSnippetField,
startCompletion, startCompletion,
} from '@codemirror/autocomplete' } from '@codemirror/autocomplete'
import { Prec, Extension } from '@codemirror/state' import { syntaxTree } from '@codemirror/language'
import { EditorView, keymap, KeyBinding, ViewPlugin } from '@codemirror/view' import type { Extension } from '@codemirror/state'
import { Prec } from '@codemirror/state'
import type { EditorView, KeyBinding, ViewPlugin } from '@codemirror/view'
import { keymap } from '@codemirror/view'
import { import {
CompletionItemKind, CompletionItemKind,
CompletionTriggerKind, CompletionTriggerKind,
} from 'vscode-languageserver-protocol' } from 'vscode-languageserver-protocol'
import { LanguageServerPlugin } from './lsp' import type { LanguageServerPlugin } from './lsp'
import { offsetToPos } from './util' import { offsetToPos } from './util'
import { syntaxTree } from '@codemirror/language'
export const CompletionItemKindMap = Object.fromEntries( export const CompletionItemKindMap = Object.fromEntries(
Object.entries(CompletionItemKind).map(([key, value]) => [value, key]) Object.entries(CompletionItemKind).map(([key, value]) => [value, key])

View File

@ -1,7 +1,9 @@
import { Extension, Prec } from '@codemirror/state' import type { Extension } from '@codemirror/state'
import { EditorView, keymap, KeyBinding, ViewPlugin } from '@codemirror/view' import { Prec } from '@codemirror/state'
import type { EditorView, KeyBinding, ViewPlugin } from '@codemirror/view'
import { keymap } from '@codemirror/view'
import { LanguageServerPlugin } from './lsp' import type { LanguageServerPlugin } from './lsp'
export default function lspFormatExt( export default function lspFormatExt(
plugin: ViewPlugin<LanguageServerPlugin> plugin: ViewPlugin<LanguageServerPlugin>

View File

@ -1,12 +1,8 @@
import { Extension } from '@codemirror/state' import type { Extension } from '@codemirror/state'
import { import type { ViewPlugin } from '@codemirror/view'
hoverTooltip, import { EditorView, hoverTooltip, tooltips } from '@codemirror/view'
tooltips,
ViewPlugin,
EditorView,
} from '@codemirror/view'
import { LanguageServerPlugin } from './lsp' import type { LanguageServerPlugin } from './lsp'
import { offsetToPos } from './util' import { offsetToPos } from './util'
export default function lspHoverExt( export default function lspHoverExt(

View File

@ -1,5 +1,5 @@
import { indentService } from '@codemirror/language' import { indentService } from '@codemirror/language'
import { Extension } from '@codemirror/state' import type { Extension } from '@codemirror/state'
export default function lspIndentExt(): Extension { export default function lspIndentExt(): Extension {
// Match the indentation of the previous line (if present). // Match the indentation of the previous line (if present).

View File

@ -4,39 +4,34 @@ import type {
CompletionResult, CompletionResult,
} from '@codemirror/autocomplete' } from '@codemirror/autocomplete'
import { completeFromList, snippetCompletion } from '@codemirror/autocomplete' import { completeFromList, snippetCompletion } from '@codemirror/autocomplete'
import {
Facet,
StateEffect,
Extension,
Transaction,
Annotation,
} from '@codemirror/state'
import type {
ViewUpdate,
PluginValue,
PluginSpec,
ViewPlugin,
} from '@codemirror/view'
import { EditorView, Tooltip } from '@codemirror/view'
import { linter } from '@codemirror/lint' import { linter } from '@codemirror/lint'
import type { Extension, StateEffect } from '@codemirror/state'
import type { PublishDiagnosticsParams } from 'vscode-languageserver-protocol' import { Facet, Transaction } from '@codemirror/state'
import type {
EditorView,
PluginSpec,
PluginValue,
Tooltip,
ViewPlugin,
ViewUpdate,
} from '@codemirror/view'
import type * as LSP from 'vscode-languageserver-protocol' import type * as LSP from 'vscode-languageserver-protocol'
import { import type {
DiagnosticSeverity,
CompletionTriggerKind, CompletionTriggerKind,
PublishDiagnosticsParams,
} from 'vscode-languageserver-protocol' } from 'vscode-languageserver-protocol'
import { DiagnosticSeverity } from 'vscode-languageserver-protocol'
import { URI } from 'vscode-uri' import { URI } from 'vscode-uri'
import { LanguageServerClient } from '../client' import type { LanguageServerClient } from '../client'
import { CompletionItemKindMap } from './autocomplete' import { lspFormatCodeEvent, lspSemanticTokensEvent } from './annotation'
import { addToken, SemanticToken } from './semantic-tokens' import lspAutocompleteExt, { CompletionItemKindMap } from './autocomplete'
import { posToOffset, formatMarkdownContents } from './util'
import lspAutocompleteExt from './autocomplete'
import lspHoverExt from './hover'
import lspFormatExt from './format' import lspFormatExt from './format'
import lspHoverExt from './hover'
import lspIndentExt from './indent' import lspIndentExt from './indent'
import lspSemanticTokensExt from './semantic-tokens' import type { SemanticToken } from './semantic-tokens'
import lspSemanticTokensExt, { addToken } from './semantic-tokens'
import { formatMarkdownContents, posToOffset } from './util'
const useLast = (values: readonly any[]) => values.reduce((_, v) => v, '') const useLast = (values: readonly any[]) => values.reduce((_, v) => v, '')
export const docPathFacet = Facet.define<string, string>({ export const docPathFacet = Facet.define<string, string>({
@ -48,17 +43,6 @@ export const workspaceFolders = Facet.define<
LSP.WorkspaceFolder[] LSP.WorkspaceFolder[]
>({ combine: useLast }) >({ combine: useLast })
export enum LspAnnotation {
SemanticTokens = 'semantic-tokens',
FormatCode = 'format-code',
Diagnostics = 'diagnostics',
}
const lspEvent = Annotation.define<LspAnnotation>()
export const lspSemanticTokensEvent = lspEvent.of(LspAnnotation.SemanticTokens)
export const lspFormatCodeEvent = lspEvent.of(LspAnnotation.FormatCode)
export const lspDiagnosticsEvent = lspEvent.of(LspAnnotation.Diagnostics)
export interface LanguageServerOptions { export interface LanguageServerOptions {
// We assume this is the main project directory, we are currently working in. // We assume this is the main project directory, we are currently working in.
workspaceFolders: LSP.WorkspaceFolder[] workspaceFolders: LSP.WorkspaceFolder[]
@ -98,7 +82,10 @@ export class LanguageServerPlugin implements PluginValue {
// document. // document.
private sendScheduled: number | null = null private sendScheduled: number | null = null
constructor(options: LanguageServerOptions, private view: EditorView) { constructor(
options: LanguageServerOptions,
private view: EditorView
) {
this.client = options.client this.client = options.client
this.documentVersion = 0 this.documentVersion = 0

View File

@ -1,10 +1,12 @@
import { highlightingFor } from '@codemirror/language' import { highlightingFor } from '@codemirror/language'
import { StateEffect, StateField, Extension } from '@codemirror/state' import type { Extension } from '@codemirror/state'
import { EditorView, Decoration, DecorationSet } from '@codemirror/view' import { StateEffect, StateField } from '@codemirror/state'
import type { DecorationSet } from '@codemirror/view'
import { Decoration, EditorView } from '@codemirror/view'
import type { Tag } from '@lezer/highlight'
import { tags } from '@lezer/highlight'
import { Tag, tags } from '@lezer/highlight' import { lspSemanticTokensEvent } from './annotation'
import { lspSemanticTokensEvent } from './lsp'
export interface SemanticToken { export interface SemanticToken {
from: number from: number

View File

@ -1,7 +1,8 @@
import { Text } from '@codemirror/state' import type { Text } from '@codemirror/state'
import { Marked, MarkedOptions } from '@ts-stack/markdown' import type { MarkedOptions } from '@ts-stack/markdown'
import { Marked } from '@ts-stack/markdown'
import type * as LSP from 'vscode-languageserver-protocol' import type * as LSP from 'vscode-languageserver-protocol'
import { isArray } from '../lib/utils' import { isArray } from '../lib/utils'
// takes a function and executes it after the wait time, if the function is called again before the wait time is up, the timer is reset // takes a function and executes it after the wait time, if the function is called again before the wait time is up, the timer is reset

View File

@ -1,10 +1,11 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */ /* eslint suggest-no-throw/suggest-no-throw: 0 */
import * as vscode from 'vscode'
import * as os from 'os'
import type { Config } from './config'
import { log, isValidExecutable } from './util'
import type { PersistentState } from './persistent_state'
import { exec } from 'child_process' import { exec } from 'child_process'
import * as os from 'os'
import * as vscode from 'vscode'
import type { Config } from './config'
import type { PersistentState } from './persistent_state'
import { isValidExecutable, log } from './util'
export async function bootstrap( export async function bootstrap(
context: vscode.ExtensionContext, context: vscode.ExtensionContext,

View File

@ -1,6 +1,6 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */ /* eslint suggest-no-throw/suggest-no-throw: 0 */
import * as lc from 'vscode-languageclient/node'
import type * as vscode from 'vscode' import type * as vscode from 'vscode'
import * as lc from 'vscode-languageclient/node'
export async function createClient( export async function createClient(
traceOutputChannel: vscode.OutputChannel, traceOutputChannel: vscode.OutputChannel,

View File

@ -1,8 +1,8 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */ /* eslint suggest-no-throw/suggest-no-throw: 0 */
import { spawnSync } from 'child_process'
import * as vscode from 'vscode' import * as vscode from 'vscode'
import type { Cmd, CtxInit } from './ctx' import type { Cmd, CtxInit } from './ctx'
import { spawnSync } from 'child_process'
export function serverVersion(ctx: CtxInit): Cmd { export function serverVersion(ctx: CtxInit): Cmd {
return async () => { return async () => {

View File

@ -1,10 +1,11 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */ /* eslint suggest-no-throw/suggest-no-throw: 0 */
import * as Is from 'vscode-languageclient/lib/common/utils/is'
import * as os from 'os' import * as os from 'os'
import * as path from 'path' import * as path from 'path'
import * as vscode from 'vscode' import * as vscode from 'vscode'
import { log, type Env } from './util' import * as Is from 'vscode-languageclient/lib/common/utils/is'
import { expectNotUndefined, unwrapUndefinable } from './undefinable' import { expectNotUndefined, unwrapUndefinable } from './undefinable'
import { type Env, log } from './util'
export type RunnableEnvCfgItem = { export type RunnableEnvCfgItem = {
mask?: string mask?: string

View File

@ -1,20 +1,20 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */ /* eslint suggest-no-throw/suggest-no-throw: 0 */
import * as vscode from 'vscode' import * as vscode from 'vscode'
import type * as lc from 'vscode-languageclient/node' import type * as lc from 'vscode-languageclient/node'
import { TransportKind } from 'vscode-languageclient/node'
import { Config, prepareVSCodeConfig } from './config' import { bootstrap } from './bootstrap'
import { createClient } from './client' import { createClient } from './client'
import { import { Config, prepareVSCodeConfig } from './config'
isKclDocument,
isKclEditor,
LazyOutputChannel,
log,
type KclEditor,
} from './util'
import type { ServerStatusParams } from './lsp_ext' import type { ServerStatusParams } from './lsp_ext'
import { PersistentState } from './persistent_state' import { PersistentState } from './persistent_state'
import { bootstrap } from './bootstrap' import {
import { TransportKind } from 'vscode-languageclient/node' type KclEditor,
LazyOutputChannel,
isKclDocument,
isKclEditor,
log,
} from './util'
// We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if // We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if
// only those are in use. We use "Empty" to represent these scenarios // only those are in use. We use "Empty" to represent these scenarios

View File

@ -1,5 +1,6 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */ /* eslint suggest-no-throw/suggest-no-throw: 0 */
import type * as vscode from 'vscode' import type * as vscode from 'vscode'
import { log } from './util' import { log } from './util'
export class PersistentState { export class PersistentState {

View File

@ -1,6 +1,5 @@
import * as path from 'path'
import { runTests } from '@vscode/test-electron' import { runTests } from '@vscode/test-electron'
import * as path from 'path'
async function main() { async function main() {
try { try {

View File

@ -1,8 +1,8 @@
import * as assert from 'assert' import * as assert from 'assert'
// You can import and use all API from the 'vscode' module // You can import and use all API from the 'vscode' module
// as well as import your extension to test it // as well as import your extension to test it
import * as vscode from 'vscode' import * as vscode from 'vscode'
// import * as myExtension from '../../extension'; // import * as myExtension from '../../extension';
suite('Extension Test Suite', () => { suite('Extension Test Suite', () => {

View File

@ -1,4 +1,5 @@
import * as path from 'path' import * as path from 'path'
const Mocha = require('mocha') const Mocha = require('mocha')
const { glob } = require('glob') const { glob } = require('glob')

View File

@ -1,8 +1,8 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */ /* eslint suggest-no-throw/suggest-no-throw: 0 */
import * as vscode from 'vscode'
import { strict as nativeAssert } from 'assert' import { strict as nativeAssert } from 'assert'
import { exec, type ExecOptions, spawnSync } from 'child_process' import { type ExecOptions, exec, spawnSync } from 'child_process'
import { inspect } from 'util' import { inspect } from 'util'
import * as vscode from 'vscode'
export interface Env { export interface Env {
[name: string]: string [name: string]: string

View File

@ -1227,7 +1227,7 @@ impl Node<CallExpressionKw> {
)); ));
} }
let op = if func.feature_tree_operation() { let op = if func.feature_tree_operation() && !ctx.is_isolated_execution().await {
let op_labeled_args = args let op_labeled_args = args
.kw_args .kw_args
.labeled .labeled
@ -1297,6 +1297,7 @@ impl Node<CallExpressionKw> {
// exec_state. // exec_state.
let func = fn_name.get_result(exec_state, ctx).await?.clone(); let func = fn_name.get_result(exec_state, ctx).await?.clone();
if !ctx.is_isolated_execution().await {
// Track call operation. // Track call operation.
let op_labeled_args = args let op_labeled_args = args
.kw_args .kw_args
@ -1315,6 +1316,7 @@ impl Node<CallExpressionKw> {
labeled_args: op_labeled_args, labeled_args: op_labeled_args,
source_range: callsite, source_range: callsite,
}); });
}
let Some(fn_src) = func.as_fn() else { let Some(fn_src) = func.as_fn() else {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
@ -1341,8 +1343,10 @@ impl Node<CallExpressionKw> {
}) })
})?; })?;
if !ctx.is_isolated_execution().await {
// Track return operation. // Track return operation.
exec_state.global.operations.push(Operation::UserDefinedFunctionReturn); exec_state.global.operations.push(Operation::UserDefinedFunctionReturn);
}
Ok(result) Ok(result)
} }
@ -1379,7 +1383,7 @@ impl Node<CallExpression> {
)); ));
} }
let op = if func.feature_tree_operation() { let op = if func.feature_tree_operation() && !ctx.is_isolated_execution().await {
let op_labeled_args = func let op_labeled_args = func
.args(false) .args(false)
.iter() .iter()
@ -1437,6 +1441,7 @@ impl Node<CallExpression> {
// exec_state. // exec_state.
let func = fn_name.get_result(exec_state, ctx).await?.clone(); let func = fn_name.get_result(exec_state, ctx).await?.clone();
if !ctx.is_isolated_execution().await {
// Track call operation. // Track call operation.
exec_state.global.operations.push(Operation::UserDefinedFunctionCall { exec_state.global.operations.push(Operation::UserDefinedFunctionCall {
name: Some(fn_name.to_string()), name: Some(fn_name.to_string()),
@ -1446,6 +1451,7 @@ impl Node<CallExpression> {
labeled_args: Default::default(), labeled_args: Default::default(),
source_range: callsite, source_range: callsite,
}); });
}
let Some(fn_src) = func.as_fn() else { let Some(fn_src) = func.as_fn() else {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
@ -1471,8 +1477,10 @@ impl Node<CallExpression> {
}) })
})?; })?;
if !ctx.is_isolated_execution().await {
// Track return operation. // Track return operation.
exec_state.global.operations.push(Operation::UserDefinedFunctionReturn); exec_state.global.operations.push(Operation::UserDefinedFunctionReturn);
}
Ok(result) Ok(result)
} }

View File

@ -498,9 +498,13 @@ impl ExecutorContext {
self.context_type == ContextType::Mock || self.context_type == ContextType::MockCustomForwarded self.context_type == ContextType::Mock || self.context_type == ContextType::MockCustomForwarded
} }
pub async fn is_isolated_execution(&self) -> bool {
self.engine.execution_kind().await.is_isolated()
}
/// Returns true if we should not send engine commands for any reason. /// Returns true if we should not send engine commands for any reason.
pub async fn no_engine_commands(&self) -> bool { pub async fn no_engine_commands(&self) -> bool {
self.is_mock() || self.engine.execution_kind().await.is_isolated() self.is_mock() || self.is_isolated_execution().await
} }
pub async fn send_clear_scene( pub async fn send_clear_scene(

View File

@ -113,15 +113,19 @@ pub struct AppSettings {
pub onboarding_status: OnboardingStatus, pub onboarding_status: OnboardingStatus,
/// Backwards compatible project directory setting. /// Backwards compatible project directory setting.
#[serde(default, alias = "projectDirectory", skip_serializing_if = "Option::is_none")] #[serde(default, alias = "projectDirectory", skip_serializing_if = "Option::is_none")]
#[ts(skip)]
pub project_directory: Option<std::path::PathBuf>, pub project_directory: Option<std::path::PathBuf>,
/// Backwards compatible theme setting. /// Backwards compatible theme setting.
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(skip)]
pub theme: Option<AppTheme>, pub theme: Option<AppTheme>,
/// The hue of the primary theme color for the app. /// The hue of the primary theme color for the app.
#[serde(default, skip_serializing_if = "Option::is_none", alias = "themeColor")] #[serde(default, skip_serializing_if = "Option::is_none", alias = "themeColor")]
#[ts(skip)]
pub theme_color: Option<FloatOrInt>, pub theme_color: Option<FloatOrInt>,
/// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled. /// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled.
#[serde(default, alias = "enableSSAO", skip_serializing_if = "Option::is_none")] #[serde(default, alias = "enableSSAO", skip_serializing_if = "Option::is_none")]
#[ts(skip)]
pub enable_ssao: Option<bool>, pub enable_ssao: Option<bool>,
/// Permanently dismiss the banner warning to download the desktop app. /// Permanently dismiss the banner warning to download the desktop app.
/// This setting only applies to the web app. And is temporary until we have Linux support. /// This setting only applies to the web app. And is temporary until we have Linux support.
@ -285,6 +289,7 @@ pub struct ModelingSettings {
/// of the app to aid in development. /// of the app to aid in development.
/// Remove this when we remove backwards compatibility with the old settings file. /// Remove this when we remove backwards compatibility with the old settings file.
#[serde(default, alias = "showDebugPanel", skip_serializing_if = "is_default")] #[serde(default, alias = "showDebugPanel", skip_serializing_if = "is_default")]
#[ts(skip)]
pub show_debug_panel: bool, pub show_debug_panel: bool,
/// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled. /// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled.
#[serde(default, skip_serializing_if = "is_default")] #[serde(default, skip_serializing_if = "is_default")]

View File

@ -94,9 +94,11 @@ pub struct ProjectAppSettings {
pub onboarding_status: OnboardingStatus, pub onboarding_status: OnboardingStatus,
/// The hue of the primary theme color for the app. /// The hue of the primary theme color for the app.
#[serde(default, skip_serializing_if = "Option::is_none", alias = "themeColor")] #[serde(default, skip_serializing_if = "Option::is_none", alias = "themeColor")]
#[ts(skip)]
pub theme_color: Option<FloatOrInt>, pub theme_color: Option<FloatOrInt>,
/// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled. /// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled.
#[serde(default, alias = "enableSSAO", skip_serializing_if = "Option::is_none")] #[serde(default, alias = "enableSSAO", skip_serializing_if = "Option::is_none")]
#[ts(skip)]
pub enable_ssao: Option<bool>, pub enable_ssao: Option<bool>,
/// Permanently dismiss the banner warning to download the desktop app. /// Permanently dismiss the banner warning to download the desktop app.
/// This setting only applies to the web app. And is temporary until we have Linux support. /// This setting only applies to the web app. And is temporary until we have Linux support.
@ -143,6 +145,7 @@ pub struct ProjectModelingSettings {
/// of the app to aid in development. /// of the app to aid in development.
/// Remove this when we remove backwards compatibility with the old settings file. /// Remove this when we remove backwards compatibility with the old settings file.
#[serde(default, alias = "showDebugPanel", skip_serializing_if = "is_default")] #[serde(default, alias = "showDebugPanel", skip_serializing_if = "is_default")]
#[ts(skip)]
pub show_debug_panel: bool, pub show_debug_panel: bool,
/// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled. /// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled.
#[serde(default, skip_serializing_if = "is_default")] #[serde(default, skip_serializing_if = "is_default")]

View File

@ -28,11 +28,19 @@ pub async fn scale(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
]), ]),
exec_state, exec_state,
)?; )?;
let scale_x = args.get_kw_arg("x")?; let scale_x = args.get_kw_arg_opt("x")?;
let scale_y = args.get_kw_arg("y")?; let scale_y = args.get_kw_arg_opt("y")?;
let scale_z = args.get_kw_arg("z")?; let scale_z = args.get_kw_arg_opt("z")?;
let global = args.get_kw_arg_opt("global")?; let global = args.get_kw_arg_opt("global")?;
// Ensure at least one scale value is provided.
if scale_x.is_none() && scale_y.is_none() && scale_z.is_none() {
return Err(KclError::Semantic(KclErrorDetails {
message: "Expected `x`, `y`, or `z` to be provided.".to_string(),
source_ranges: vec![args.source_range],
}));
}
let objects = inner_scale(objects, scale_x, scale_y, scale_z, global, exec_state, args).await?; let objects = inner_scale(objects, scale_x, scale_y, scale_z, global, exec_state, args).await?;
Ok(objects.into()) Ok(objects.into())
} }
@ -85,8 +93,6 @@ pub async fn scale(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// |> hole(pipeHole, %) /// |> hole(pipeHole, %)
/// |> sweep(path = sweepPath) /// |> sweep(path = sweepPath)
/// |> scale( /// |> scale(
/// x = 1.0,
/// y = 1.0,
/// z = 2.5, /// z = 2.5,
/// ) /// )
/// ``` /// ```
@ -98,8 +104,6 @@ pub async fn scale(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// ///
/// cube /// cube
/// |> scale( /// |> scale(
/// x = 1.0,
/// y = 1.0,
/// z = 2.5, /// z = 2.5,
/// ) /// )
/// ``` /// ```
@ -135,7 +139,7 @@ pub async fn scale(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// parts = sweep([rectangleSketch, circleSketch], path = sweepPath) /// parts = sweep([rectangleSketch, circleSketch], path = sweepPath)
/// ///
/// // Scale the sweep. /// // Scale the sweep.
/// scale(parts, x = 1.0, y = 1.0, z = 0.5) /// scale(parts, z = 0.5)
/// ``` /// ```
#[stdlib { #[stdlib {
name = "scale", name = "scale",
@ -144,17 +148,17 @@ pub async fn scale(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
unlabeled_first = true, unlabeled_first = true,
args = { args = {
objects = {docs = "The solid, sketch, or set of solids or sketches to scale."}, objects = {docs = "The solid, sketch, or set of solids or sketches to scale."},
x = {docs = "The scale factor for the x axis."}, x = {docs = "The scale factor for the x axis. Default is 1 if not provided.", include_in_snippet = true},
y = {docs = "The scale factor for the y axis."}, y = {docs = "The scale factor for the y axis. Default is 1 if not provided.", include_in_snippet = true},
z = {docs = "The scale factor for the z axis."}, z = {docs = "The scale factor for the z axis. Default is 1 if not provided.", include_in_snippet = true},
global = {docs = "If true, the transform is applied in global space. The origin of the model will move. By default, the transform is applied in local sketch axis, therefore the origin will not move."} global = {docs = "If true, the transform is applied in global space. The origin of the model will move. By default, the transform is applied in local sketch axis, therefore the origin will not move."}
} }
}] }]
async fn inner_scale( async fn inner_scale(
objects: SolidOrSketchOrImportedGeometry, objects: SolidOrSketchOrImportedGeometry,
x: f64, x: Option<f64>,
y: f64, y: Option<f64>,
z: f64, z: Option<f64>,
global: Option<bool>, global: Option<bool>,
exec_state: &mut ExecState, exec_state: &mut ExecState,
args: Args, args: Args,
@ -174,7 +178,11 @@ async fn inner_scale(
object_id, object_id,
transforms: vec![shared::ComponentTransform { transforms: vec![shared::ComponentTransform {
scale: Some(shared::TransformBy::<Point3d<f64>> { scale: Some(shared::TransformBy::<Point3d<f64>> {
property: Point3d { x, y, z }, property: Point3d {
x: x.unwrap_or(1.0),
y: y.unwrap_or(1.0),
z: z.unwrap_or(1.0),
},
set: false, set: false,
is_local: !global.unwrap_or(false), is_local: !global.unwrap_or(false),
}), }),
@ -201,11 +209,19 @@ pub async fn translate(exec_state: &mut ExecState, args: Args) -> Result<KclValu
]), ]),
exec_state, exec_state,
)?; )?;
let translate_x = args.get_kw_arg("x")?; let translate_x = args.get_kw_arg_opt("x")?;
let translate_y = args.get_kw_arg("y")?; let translate_y = args.get_kw_arg_opt("y")?;
let translate_z = args.get_kw_arg("z")?; let translate_z = args.get_kw_arg_opt("z")?;
let global = args.get_kw_arg_opt("global")?; let global = args.get_kw_arg_opt("global")?;
// Ensure at least one translation value is provided.
if translate_x.is_none() && translate_y.is_none() && translate_z.is_none() {
return Err(KclError::Semantic(KclErrorDetails {
message: "Expected `x`, `y`, or `z` to be provided.".to_string(),
source_ranges: vec![args.source_range],
}));
}
let objects = inner_translate(objects, translate_x, translate_y, translate_z, global, exec_state, args).await?; let objects = inner_translate(objects, translate_x, translate_y, translate_z, global, exec_state, args).await?;
Ok(objects.into()) Ok(objects.into())
} }
@ -326,7 +342,6 @@ pub async fn translate(exec_state: &mut ExecState, args: Args) -> Result<KclValu
/// |> translate( /// |> translate(
/// x = 5, /// x = 5,
/// y = 5, /// y = 5,
/// z = 0,
/// ) /// )
/// |> extrude( /// |> extrude(
/// length = 10, /// length = 10,
@ -349,7 +364,7 @@ pub async fn translate(exec_state: &mut ExecState, args: Args) -> Result<KclValu
/// profile001 = square() /// profile001 = square()
/// ///
/// profile002 = square() /// profile002 = square()
/// |> translate(x = 0, y = 0, z = 20) /// |> translate(z = 20)
/// |> rotate(axis = [0, 0, 1.0], angle = 45) /// |> rotate(axis = [0, 0, 1.0], angle = 45)
/// ///
/// loft([profile001, profile002]) /// loft([profile001, profile002])
@ -361,17 +376,17 @@ pub async fn translate(exec_state: &mut ExecState, args: Args) -> Result<KclValu
unlabeled_first = true, unlabeled_first = true,
args = { args = {
objects = {docs = "The solid, sketch, or set of solids or sketches to move."}, objects = {docs = "The solid, sketch, or set of solids or sketches to move."},
x = {docs = "The amount to move the solid or sketch along the x axis."}, x = {docs = "The amount to move the solid or sketch along the x axis. Defaults to 0 if not provided.", include_in_snippet = true},
y = {docs = "The amount to move the solid or sketch along the y axis."}, y = {docs = "The amount to move the solid or sketch along the y axis. Defaults to 0 if not provided.", include_in_snippet = true},
z = {docs = "The amount to move the solid or sketch along the z axis."}, z = {docs = "The amount to move the solid or sketch along the z axis. Defaults to 0 if not provided.", include_in_snippet = true},
global = {docs = "If true, the transform is applied in global space. The origin of the model will move. By default, the transform is applied in local sketch axis, therefore the origin will not move."} global = {docs = "If true, the transform is applied in global space. The origin of the model will move. By default, the transform is applied in local sketch axis, therefore the origin will not move."}
} }
}] }]
async fn inner_translate( async fn inner_translate(
objects: SolidOrSketchOrImportedGeometry, objects: SolidOrSketchOrImportedGeometry,
x: f64, x: Option<f64>,
y: f64, y: Option<f64>,
z: f64, z: Option<f64>,
global: Option<bool>, global: Option<bool>,
exec_state: &mut ExecState, exec_state: &mut ExecState,
args: Args, args: Args,
@ -392,9 +407,9 @@ async fn inner_translate(
transforms: vec![shared::ComponentTransform { transforms: vec![shared::ComponentTransform {
translate: Some(shared::TransformBy::<Point3d<LengthUnit>> { translate: Some(shared::TransformBy::<Point3d<LengthUnit>> {
property: shared::Point3d { property: shared::Point3d {
x: LengthUnit(x), x: LengthUnit(x.unwrap_or_default()),
y: LengthUnit(y), y: LengthUnit(y.unwrap_or_default()),
z: LengthUnit(z), z: LengthUnit(z.unwrap_or_default()),
}, },
set: false, set: false,
is_local: !global.unwrap_or(false), is_local: !global.unwrap_or(false),
@ -1001,4 +1016,34 @@ sweepSketch = startSketchOn('XY')
.to_string() .to_string()
); );
} }
#[tokio::test(flavor = "multi_thread")]
async fn test_translate_no_args() {
let ast = PIPE.to_string()
+ r#"
|> translate(
)
"#;
let result = parse_execute(&ast).await;
assert!(result.is_err());
assert_eq!(
result.unwrap_err().message(),
r#"Expected `x`, `y`, or `z` to be provided."#.to_string()
);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_scale_no_args() {
let ast = PIPE.to_string()
+ r#"
|> scale(
)
"#;
let result = parse_execute(&ast).await;
assert!(result.is_err());
assert_eq!(
result.unwrap_err().message(),
r#"Expected `x`, `y`, or `z` to be provided."#.to_string()
);
}
} }

View File

@ -2,43 +2,4 @@
source: kcl-lib/src/simulation_tests.rs source: kcl-lib/src/simulation_tests.rs
description: Operations executed import_function_not_sketch.kcl description: Operations executed import_function_not_sketch.kcl
--- ---
[ []
{
"labeledArgs": {
"data": {
"value": {
"type": "String",
"value": "XY"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"labeledArgs": {
"axis": {
"value": {
"type": "String",
"value": "y"
},
"sourceRange": []
}
},
"name": "revolve",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
}
]

View File

@ -2,86 +2,4 @@
source: kcl-lib/src/simulation_tests.rs source: kcl-lib/src/simulation_tests.rs
description: Operations executed import_side_effect.kcl description: Operations executed import_side_effect.kcl
--- ---
[ []
{
"labeledArgs": {
"data": {
"value": {
"type": "String",
"value": "XY"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"type": "UserDefinedFunctionCall",
"name": "circle",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {
"center": {
"value": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"sourceRange": []
},
"radius": {
"value": {
"type": "Number",
"value": 10.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
}
]

View File

@ -3,66 +3,6 @@ source: kcl-lib/src/simulation_tests.rs
description: Operations executed multi-axis-robot.kcl description: Operations executed multi-axis-robot.kcl
--- ---
[ [
{
"type": "UserDefinedFunctionCall",
"name": "sin",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
},
{
"type": "UserDefinedFunctionCall",
"name": "cos",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
},
{
"type": "UserDefinedFunctionCall",
"name": "sin",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
},
{
"type": "UserDefinedFunctionCall",
"name": "cos",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
},
{ {
"labeledArgs": { "labeledArgs": {
"data": { "data": {

View File

@ -3,36 +3,6 @@ source: kcl-lib/src/simulation_tests.rs
description: Operations executed pipe-flange-assembly.kcl description: Operations executed pipe-flange-assembly.kcl
--- ---
[ [
{
"type": "UserDefinedFunctionCall",
"name": "cos",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
},
{
"type": "UserDefinedFunctionCall",
"name": "cos",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
},
{ {
"type": "UserDefinedFunctionCall", "type": "UserDefinedFunctionCall",
"name": "flange", "name": "flange",

View File

@ -349,352 +349,6 @@ description: Operations executed walkie-talkie.kcl
{ {
"type": "UserDefinedFunctionReturn" "type": "UserDefinedFunctionReturn"
}, },
{
"type": "UserDefinedFunctionCall",
"name": "body",
"functionSourceRange": [
359,
2786,
6
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"labeledArgs": {
"data": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 0.325,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
},
"tags": {
"value": {
"type": "Array",
"value": [
{
"type": "Uuid",
"value": "[uuid]"
},
{
"type": "Uuid",
"value": "[uuid]"
},
{
"type": "Uuid",
"value": "[uuid]"
},
{
"type": "Uuid",
"value": "[uuid]"
}
]
},
"sourceRange": []
}
},
"name": "chamfer",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"labeledArgs": {
"data": {
"value": {
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
},
"tag": {
"value": {
"type": "String",
"value": "END"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"type": "UserDefinedFunctionCall",
"name": "cos",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
},
{
"type": "UserDefinedFunctionCall",
"name": "cos",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
},
{
"type": "UserDefinedFunctionCall",
"name": "cos",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
},
{
"type": "UserDefinedFunctionCall",
"name": "cos",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": -0.0625,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"labeledArgs": {
"data": {
"value": {
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
},
"tag": {
"value": {
"type": "String",
"value": "start"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": -0.0625,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"labeledArgs": {
"data": {
"value": {
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
},
"tag": {
"value": {
"type": "String",
"value": "start"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": -0.5,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"type": "UserDefinedFunctionReturn"
},
{ {
"type": "UserDefinedFunctionCall", "type": "UserDefinedFunctionCall",
"name": "antenna", "name": "antenna",

View File

@ -3,91 +3,6 @@ source: kcl-lib/src/simulation_tests.rs
description: Operations executed pattern_circular_in_module.kcl description: Operations executed pattern_circular_in_module.kcl
--- ---
[ [
{
"type": "UserDefinedFunctionCall",
"name": "thing",
"functionSourceRange": [
15,
378,
5
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"labeledArgs": {
"data": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
}
},
{
"type": "UserDefinedFunctionReturn"
},
{ {
"type": "UserDefinedFunctionCall", "type": "UserDefinedFunctionCall",
"name": "thing", "name": "thing",

View File

@ -169,175 +169,6 @@ description: Operations executed pattern_linear_in_module.kcl
"sourceRange": [] "sourceRange": []
} }
}, },
{
"type": "UserDefinedFunctionReturn"
},
{
"type": "UserDefinedFunctionCall",
"name": "thing",
"functionSourceRange": [
15,
221,
5
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"labeledArgs": {
"data": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"type": "UserDefinedFunctionCall",
"name": "circle",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {
"center": {
"value": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"sourceRange": []
},
"radius": {
"value": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
}
},
{ {
"type": "UserDefinedFunctionReturn" "type": "UserDefinedFunctionReturn"
} }

View File

@ -3,6 +3,7 @@ name = "kcl-python-bindings"
version = "0.3.57" version = "0.3.57"
edition = "2021" edition = "2021"
repository = "https://github.com/kittycad/modeling-app" repository = "https://github.com/kittycad/modeling-app"
exclude = ["tests/*", "files/*", "venv/*"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib] [lib]

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