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

This commit is contained in:
Paul Tagliamonte
2025-04-01 11:55:02 -04:00
61 changed files with 3007 additions and 715 deletions

View File

@ -17,7 +17,7 @@ circle(@sketch_or_surface: Sketch | Plane | Face, center: Point2d, radius: numbe
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `sketch_or_surface` | [`Sketch`](/docs/kcl/types/Sketch) `|` [`Plane`](/docs/kcl/types/Face) `|` [`Plane`](/docs/kcl/types/Face) | Sketch to extend, or plane or surface to sketch on. | Yes | | `sketch_or_surface` | [`Sketch`](/docs/kcl/types/Sketch) OR [`Plane`](/docs/kcl/types/Plane) OR [`Face`](/docs/kcl/types/Face) | Sketch to extend, or plane or surface to sketch on. | Yes |
| `center` | [`Point2d`](/docs/kcl/types/Point2d) | The center of the circle. | Yes | | `center` | [`Point2d`](/docs/kcl/types/Point2d) | The center of the circle. | Yes |
| `radius` | [`number`](/docs/kcl/types/number) | The radius of the circle. | Yes | | `radius` | [`number`](/docs/kcl/types/number) | The radius of the circle. | Yes |
| [`tag`](/docs/kcl/types/tag) | [`tag`](/docs/kcl/types/tag) | Create a new tag which refers to this circle. | No | | [`tag`](/docs/kcl/types/tag) | [`tag`](/docs/kcl/types/tag) | Create a new tag which refers to this circle. | No |

View File

@ -207302,372 +207302,8 @@
}, },
"definitions": { "definitions": {
"TyF64": { "TyF64": {
"type": "object",
"required": [
"n",
"ty"
],
"properties": {
"n": {
"type": "number", "type": "number",
"format": "double" "format": "double"
},
"ty": {
"$ref": "#/components/schemas/NumericType"
}
}
},
"NumericType": {
"oneOf": [
{
"type": "object",
"oneOf": [
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Count"
]
}
}
},
{
"description": "A unit of length.",
"type": "object",
"oneOf": [
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Mm"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Cm"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"M"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Inches"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Feet"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Yards"
]
}
}
}
],
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Length"
]
}
}
},
{
"description": "A unit of angle.",
"type": "object",
"oneOf": [
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Degrees"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Radians"
]
}
}
}
],
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Angle"
]
}
}
}
],
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Known"
]
}
}
},
{
"type": "object",
"required": [
"angle",
"len",
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Default"
]
},
"len": {
"$ref": "#/components/schemas/UnitLen"
},
"angle": {
"$ref": "#/components/schemas/UnitAngle"
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Unknown"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Any"
]
}
}
}
]
},
"UnitLen": {
"description": "A unit of length.",
"oneOf": [
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Mm"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Cm"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"M"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Inches"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Feet"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Yards"
]
}
}
}
]
},
"UnitAngle": {
"description": "A unit of angle.",
"oneOf": [
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Degrees"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Radians"
]
}
}
}
]
} }
} }
}, },

View File

@ -28,7 +28,7 @@ An extrude plane.
| `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude plane. | No | | `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude plane. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No | | [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
| `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No | | `sourceRange` |`[integer, integer, integer]`| The source range. | No |
---- ----
@ -48,7 +48,7 @@ An extruded arc.
| `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude plane. | No | | `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude plane. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No | | [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
| `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No | | `sourceRange` |`[integer, integer, integer]`| The source range. | No |
---- ----
@ -68,7 +68,7 @@ Geometry metadata.
| `faceId` |[`string`](/docs/kcl/types/string)| The id for the chamfer surface. | No | | `faceId` |[`string`](/docs/kcl/types/string)| The id for the chamfer surface. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No | | [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
| `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No | | `sourceRange` |`[integer, integer, integer]`| The source range. | No |
---- ----
@ -88,7 +88,7 @@ Geometry metadata.
| `faceId` |[`string`](/docs/kcl/types/string)| The id for the fillet surface. | No | | `faceId` |[`string`](/docs/kcl/types/string)| The id for the fillet surface. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No | | [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
| `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No | | `sourceRange` |`[integer, integer, integer]`| The source range. | No |
---- ----

View File

@ -17,6 +17,6 @@ Geometry metadata.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
| `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No | | `sourceRange` |`[integer, integer, integer]`| The source range. | No |

View File

@ -17,7 +17,7 @@ A helix.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `value` |[`string`](/docs/kcl/types/string)| The id of the helix. | No | | `value` |[`string`](/docs/kcl/types/string)| The id of the helix. | No |
| `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The artifact ID. | No | | `artifactId` |[`string`](/docs/kcl/types/string)| The artifact ID. | No |
| `revolutions` |[`number`](/docs/kcl/types/number)| Number of revolutions. | No | | `revolutions` |[`number`](/docs/kcl/types/number)| Number of revolutions. | No |
| `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No | | `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No |
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No | | `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |

View File

@ -285,7 +285,7 @@ Data for an imported geometry.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `Module`| | No | | `type` |enum: `Module`| | No |
| `value` |[`ModuleId`](/docs/kcl/types/ModuleId)| Identifier of a source file. Uses a u32 to keep the size small. | No | | `value` |`integer`| Identifier of a source file. Uses a u32 to keep the size small. | No |
---- ----

View File

@ -17,6 +17,6 @@ Data for polar coordinates.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `angle` |[`number`](/docs/kcl/types/number)| The angle of the line (in degrees). | No | | `angle` |[`number`](/docs/kcl/types/number)| The angle of the line (in degrees). | No |
| `length` |[`TyF64`](/docs/kcl/types/TyF64)| The length of the line. | No | | `length` |[`number`](/docs/kcl/types/number)| The length of the line. | No |

View File

@ -25,7 +25,7 @@ A sketch type.
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `plane`| | No | | `type` |enum: `plane`| | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the plane. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the plane. | No |
| `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The artifact ID. | No | | `artifactId` |[`string`](/docs/kcl/types/string)| The artifact ID. | No |
| `value` |[`PlaneType`](/docs/kcl/types/PlaneType)| Type for a plane. | No | | `value` |[`PlaneType`](/docs/kcl/types/PlaneType)| Type for a plane. | No |
| `origin` |[`Point3d`](/docs/kcl/types/Point3d)| Origin of the plane. | No | | `origin` |[`Point3d`](/docs/kcl/types/Point3d)| Origin of the plane. | No |
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's X axis be? | No | | `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's X axis be? | No |
@ -49,7 +49,7 @@ A face.
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `face`| | No | | `type` |enum: `face`| | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the face. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the face. | No |
| `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The artifact ID. | No | | `artifactId` |[`string`](/docs/kcl/types/string)| The artifact ID. | No |
| `value` |[`string`](/docs/kcl/types/string)| The tag of the face. | No | | `value` |[`string`](/docs/kcl/types/string)| The tag of the face. | No |
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's X axis be? | No | | `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's X axis be? | No |
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's Y axis be? | No | | `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's Y axis be? | No |

View File

@ -1,15 +0,0 @@
---
title: "SourceRange"
excerpt: ""
layout: manual
---
**Type:** `integer` (`uint`)

View File

@ -5,17 +5,11 @@ layout: manual
--- ---
**Type:** `object` **Type:** [`number`](/docs/kcl/types/number) (`double`)
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `n` |[`number`](/docs/kcl/types/number)| | No |
| `ty` |[`NumericType`](/docs/kcl/types/NumericType)| | No |

View File

@ -272,14 +272,6 @@ export const isErrorWhitelisted = (exception: Error) => {
project: 'Google Chrome', project: 'Google Chrome',
foundInSpec: 'e2e/playwright/snapshot-tests.spec.ts', foundInSpec: 'e2e/playwright/snapshot-tests.spec.ts',
}, },
// TODO: fix this error in the code
{
name: 'ReferenceError',
message: 'createNewVariableCheckbox is not defined',
stack: '',
project: 'Google Chrome',
foundInSpec: 'e2e/playwright/testing-constraints.spec.ts',
},
{ {
name: 'Error', name: 'Error',
message: 'The "path" argument must be of type string. Received undefined', message: 'The "path" argument must be of type string. Received undefined',

View File

@ -3476,6 +3476,39 @@ segAng(rectangleSegmentA002),
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = 'X')` const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = 'X')`
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy() expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
// Edit flow
const newAngle = '90'
await toolbar.openPane('feature-tree')
const operationButton = await toolbar.getFeatureTreeOperation(
'Revolve',
0
)
await operationButton.dblclick({ button: 'left' })
await cmdBar.expectState({
commandName: 'Revolve',
currentArgKey: 'angle',
currentArgValue: '360',
headerArguments: {
Angle: '360',
},
highlightedHeaderArg: 'angle',
stage: 'arguments',
})
await page.keyboard.insertText(newAngle)
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Angle: newAngle,
},
commandName: 'Revolve',
})
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await editor.expectEditor.toContain(
newCodeToFind.replace('angle = 360', 'angle = ' + newAngle)
)
}) })
test('revolve surface around edge from an extruded solid2d', async ({ test('revolve surface around edge from an extruded solid2d', async ({
context, context,
@ -3486,26 +3519,22 @@ segAng(rectangleSegmentA002),
toolbar, toolbar,
cmdBar, cmdBar,
}) => { }) => {
const initialCode = ` const initialCode = `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ) |> startProfileAt([-102.57, 101.72], %)
|> startProfileAt([-102.57, 101.72], %) |> angledLine([0, 202.6], %, $rectangleSegmentA001)
|> angledLine([0, 202.6], %, $rectangleSegmentA001) |> angledLine([
|> angledLine([ segAng(rectangleSegmentA001) - 90,
segAng(rectangleSegmentA001) - 90, 202.6
202.6 ], %, $rectangleSegmentB001)
], %, $rectangleSegmentB001) |> angledLine([
|> angledLine([ segAng(rectangleSegmentA001),
segAng(rectangleSegmentA001), -segLen(rectangleSegmentA001)
-segLen(rectangleSegmentA001) ], %, $rectangleSegmentC001)
], %, $rectangleSegmentC001) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()
|> close()
extrude001 = extrude(sketch001, length = 50) extrude001 = extrude(sketch001, length = 50)
sketch002 = startSketchOn(extrude001, rectangleSegmentA001) sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
|> circle( |> circle(center = [-11.34, 10.0], radius = 8.69)
center = [-11.34, 10.0],
radius = 8.69
)
` `
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
@ -3523,9 +3552,49 @@ radius = 8.69
const lineCodeToSelection = `|> angledLine([0, 202.6], %, $rectangleSegmentA001)` const lineCodeToSelection = `|> angledLine([0, 202.6], %, $rectangleSegmentA001)`
await page.getByText(lineCodeToSelection).click() await page.getByText(lineCodeToSelection).click()
await cmdBar.progressCmdBar() await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = getOppositeEdge(rectangleSegmentA001)) ` const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = rectangleSegmentA001)`
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy() await editor.expectEditor.toContain(newCodeToFind)
// Edit flow
const newAngle = '180'
await toolbar.openPane('feature-tree')
const operationButton = await toolbar.getFeatureTreeOperation(
'Revolve',
0
)
await operationButton.dblclick({ button: 'left' })
await cmdBar.expectState({
commandName: 'Revolve',
currentArgKey: 'angle',
currentArgValue: '360',
headerArguments: {
Angle: '360',
},
highlightedHeaderArg: 'angle',
stage: 'arguments',
})
await page.keyboard.insertText(newAngle)
await page.getByRole('button', { name: 'Create new variable' }).click()
await expect(page.getByPlaceholder('Variable name')).toHaveValue(
'angle001'
)
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Angle: newAngle,
},
commandName: 'Revolve',
})
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await editor.expectEditor.toContain('angle001 = ' + newAngle)
await editor.expectEditor.toContain(
newCodeToFind.replace('angle = 360', 'angle = angle001')
)
}) })
test('revolve sketch circle around line segment from startProfileAt sketch', async ({ test('revolve sketch circle around line segment from startProfileAt sketch', async ({
context, context,
@ -3536,11 +3605,10 @@ radius = 8.69
toolbar, toolbar,
cmdBar, cmdBar,
}) => { }) => {
const initialCode = ` const initialCode = `sketch002 = startSketchOn(XY)
sketch002 = startSketchOn(XY)
|> startProfileAt([-2.02, 1.79], %) |> startProfileAt([-2.02, 1.79], %)
|> xLine(length = 2.6) |> xLine(length = 2.6)
sketch001 = startSketchOn('-XY') sketch001 = startSketchOn(-XY)
|> startProfileAt([-0.48, 1.25], %) |> startProfileAt([-0.48, 1.25], %)
|> angledLine([0, 2.38], %, $rectangleSegmentA001) |> angledLine([0, 2.38], %, $rectangleSegmentA001)
|> angledLine([segAng(rectangleSegmentA001) - 90, 2.4], %, $rectangleSegmentB001) |> angledLine([segAng(rectangleSegmentA001) - 90, 2.4], %, $rectangleSegmentB001)
@ -3550,12 +3618,9 @@ radius = 8.69
], %, $rectangleSegmentC001) ], %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
extrude001 = extrude(sketch001, length = 5) extrude001 = extrude(sketch001, length = 5)
sketch003 = startSketchOn(extrude001, 'START') sketch003 = startSketchOn(extrude001, 'START')
|> circle( |> circle(center = [-0.69, 0.56], radius = 0.28)
center = [-0.69, 0.56],
radius = 0.28
)
` `
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
@ -3574,9 +3639,44 @@ radius = 8.69
const lineCodeToSelection = `|> xLine(length = 2.6)` const lineCodeToSelection = `|> xLine(length = 2.6)`
await page.getByText(lineCodeToSelection).click() await page.getByText(lineCodeToSelection).click()
await cmdBar.progressCmdBar() await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
const newCodeToFind = `revolve001 = revolve(sketch003, angle = 360, axis = seg01)` const newCodeToFind = `revolve001 = revolve(sketch003, angle = 360, axis = seg01)`
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy() expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
// Edit flow
const newAngle = '270'
await toolbar.openPane('feature-tree')
const operationButton = await toolbar.getFeatureTreeOperation(
'Revolve',
0
)
await operationButton.dblclick({ button: 'left' })
await cmdBar.expectState({
commandName: 'Revolve',
currentArgKey: 'angle',
currentArgValue: '360',
headerArguments: {
Angle: '360',
},
highlightedHeaderArg: 'angle',
stage: 'arguments',
})
await page.keyboard.insertText(newAngle)
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Angle: newAngle,
},
commandName: 'Revolve',
})
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await editor.expectEditor.toContain(
newCodeToFind.replace('angle = 360', 'angle = ' + newAngle)
)
}) })
}) })

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -160,31 +160,6 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|> xLine(length = segLen(seg_what)) |> xLine(length = segLen(seg_what))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])` |> line(endAbsolute = [profileStartX(%), profileStartY(%)])`
) )
const isChecked = await createNewVariableCheckbox.isChecked()
const addVariable = testName === 'Add variable'
XOR(isChecked, addVariable) && // XOR because no need to click the checkbox if the state is already correct
(await createNewVariableCheckbox.click())
await page
.getByRole('button', { name: 'Add constraining value' })
.click()
// Wait for the codemod to take effect
await expect(page.locator('.cm-content')).toContainText(`angle: -57,`)
await expect(page.locator('.cm-content')).toContainText(
`offset: ${offset},`
)
await pollEditorLinesSelectedLength(page, 2)
const activeLinesContent = await page.locator('.cm-activeLine').all()
await expect(activeLinesContent[0]).toHaveText(
`|> line(end = [74.36, 130.4], tag = $seg01)`
)
await expect(activeLinesContent[1]).toHaveText(`}, %)`)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)
}) })
const u = await getUtils(page) const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })

View File

@ -329,7 +329,7 @@ fn do_stdlib_inner(
let camel_case_arg_name = to_camel_case(&arg_name); let camel_case_arg_name = to_camel_case(&arg_name);
if ty_string != "ExecState" && ty_string != "Args" { if ty_string != "ExecState" && ty_string != "Args" {
let schema = quote! { let schema = quote! {
#docs_crate::cleanup_number_tuples_root(generator.root_schema_for::<#ty_ident>()) generator.root_schema_for::<#ty_ident>()
}; };
arg_types.push(quote! { arg_types.push(quote! {
#docs_crate::StdLibFnArg { #docs_crate::StdLibFnArg {
@ -394,7 +394,7 @@ fn do_stdlib_inner(
let return_type = if !ret_ty_string.is_empty() || ret_ty_string != "()" { let return_type = if !ret_ty_string.is_empty() || ret_ty_string != "()" {
let ret_ty_string = rust_type_to_openapi_type(&ret_ty_string); let ret_ty_string = rust_type_to_openapi_type(&ret_ty_string);
quote! { quote! {
let schema = #docs_crate::cleanup_number_tuples_root(generator.root_schema_for::<#return_type_inner>()); let schema = generator.root_schema_for::<#return_type_inner>();
Some(#docs_crate::StdLibFnArg { Some(#docs_crate::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: #ret_ty_string.to_string(), type_: #ret_ty_string.to_string(),

View File

@ -102,7 +102,7 @@ impl crate::docs::StdLibFn for SomeFn {
vec![crate::docs::StdLibFnArg { vec![crate::docs::StdLibFnArg {
name: "data".to_string(), name: "data".to_string(),
type_: "Foo".to_string(), type_: "Foo".to_string(),
schema: crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<Foo>()), schema: generator.root_schema_for::<Foo>(),
required: true, required: true,
label_required: true, label_required: true,
description: String::new().to_string(), description: String::new().to_string(),
@ -114,7 +114,7 @@ impl crate::docs::StdLibFn for SomeFn {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<i32>()); let schema = generator.root_schema_for::<i32>();
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "i32".to_string(), type_: "i32".to_string(),

View File

@ -102,7 +102,7 @@ impl crate::docs::StdLibFn for SomeFn {
vec![crate::docs::StdLibFnArg { vec![crate::docs::StdLibFnArg {
name: "data".to_string(), name: "data".to_string(),
type_: "string".to_string(), type_: "string".to_string(),
schema: crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<str>()), schema: generator.root_schema_for::<str>(),
required: true, required: true,
label_required: true, label_required: true,
description: String::new().to_string(), description: String::new().to_string(),
@ -114,7 +114,7 @@ impl crate::docs::StdLibFn for SomeFn {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<i32>()); let schema = generator.root_schema_for::<i32>();
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "i32".to_string(), type_: "i32".to_string(),

View File

@ -103,9 +103,7 @@ impl crate::docs::StdLibFn for Show {
vec![crate::docs::StdLibFnArg { vec![crate::docs::StdLibFnArg {
name: "args".to_string(), name: "args".to_string(),
type_: "[number]".to_string(), type_: "[number]".to_string(),
schema: crate::docs::cleanup_number_tuples_root( schema: generator.root_schema_for::<[f64; 2usize]>(),
generator.root_schema_for::<[f64; 2usize]>(),
),
required: true, required: true,
label_required: true, label_required: true,
description: String::new().to_string(), description: String::new().to_string(),
@ -117,7 +115,7 @@ impl crate::docs::StdLibFn for Show {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<f64>()); let schema = generator.root_schema_for::<f64>();
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "number".to_string(), type_: "number".to_string(),

View File

@ -103,7 +103,7 @@ impl crate::docs::StdLibFn for Show {
vec![crate::docs::StdLibFnArg { vec![crate::docs::StdLibFnArg {
name: "args".to_string(), name: "args".to_string(),
type_: "number".to_string(), type_: "number".to_string(),
schema: crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<f64>()), schema: generator.root_schema_for::<f64>(),
required: true, required: true,
label_required: true, label_required: true,
description: String::new().to_string(), description: String::new().to_string(),
@ -115,7 +115,7 @@ impl crate::docs::StdLibFn for Show {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<f64>()); let schema = generator.root_schema_for::<f64>();
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "number".to_string(), type_: "number".to_string(),

View File

@ -104,9 +104,7 @@ impl crate::docs::StdLibFn for MyFunc {
vec![crate::docs::StdLibFnArg { vec![crate::docs::StdLibFnArg {
name: "args".to_string(), name: "args".to_string(),
type_: "kittycad::types::InputFormat".to_string(), type_: "kittycad::types::InputFormat".to_string(),
schema: crate::docs::cleanup_number_tuples_root( schema: generator.root_schema_for::<Option<kittycad::types::InputFormat>>(),
generator.root_schema_for::<Option<kittycad::types::InputFormat>>(),
),
required: false, required: false,
label_required: true, label_required: true,
description: String::new().to_string(), description: String::new().to_string(),
@ -118,8 +116,7 @@ impl crate::docs::StdLibFn for MyFunc {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = let schema = generator.root_schema_for::<Vec<Sketch>>();
crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<Vec<Sketch>>());
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "[Sketch]".to_string(), type_: "[Sketch]".to_string(),

View File

@ -105,9 +105,7 @@ impl crate::docs::StdLibFn for LineTo {
crate::docs::StdLibFnArg { crate::docs::StdLibFnArg {
name: "data".to_string(), name: "data".to_string(),
type_: "LineToData".to_string(), type_: "LineToData".to_string(),
schema: crate::docs::cleanup_number_tuples_root( schema: generator.root_schema_for::<LineToData>(),
generator.root_schema_for::<LineToData>(),
),
required: true, required: true,
label_required: true, label_required: true,
description: String::new().to_string(), description: String::new().to_string(),
@ -116,9 +114,7 @@ impl crate::docs::StdLibFn for LineTo {
crate::docs::StdLibFnArg { crate::docs::StdLibFnArg {
name: "sketch".to_string(), name: "sketch".to_string(),
type_: "Sketch".to_string(), type_: "Sketch".to_string(),
schema: crate::docs::cleanup_number_tuples_root( schema: generator.root_schema_for::<Sketch>(),
generator.root_schema_for::<Sketch>(),
),
required: true, required: true,
label_required: true, label_required: true,
description: "the sketch you're adding the line to".to_string(), description: "the sketch you're adding the line to".to_string(),
@ -131,7 +127,7 @@ impl crate::docs::StdLibFn for LineTo {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<Sketch>()); let schema = generator.root_schema_for::<Sketch>();
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "Sketch".to_string(), type_: "Sketch".to_string(),

View File

@ -103,9 +103,7 @@ impl crate::docs::StdLibFn for Min {
vec![crate::docs::StdLibFnArg { vec![crate::docs::StdLibFnArg {
name: "args".to_string(), name: "args".to_string(),
type_: "[number]".to_string(), type_: "[number]".to_string(),
schema: crate::docs::cleanup_number_tuples_root( schema: generator.root_schema_for::<Vec<f64>>(),
generator.root_schema_for::<Vec<f64>>(),
),
required: true, required: true,
label_required: true, label_required: true,
description: String::new().to_string(), description: String::new().to_string(),
@ -117,7 +115,7 @@ impl crate::docs::StdLibFn for Min {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<f64>()); let schema = generator.root_schema_for::<f64>();
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "number".to_string(), type_: "number".to_string(),

View File

@ -103,9 +103,7 @@ impl crate::docs::StdLibFn for Show {
vec![crate::docs::StdLibFnArg { vec![crate::docs::StdLibFnArg {
name: "args".to_string(), name: "args".to_string(),
type_: "number".to_string(), type_: "number".to_string(),
schema: crate::docs::cleanup_number_tuples_root( schema: generator.root_schema_for::<Option<f64>>(),
generator.root_schema_for::<Option<f64>>(),
),
required: false, required: false,
label_required: true, label_required: true,
description: String::new().to_string(), description: String::new().to_string(),
@ -117,7 +115,7 @@ impl crate::docs::StdLibFn for Show {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<f64>()); let schema = generator.root_schema_for::<f64>();
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "number".to_string(), type_: "number".to_string(),

View File

@ -103,9 +103,7 @@ impl crate::docs::StdLibFn for Import {
vec![crate::docs::StdLibFnArg { vec![crate::docs::StdLibFnArg {
name: "args".to_string(), name: "args".to_string(),
type_: "kittycad::types::InputFormat".to_string(), type_: "kittycad::types::InputFormat".to_string(),
schema: crate::docs::cleanup_number_tuples_root( schema: generator.root_schema_for::<Option<kittycad::types::InputFormat>>(),
generator.root_schema_for::<Option<kittycad::types::InputFormat>>(),
),
required: false, required: false,
label_required: true, label_required: true,
description: String::new().to_string(), description: String::new().to_string(),
@ -117,7 +115,7 @@ impl crate::docs::StdLibFn for Import {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<f64>()); let schema = generator.root_schema_for::<f64>();
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "number".to_string(), type_: "number".to_string(),

View File

@ -103,9 +103,7 @@ impl crate::docs::StdLibFn for Import {
vec![crate::docs::StdLibFnArg { vec![crate::docs::StdLibFnArg {
name: "args".to_string(), name: "args".to_string(),
type_: "kittycad::types::InputFormat".to_string(), type_: "kittycad::types::InputFormat".to_string(),
schema: crate::docs::cleanup_number_tuples_root( schema: generator.root_schema_for::<Option<kittycad::types::InputFormat>>(),
generator.root_schema_for::<Option<kittycad::types::InputFormat>>(),
),
required: false, required: false,
label_required: true, label_required: true,
description: String::new().to_string(), description: String::new().to_string(),
@ -117,8 +115,7 @@ impl crate::docs::StdLibFn for Import {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = let schema = generator.root_schema_for::<Vec<Sketch>>();
crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<Vec<Sketch>>());
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "[Sketch]".to_string(), type_: "[Sketch]".to_string(),

View File

@ -103,9 +103,7 @@ impl crate::docs::StdLibFn for Import {
vec![crate::docs::StdLibFnArg { vec![crate::docs::StdLibFnArg {
name: "args".to_string(), name: "args".to_string(),
type_: "kittycad::types::InputFormat".to_string(), type_: "kittycad::types::InputFormat".to_string(),
schema: crate::docs::cleanup_number_tuples_root( schema: generator.root_schema_for::<Option<kittycad::types::InputFormat>>(),
generator.root_schema_for::<Option<kittycad::types::InputFormat>>(),
),
required: false, required: false,
label_required: true, label_required: true,
description: String::new().to_string(), description: String::new().to_string(),
@ -117,8 +115,7 @@ impl crate::docs::StdLibFn for Import {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = let schema = generator.root_schema_for::<Vec<Sketch>>();
crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<Vec<Sketch>>());
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "[Sketch]".to_string(), type_: "[Sketch]".to_string(),

View File

@ -103,9 +103,7 @@ impl crate::docs::StdLibFn for Show {
vec![crate::docs::StdLibFnArg { vec![crate::docs::StdLibFnArg {
name: "args".to_string(), name: "args".to_string(),
type_: "[number]".to_string(), type_: "[number]".to_string(),
schema: crate::docs::cleanup_number_tuples_root( schema: generator.root_schema_for::<Vec<f64>>(),
generator.root_schema_for::<Vec<f64>>(),
),
required: true, required: true,
label_required: true, label_required: true,
description: String::new().to_string(), description: String::new().to_string(),
@ -117,7 +115,7 @@ impl crate::docs::StdLibFn for Show {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<()>()); let schema = generator.root_schema_for::<()>();
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "()".to_string(), type_: "()".to_string(),

View File

@ -106,7 +106,7 @@ impl crate::docs::StdLibFn for SomeFunction {
let mut settings = schemars::gen::SchemaSettings::openapi3(); let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = inline_subschemas; settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings); let mut generator = schemars::gen::SchemaGenerator::new(settings);
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<i32>()); let schema = generator.root_schema_for::<i32>();
Some(crate::docs::StdLibFnArg { Some(crate::docs::StdLibFnArg {
name: "".to_string(), name: "".to_string(),
type_: "i32".to_string(), type_: "i32".to_string(),

View File

@ -10,6 +10,7 @@ use convert_case::Casing;
use handlebars::Renderable; use handlebars::Renderable;
use indexmap::IndexMap; use indexmap::IndexMap;
use itertools::Itertools; use itertools::Itertools;
use schemars::schema::SingleOrVec;
use serde_json::json; use serde_json::json;
use tokio::task::JoinSet; use tokio::task::JoinSet;
@ -673,6 +674,7 @@ fn cleanup_type_links<'a>(output: &str, types: impl Iterator<Item = &'a String>)
// TODO: This is a hack for the handlebars template being too complex. // TODO: This is a hack for the handlebars template being too complex.
cleaned_output = cleaned_output.replace("`[, `number`, `number`]`", "`[number, number]`"); cleaned_output = cleaned_output.replace("`[, `number`, `number`]`", "`[number, number]`");
cleaned_output = cleaned_output.replace("`[, `number`, `number`, `number`]`", "`[number, number, number]`"); cleaned_output = cleaned_output.replace("`[, `number`, `number`, `number`]`", "`[number, number, number]`");
cleaned_output = cleaned_output.replace("`[, `integer`, `integer`, `integer`]`", "`[integer, integer, integer]`");
// Fix the links to the types. // Fix the links to the types.
for type_name in types.map(|s| &**s).chain(DECLARED_TYPES) { for type_name in types.map(|s| &**s).chain(DECLARED_TYPES) {
@ -691,7 +693,7 @@ fn cleanup_type_links<'a>(output: &str, types: impl Iterator<Item = &'a String>)
// TODO handle union types generically rather than special casing them. // TODO handle union types generically rather than special casing them.
cleaned_output = cleaned_output.replace( cleaned_output = cleaned_output.replace(
"`Sketch | Plane | Face`", "`Sketch | Plane | Face`",
"[`Sketch`](/docs/kcl/types/Sketch) `|` [`Plane`](/docs/kcl/types/Face) `|` [`Plane`](/docs/kcl/types/Face)", "[`Sketch`](/docs/kcl/types/Sketch) OR [`Plane`](/docs/kcl/types/Plane) OR [`Face`](/docs/kcl/types/Face)",
); );
cleanup_static_links(&cleaned_output) cleanup_static_links(&cleaned_output)
@ -720,6 +722,11 @@ fn add_to_types(
)); ));
}; };
if name == "SourceRange" {
types.insert(name.to_string(), schema.clone());
return Ok(());
}
// If we have an array we want to generate the type markdown files for each item in the // If we have an array we want to generate the type markdown files for each item in the
// array. // array.
if let Some(array) = &o.array { if let Some(array) = &o.array {
@ -727,7 +734,7 @@ fn add_to_types(
if let Some(items) = &array.items { if let Some(items) = &array.items {
match items { match items {
schemars::schema::SingleOrVec::Single(item) => { schemars::schema::SingleOrVec::Single(item) => {
if is_primitive(item)?.is_some() && name != "SourceRange" { if is_primitive(item)?.is_some() {
return Ok(()); return Ok(());
} }
return add_to_types(name.trim_start_matches('[').trim_end_matches(']'), item, types); return add_to_types(name.trim_start_matches('[').trim_end_matches(']'), item, types);
@ -816,9 +823,8 @@ fn generate_type(
} }
let cleaned_schema = recurse_and_create_references(name, schema, types)?; let cleaned_schema = recurse_and_create_references(name, schema, types)?;
let new_schema = super::cleanup_number_tuples(&cleaned_schema);
let schemars::schema::Schema::Object(o) = new_schema else { let schemars::schema::Schema::Object(o) = cleaned_schema else {
return Err(anyhow::anyhow!( return Err(anyhow::anyhow!(
"Failed to get object schema, should have not been a primitive" "Failed to get object schema, should have not been a primitive"
)); ));
@ -950,6 +956,13 @@ fn recurse_and_create_references(
"Failed to get object schema, should have not been a primitive" "Failed to get object schema, should have not been a primitive"
)); ));
}; };
// If this is a primitive just use the primitive.
if to.subschemas.is_none() && to.object.is_none() && to.reference.is_none() {
return Ok(t.clone());
}
// Otherwise append the metadata to our reference.
if let Some(metadata) = obj.metadata.as_mut() { if let Some(metadata) = obj.metadata.as_mut() {
if metadata.description.is_none() { if metadata.description.is_none() {
metadata.description = to.metadata.as_ref().and_then(|m| m.description.clone()); metadata.description = to.metadata.as_ref().and_then(|m| m.description.clone());
@ -1052,6 +1065,13 @@ fn recurse_and_create_references(
*item = new_item; *item = new_item;
} }
} }
if subschema.one_of.is_none() && subschema.all_of.is_none() && subschema.any_of.is_none() && obj.array.is_none()
{
if let Some(SingleOrVec::Single(_)) = &o.instance_type {
return Ok(schema.clone());
}
}
} }
let obj = cleanup_type_description(&obj) let obj = cleanup_type_description(&obj)

View File

@ -660,69 +660,6 @@ pub fn get_description_string_from_schema(schema: &schemars::schema::RootSchema)
None None
} }
pub fn cleanup_number_tuples_root(mut schema: schemars::schema::RootSchema) -> schemars::schema::RootSchema {
cleanup_number_tuples_object(&mut schema.schema);
schema
}
fn cleanup_number_tuples_object(o: &mut schemars::schema::SchemaObject) {
if let Some(object) = &mut o.object {
for (_, value) in object.properties.iter_mut() {
*value = cleanup_number_tuples(value);
}
}
if let Some(array) = &mut o.array {
if let Some(items) = &mut array.items {
match items {
schemars::schema::SingleOrVec::Single(_) => {
// Do nothing since its only a single item.
}
schemars::schema::SingleOrVec::Vec(items) => {
if items.len() == 2 {
// Get the second item and see if its a NumericType.
if let Some(schemars::schema::Schema::Object(obj)) = items.get(1) {
if let Some(reference) = &obj.reference {
if reference == "#/components/schemas/NumericType" {
// Get the first item.
if let Some(schemars::schema::Schema::Object(obj2)) = items.first() {
let mut obj2 = obj2.clone();
obj2.metadata = o.metadata.clone();
// Replace the array with the first item.
*o = obj2;
}
}
} else if NUMERIC_TYPE_SCHEMA.object == obj.object {
if let Some(schemars::schema::Schema::Object(obj2)) = items.first() {
let mut obj2 = obj2.clone();
obj2.metadata = o.metadata.clone();
// Replace the array with the first item.
*o = obj2;
}
}
}
}
}
}
}
}
}
/// Some numbers will be tuples of 2 where the second type is always "NumericType". We want to
/// replace these with the first item in the array and not have an array as it messes
/// with the docs generation which assumes if there is a tuple that you give 2 values not one
/// in the form of an array.
fn cleanup_number_tuples(schema: &schemars::schema::Schema) -> schemars::schema::Schema {
let mut schema = schema.clone();
if let schemars::schema::Schema::Object(o) = &mut schema {
cleanup_number_tuples_object(o);
}
schema
}
pub fn is_primitive(schema: &schemars::schema::Schema) -> Result<Option<Primitive>> { pub fn is_primitive(schema: &schemars::schema::Schema) -> Result<Option<Primitive>> {
match schema { match schema {
schemars::schema::Schema::Object(o) => { schemars::schema::Schema::Object(o) => {

View File

@ -1258,6 +1258,48 @@ mod linear_pattern3d_a_pattern {
super::execute(TEST_NAME, true).await super::execute(TEST_NAME, true).await
} }
} }
mod pattern_circular_in_module {
const TEST_NAME: &str = "pattern_circular_in_module";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}
mod pattern_linear_in_module {
const TEST_NAME: &str = "pattern_linear_in_module";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}
mod tangential_arc { mod tangential_arc {
const TEST_NAME: &str = "tangential_arc"; const TEST_NAME: &str = "tangential_arc";

View File

@ -72,7 +72,7 @@ impl KwArgs {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
#[ts(export)] #[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct TyF64 { pub struct TyF64 {
@ -98,6 +98,16 @@ impl TyF64 {
} }
} }
impl JsonSchema for TyF64 {
fn schema_name() -> String {
"TyF64".to_string()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
gen.subschema_for::<f64>()
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Args { pub struct Args {
/// Positional args. /// Positional args.

View File

@ -381,6 +381,7 @@ async fn send_pattern_transform<T: GeometryTrait>(
args: &Args, args: &Args,
) -> Result<Vec<T>, KclError> { ) -> Result<Vec<T>, KclError> {
let id = exec_state.next_uuid(); let id = exec_state.next_uuid();
let extra_instances = transforms.len();
let resp = args let resp = args
.send_modeling_cmd( .send_modeling_cmd(
@ -393,10 +394,19 @@ async fn send_pattern_transform<T: GeometryTrait>(
) )
.await?; .await?;
let OkWebSocketResponseData::Modeling { let mut mock_ids = Vec::new();
let entity_ids = if let OkWebSocketResponseData::Modeling {
modeling_response: OkModelingCmdResponse::EntityLinearPatternTransform(pattern_info), modeling_response: OkModelingCmdResponse::EntityLinearPatternTransform(pattern_info),
} = &resp } = &resp
else { {
&pattern_info.entity_ids
} else if args.ctx.no_engine_commands().await {
mock_ids.reserve(extra_instances);
for _ in 0..extra_instances {
mock_ids.push(exec_state.next_uuid());
}
&mock_ids
} else {
return Err(KclError::Engine(KclErrorDetails { return Err(KclError::Engine(KclErrorDetails {
message: format!("EntityLinearPattern response was not as expected: {:?}", resp), message: format!("EntityLinearPattern response was not as expected: {:?}", resp),
source_ranges: vec![args.source_range], source_ranges: vec![args.source_range],
@ -404,7 +414,7 @@ async fn send_pattern_transform<T: GeometryTrait>(
}; };
let mut geometries = vec![solid.clone()]; let mut geometries = vec![solid.clone()];
for id in pattern_info.entity_ids.iter().copied() { for id in entity_ids.iter().copied() {
let mut new_solid = solid.clone(); let mut new_solid = solid.clone();
new_solid.set_id(id); new_solid.set_id(id);
geometries.push(new_solid); geometries.push(new_solid);
@ -1280,10 +1290,21 @@ async fn pattern_circular(
) )
.await?; .await?;
let OkWebSocketResponseData::Modeling { // The common case is borrowing from the response. Instead of cloning,
// create a Vec to borrow from in mock mode.
let mut mock_ids = Vec::new();
let entity_ids = if let OkWebSocketResponseData::Modeling {
modeling_response: OkModelingCmdResponse::EntityCircularPattern(pattern_info), modeling_response: OkModelingCmdResponse::EntityCircularPattern(pattern_info),
} = &resp } = &resp
else { {
&pattern_info.entity_ids
} else if args.ctx.no_engine_commands().await {
mock_ids.reserve(num_repetitions as usize);
for _ in 0..num_repetitions {
mock_ids.push(exec_state.next_uuid());
}
&mock_ids
} else {
return Err(KclError::Engine(KclErrorDetails { return Err(KclError::Engine(KclErrorDetails {
message: format!("EntityCircularPattern response was not as expected: {:?}", resp), message: format!("EntityCircularPattern response was not as expected: {:?}", resp),
source_ranges: vec![args.source_range], source_ranges: vec![args.source_range],
@ -1293,18 +1314,18 @@ async fn pattern_circular(
let geometries = match geometry { let geometries = match geometry {
Geometry::Sketch(sketch) => { Geometry::Sketch(sketch) => {
let mut geometries = vec![sketch.clone()]; let mut geometries = vec![sketch.clone()];
for id in pattern_info.entity_ids.iter() { for id in entity_ids.iter().copied() {
let mut new_sketch = sketch.clone(); let mut new_sketch = sketch.clone();
new_sketch.id = *id; new_sketch.id = id;
geometries.push(new_sketch); geometries.push(new_sketch);
} }
Geometries::Sketches(geometries) Geometries::Sketches(geometries)
} }
Geometry::Solid(solid) => { Geometry::Solid(solid) => {
let mut geometries = vec![solid.clone()]; let mut geometries = vec![solid.clone()];
for id in pattern_info.entity_ids.iter() { for id in entity_ids.iter().copied() {
let mut new_solid = solid.clone(); let mut new_solid = solid.clone();
new_solid.id = *id; new_solid.id = id;
geometries.push(new_solid); geometries.push(new_solid);
} }
Geometries::Solids(geometries) Geometries::Solids(geometries)

View File

@ -0,0 +1,700 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact commands pattern_circular_in_module.kcl
---
[
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "edge_lines_visible",
"hidden": false
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"size": 60.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "start_path"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": 0.5,
"y": 25.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 0.0,
"y": 5.0,
"z": 0.0
},
"relative": true
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": -1.0,
"y": 0.0,
"z": 0.0
},
"relative": true
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 0.0,
"y": -5.0,
"z": 0.0
},
"relative": true
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "close_path",
"path_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_circular_pattern",
"entity_id": "[uuid]",
"axis": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"center": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"num_repetitions": 3,
"arc_degrees": 360.0,
"rotate_duplicates": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 1.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 1.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 1.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 1.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
}
]

View File

@ -0,0 +1,6 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact graph flowchart pattern_circular_in_module.kcl
extension: md
snapshot_kind: binary
---

View File

@ -0,0 +1,63 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[63, 90, 5]"]
3["Segment<br>[98, 116, 5]"]
4["Segment<br>[124, 143, 5]"]
5["Segment<br>[151, 170, 5]"]
6["Segment<br>[178, 185, 5]"]
7[Solid2d]
end
1["Plane<br>[38, 55, 5]"]
8["Sweep Extrusion<br>[342, 376, 5]"]
9[Wall]
10[Wall]
11[Wall]
12[Wall]
13["Cap Start"]
14["Cap End"]
15["SweepEdge Opposite"]
16["SweepEdge Adjacent"]
17["SweepEdge Opposite"]
18["SweepEdge Adjacent"]
19["SweepEdge Opposite"]
20["SweepEdge Adjacent"]
21["SweepEdge Opposite"]
22["SweepEdge Adjacent"]
23["Sweep Extrusion<br>[342, 376, 5]"]
24["Sweep Extrusion<br>[342, 376, 5]"]
25["Sweep Extrusion<br>[342, 376, 5]"]
1 --- 2
2 --- 3
2 --- 4
2 --- 5
2 --- 6
2 ---- 8
2 --- 7
3 --- 9
3 --- 15
3 --- 16
4 --- 10
4 --- 17
4 --- 18
5 --- 11
5 --- 19
5 --- 20
6 --- 12
6 --- 21
6 --- 22
8 --- 9
8 --- 10
8 --- 11
8 --- 12
8 --- 13
8 --- 14
8 --- 15
8 --- 16
8 --- 17
8 --- 18
8 --- 19
8 --- 20
8 --- 21
8 --- 22
```

View File

@ -0,0 +1,89 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of parsing pattern_circular_in_module.kcl
---
{
"Ok": {
"body": [
{
"commentStart": 0,
"end": 0,
"path": {
"type": "Kcl",
"filename": "thing.kcl"
},
"selector": {
"type": "List",
"items": [
{
"alias": null,
"commentStart": 7,
"end": 0,
"name": {
"commentStart": 7,
"end": 0,
"name": "thing",
"start": 0,
"type": "Identifier"
},
"start": 0,
"type": "ImportItem"
}
]
},
"start": 0,
"type": "ImportStatement",
"type": "ImportStatement"
},
{
"commentStart": 29,
"end": 0,
"expression": {
"arguments": [],
"callee": {
"abs_path": false,
"commentStart": 31,
"end": 0,
"name": {
"commentStart": 31,
"end": 0,
"name": "thing",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 31,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
"start": 0,
"type": "ExpressionStatement",
"type": "ExpressionStatement"
}
],
"commentStart": 0,
"end": 0,
"nonCodeMeta": {
"nonCodeNodes": {
"0": [
{
"commentStart": 29,
"end": 0,
"start": 0,
"type": "NonCodeNode",
"value": {
"type": "newLine"
}
}
]
},
"startNodes": []
},
"start": 0
}
}

View File

@ -0,0 +1,3 @@
import thing from "thing.kcl"
thing()

View File

@ -0,0 +1,176 @@
---
source: kcl-lib/src/simulation_tests.rs
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",
"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"
}
]

View File

@ -0,0 +1,9 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Variables in memory after executing pattern_circular_in_module.kcl
---
{
"thing": {
"type": "Function"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,19 @@
export fn thing() {
exampleSketch = startSketchOn(XZ)
|> startProfileAt([.5, 25], %)
|> line(end = [0, 5])
|> line(end = [-1, 0])
|> line(end = [0, -5])
|> close()
|> patternCircular2d(
center = [0, 0],
instances = 4,
arcDegrees = 360,
rotateDuplicates = true,
)
return extrude(exampleSketch, length = 1)
}
// This makes it run in isolated mode when the function is imported.
thing()

View File

@ -0,0 +1,7 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing pattern_circular_in_module.kcl
---
import thing from "thing.kcl"
thing()

View File

@ -0,0 +1,23 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing tests/pattern_circular_in_module/thing.kcl
---
export fn thing() {
exampleSketch = startSketchOn(XZ)
|> startProfileAt([.5, 25], %)
|> line(end = [0, 5])
|> line(end = [-1, 0])
|> line(end = [0, -5])
|> close()
|> patternCircular2d(
center = [0, 0],
instances = 4,
arcDegrees = 360,
rotateDuplicates = true,
)
return extrude(exampleSketch, length = 1)
}
// This makes it run in isolated mode when the function is imported.
thing()

View File

@ -0,0 +1,808 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact commands pattern_linear_in_module.kcl
---
[
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "edge_lines_visible",
"hidden": false
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"size": 60.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "start_path"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": 1.0,
"y": 0.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "arc",
"center": {
"x": 0.0,
"y": 0.0
},
"radius": 1.0,
"start": {
"unit": "degrees",
"value": 0.0
},
"end": {
"unit": "degrees",
"value": 360.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "close_path",
"path_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_linear_pattern_transform",
"entity_id": "[uuid]",
"transform": [],
"transforms": [
[
{
"translate": {
"x": 4.0,
"y": 0.0,
"z": 0.0
},
"scale": {
"x": 1.0,
"y": 1.0,
"z": 1.0
},
"rotation": {
"axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"angle": {
"unit": "degrees",
"value": 0.0
},
"origin": {
"type": "local"
}
},
"replicate": true
}
],
[
{
"translate": {
"x": 8.0,
"y": 0.0,
"z": 0.0
},
"scale": {
"x": 1.0,
"y": 1.0,
"z": 1.0
},
"rotation": {
"axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"angle": {
"unit": "degrees",
"value": 0.0
},
"origin": {
"type": "local"
}
},
"replicate": true
}
],
[
{
"translate": {
"x": 12.0,
"y": 0.0,
"z": 0.0
},
"scale": {
"x": 1.0,
"y": 1.0,
"z": 1.0
},
"rotation": {
"axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"angle": {
"unit": "degrees",
"value": 0.0
},
"origin": {
"type": "local"
}
},
"replicate": true
}
],
[
{
"translate": {
"x": 16.0,
"y": 0.0,
"z": 0.0
},
"scale": {
"x": 1.0,
"y": 1.0,
"z": 1.0
},
"rotation": {
"axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"angle": {
"unit": "degrees",
"value": 0.0
},
"origin": {
"type": "local"
}
},
"replicate": true
}
],
[
{
"translate": {
"x": 20.0,
"y": 0.0,
"z": 0.0
},
"scale": {
"x": 1.0,
"y": 1.0,
"z": 1.0
},
"rotation": {
"axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"angle": {
"unit": "degrees",
"value": 0.0
},
"origin": {
"type": "local"
}
},
"replicate": true
}
],
[
{
"translate": {
"x": 24.0,
"y": 0.0,
"z": 0.0
},
"scale": {
"x": 1.0,
"y": 1.0,
"z": 1.0
},
"rotation": {
"axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"angle": {
"unit": "degrees",
"value": 0.0
},
"origin": {
"type": "local"
}
},
"replicate": true
}
]
]
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 1.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 1.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 1.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 1.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 1.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 1.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 1.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
}
]

View File

@ -0,0 +1,6 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact graph flowchart pattern_linear_in_module.kcl
extension: md
snapshot_kind: binary
---

View File

@ -0,0 +1,33 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[54, 89, 5]"]
3["Segment<br>[54, 89, 5]"]
4[Solid2d]
end
1["Plane<br>[29, 46, 5]"]
5["Sweep Extrusion<br>[200, 219, 5]"]
6[Wall]
7["Cap Start"]
8["Cap End"]
9["SweepEdge Opposite"]
10["SweepEdge Adjacent"]
11["Sweep Extrusion<br>[200, 219, 5]"]
12["Sweep Extrusion<br>[200, 219, 5]"]
13["Sweep Extrusion<br>[200, 219, 5]"]
14["Sweep Extrusion<br>[200, 219, 5]"]
15["Sweep Extrusion<br>[200, 219, 5]"]
16["Sweep Extrusion<br>[200, 219, 5]"]
1 --- 2
2 --- 3
2 ---- 5
2 --- 4
3 --- 6
3 --- 9
3 --- 10
5 --- 6
5 --- 7
5 --- 8
5 --- 9
5 --- 10
```

View File

@ -0,0 +1,89 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of parsing pattern_linear_in_module.kcl
---
{
"Ok": {
"body": [
{
"commentStart": 0,
"end": 0,
"path": {
"type": "Kcl",
"filename": "thing.kcl"
},
"selector": {
"type": "List",
"items": [
{
"alias": null,
"commentStart": 7,
"end": 0,
"name": {
"commentStart": 7,
"end": 0,
"name": "thing",
"start": 0,
"type": "Identifier"
},
"start": 0,
"type": "ImportItem"
}
]
},
"start": 0,
"type": "ImportStatement",
"type": "ImportStatement"
},
{
"commentStart": 29,
"end": 0,
"expression": {
"arguments": [],
"callee": {
"abs_path": false,
"commentStart": 31,
"end": 0,
"name": {
"commentStart": 31,
"end": 0,
"name": "thing",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 31,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
"start": 0,
"type": "ExpressionStatement",
"type": "ExpressionStatement"
}
],
"commentStart": 0,
"end": 0,
"nonCodeMeta": {
"nonCodeNodes": {
"0": [
{
"commentStart": 29,
"end": 0,
"start": 0,
"type": "NonCodeNode",
"value": {
"type": "newLine"
}
}
]
},
"startNodes": []
},
"start": 0
}
}

View File

@ -0,0 +1,3 @@
import thing from "thing.kcl"
thing()

View File

@ -0,0 +1,344 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Operations executed pattern_linear_in_module.kcl
---
[
{
"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": "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"
}
]

View File

@ -0,0 +1,9 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Variables in memory after executing pattern_linear_in_module.kcl
---
{
"thing": {
"type": "Function"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -0,0 +1,13 @@
export fn thing() {
return startSketchOn(XZ)
|> circle(center = [0, 0], radius = 1)
|> patternLinear2d(
axis = [1, 0],
instances = 7,
distance = 4
)
|> extrude(length = 1)
}
// This makes it run in isolated mode when the function is imported.
thing()

View File

@ -0,0 +1,7 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing pattern_linear_in_module.kcl
---
import thing from "thing.kcl"
thing()

View File

@ -0,0 +1,13 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing tests/pattern_linear_in_module/thing.kcl
---
export fn thing() {
return startSketchOn(XZ)
|> circle(center = [0, 0], radius = 1)
|> patternLinear2d(axis = [1, 0], instances = 7, distance = 4)
|> extrude(length = 1)
}
// This makes it run in isolated mode when the function is imported.
thing()

View File

@ -320,6 +320,7 @@ export function mutateAstWithTagForSketchSegment(
// Check whether selection is a valid segment // Check whether selection is a valid segment
if ( if (
!segmentNode.node.callee ||
!( !(
segmentNode.node.callee.name.name in sketchLineHelperMap || segmentNode.node.callee.name.name in sketchLineHelperMap ||
segmentNode.node.callee.name.name in sketchLineHelperMapKw segmentNode.node.callee.name.name in sketchLineHelperMapKw

View File

@ -1,14 +1,6 @@
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { KCL_DEFAULT_CONSTANT_PREFIXES } from 'lib/constants' import { KCL_DEFAULT_CONSTANT_PREFIXES } from 'lib/constants'
import { import { Program, PathToNode, Expr, VariableDeclarator } from 'lang/wasm'
Program,
PathToNode,
Expr,
CallExpression,
VariableDeclarator,
CallExpressionKw,
ArtifactGraph,
} from 'lang/wasm'
import { Selections } from 'lib/selections' import { Selections } from 'lib/selections'
import { Node } from '@rust/kcl-lib/bindings/Node' import { Node } from '@rust/kcl-lib/bindings/Node'
import { import {
@ -29,8 +21,7 @@ import {
mutateAstWithTagForSketchSegment, mutateAstWithTagForSketchSegment,
getEdgeTagCall, getEdgeTagCall,
} from 'lang/modifyAst/addEdgeTreatment' } from 'lang/modifyAst/addEdgeTreatment'
import { Artifact, getPathsFromArtifact } from 'lang/std/artifactGraph' import { getSafeInsertIndex } from 'lang/queryAst/getSafeInsertIndex'
import { kclManager } from 'lib/singletons'
export function getAxisExpressionAndIndex( export function getAxisExpressionAndIndex(
axisOrEdge: 'Axis' | 'Edge', axisOrEdge: 'Axis' | 'Edge',
@ -47,13 +38,6 @@ export function getAxisExpressionAndIndex(
ast, ast,
edge.graphSelections[0]?.codeRef.range edge.graphSelections[0]?.codeRef.range
) )
const lineNode = getNodeFromPath<CallExpression | CallExpressionKw>(
ast,
pathToAxisSelection,
['CallExpression', 'CallExpressionKw']
)
if (err(lineNode)) return lineNode
const tagResult = mutateAstWithTagForSketchSegment(ast, pathToAxisSelection) const tagResult = mutateAstWithTagForSketchSegment(ast, pathToAxisSelection)
// Have the tag whether it is already created or a new one is generated // Have the tag whether it is already created or a new one is generated
@ -90,12 +74,12 @@ export function getAxisExpressionAndIndex(
export function revolveSketch( export function revolveSketch(
ast: Node<Program>, ast: Node<Program>,
pathToSketchNode: PathToNode, pathToSketchNode: PathToNode,
angle: Expr = createLiteral(4), angle: Expr,
axisOrEdge: 'Axis' | 'Edge', axisOrEdge: 'Axis' | 'Edge',
axis: string, axis: string | undefined,
edge: Selections, edge: Selections | undefined,
artifactGraph: ArtifactGraph, variableName?: string,
artifact?: Artifact insertIndex?: number
): ):
| { | {
modifiedAst: Node<Program> modifiedAst: Node<Program>
@ -103,16 +87,7 @@ export function revolveSketch(
pathToRevolveArg: PathToNode pathToRevolveArg: PathToNode
} }
| Error { | Error {
const orderedSketchNodePaths = getPathsFromArtifact({
artifact: artifact,
sketchPathToNode: pathToSketchNode,
artifactGraph,
ast: kclManager.ast,
})
if (err(orderedSketchNodePaths)) return orderedSketchNodePaths
const clonedAst = structuredClone(ast) const clonedAst = structuredClone(ast)
const sketchNode = getNodeFromPath(clonedAst, pathToSketchNode)
if (err(sketchNode)) return sketchNode
const sketchVariableDeclaratorNode = getNodeFromPath<VariableDeclarator>( const sketchVariableDeclaratorNode = getNodeFromPath<VariableDeclarator>(
clonedAst, clonedAst,
pathToSketchNode, pathToSketchNode,
@ -121,9 +96,14 @@ export function revolveSketch(
if (err(sketchVariableDeclaratorNode)) return sketchVariableDeclaratorNode if (err(sketchVariableDeclaratorNode)) return sketchVariableDeclaratorNode
const { node: sketchVariableDeclarator } = sketchVariableDeclaratorNode const { node: sketchVariableDeclarator } = sketchVariableDeclaratorNode
const getAxisResult = getAxisExpressionAndIndex(axisOrEdge, axis, edge, ast) const getAxisResult = getAxisExpressionAndIndex(
axisOrEdge,
axis,
edge,
clonedAst
)
if (err(getAxisResult)) return getAxisResult if (err(getAxisResult)) return getAxisResult
const { generatedAxis, axisIndexIfAxis } = getAxisResult const { generatedAxis } = getAxisResult
if (!generatedAxis) return new Error('Generated axis selection is missing.') if (!generatedAxis) return new Error('Generated axis selection is missing.')
const revolveCall = createCallExpressionStdLibKw( const revolveCall = createCallExpressionStdLibKw(
@ -134,29 +114,21 @@ export function revolveSketch(
// We're not creating a pipe expression, // We're not creating a pipe expression,
// but rather a separate constant for the extrusion // but rather a separate constant for the extrusion
const name = findUniqueName(clonedAst, KCL_DEFAULT_CONSTANT_PREFIXES.REVOLVE) const name =
const VariableDeclaration = createVariableDeclaration(name, revolveCall) variableName ??
const lastSketchNodePath = findUniqueName(clonedAst, KCL_DEFAULT_CONSTANT_PREFIXES.REVOLVE)
orderedSketchNodePaths[orderedSketchNodePaths.length - 1] const variableDeclaration = createVariableDeclaration(name, revolveCall)
let sketchIndexInBody = Number(lastSketchNodePath[1][0]) const bodyInsertIndex =
if (typeof sketchIndexInBody !== 'number') { insertIndex ?? getSafeInsertIndex(revolveCall, clonedAst)
return new Error('expected sketchIndexInBody to be a number') clonedAst.body.splice(bodyInsertIndex, 0, variableDeclaration)
} const argIndex = 0
// If an axis was selected in KCL, find the max index to insert the revolve command
if (axisIndexIfAxis) {
sketchIndexInBody = Math.max(sketchIndexInBody, axisIndexIfAxis)
}
clonedAst.body.splice(sketchIndexInBody + 1, 0, VariableDeclaration)
const pathToRevolveArg: PathToNode = [ const pathToRevolveArg: PathToNode = [
['body', ''], ['body', ''],
[sketchIndexInBody + 1, 'index'], [bodyInsertIndex, 'index'],
['declaration', 'VariableDeclaration'], ['declaration', 'VariableDeclaration'],
['init', 'VariableDeclarator'], ['init', 'VariableDeclarator'],
['arguments', 'CallExpressionKw'], ['arguments', 'CallExpressionKw'],
[0, ARG_INDEX_FIELD], [argIndex, ARG_INDEX_FIELD],
['arg', LABELED_ARG_FIELD], ['arg', LABELED_ARG_FIELD],
] ]

View File

@ -77,11 +77,15 @@ export type ModelingCommandSchema = {
thickness: KclCommandValue thickness: KclCommandValue
} }
Revolve: { Revolve: {
// Enables editing workflow
nodeToEdit?: PathToNode
// Flow arg
axisOrEdge: 'Axis' | 'Edge'
// KCL stdlib arguments
selection: Selections selection: Selections
angle: KclCommandValue angle: KclCommandValue
axisOrEdge: 'Axis' | 'Edge' axis: string | undefined
axis: string edge: Selections | undefined
edge: Selections
} }
Fillet: { Fillet: {
// Enables editing workflow // Enables editing workflow
@ -472,6 +476,13 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
icon: 'revolve', icon: 'revolve',
needsReview: true, needsReview: true,
args: { args: {
nodeToEdit: {
description:
'Path to the node in the AST to edit. Never shown to the user.',
skip: true,
inputType: 'text',
required: false,
},
selection: { selection: {
inputType: 'selection', inputType: 'selection',
selectionTypes: ['solid2d', 'segment'], selectionTypes: ['solid2d', 'segment'],
@ -500,6 +511,7 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
{ name: 'X Axis', isCurrent: true, value: 'X' }, { name: 'X Axis', isCurrent: true, value: 'X' },
{ name: 'Y Axis', isCurrent: false, value: 'Y' }, { name: 'Y Axis', isCurrent: false, value: 'Y' },
], ],
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
}, },
edge: { edge: {
required: (commandContext) => required: (commandContext) =>

View File

@ -800,6 +800,163 @@ const prepareToEditHelix: PrepareToEditCallback = async ({ operation }) => {
} }
} }
const prepareToEditRevolve: PrepareToEditCallback = async ({
operation,
artifact,
}) => {
const baseCommand = {
name: 'Revolve',
groupId: 'modeling',
}
if (
!artifact ||
!('pathId' in artifact) ||
operation.type !== 'StdLibCall' ||
!operation.labeledArgs
) {
return { reason: 'Wrong operation type or artifact' }
}
// We have to go a little roundabout to get from the original artifact
// to the solid2DId that we need to pass to the command.
const pathArtifact = getArtifactOfTypes(
{
key: artifact.pathId,
types: ['path'],
},
kclManager.artifactGraph
)
if (
err(pathArtifact) ||
pathArtifact.type !== 'path' ||
!pathArtifact.solid2dId
) {
return { reason: "Couldn't find related path artifact" }
}
const solid2DArtifact = getArtifactOfTypes(
{
key: pathArtifact.solid2dId,
types: ['solid2d'],
},
kclManager.artifactGraph
)
if (err(solid2DArtifact) || solid2DArtifact.type !== 'solid2d') {
return { reason: "Couldn't find related solid2d artifact" }
}
const selection = {
graphSelections: [
{
artifact: solid2DArtifact,
codeRef: pathArtifact.codeRef,
},
],
otherSelections: [],
}
// axis options string arg
if (!('axis' in operation.labeledArgs) || !operation.labeledArgs.axis) {
return { reason: "Couldn't find axis argument" }
}
const axisValue = operation.labeledArgs.axis.value
let axisOrEdge: 'Axis' | 'Edge' | undefined
let axis: string | undefined
let edge: Selections | undefined
if (axisValue.type === 'String') {
// default axis casee
axisOrEdge = 'Axis'
axis = axisValue.value
} else if (axisValue.type === 'TagIdentifier' && axisValue.artifact_id) {
// segment case
axisOrEdge = 'Edge'
const artifact = getArtifactOfTypes(
{
key: axisValue.artifact_id,
types: ['segment'],
},
kclManager.artifactGraph
)
if (err(artifact)) {
return { reason: "Couldn't find related edge artifact" }
}
edge = {
graphSelections: [
{
artifact,
codeRef: artifact.codeRef,
},
],
otherSelections: [],
}
} else if (axisValue.type === 'Uuid') {
// sweepEdge case
axisOrEdge = 'Edge'
const artifact = getArtifactOfTypes(
{
key: axisValue.value,
types: ['sweepEdge'],
},
kclManager.artifactGraph
)
if (err(artifact)) {
return { reason: "Couldn't find related edge artifact" }
}
const codeRef = getSweepEdgeCodeRef(artifact, kclManager.artifactGraph)
if (err(codeRef)) {
return { reason: "Couldn't find related edge code ref" }
}
edge = {
graphSelections: [
{
artifact,
codeRef,
},
],
otherSelections: [],
}
} else {
return { reason: 'The type of the axis argument is unsupported' }
}
// angle kcl arg
if (!('angle' in operation.labeledArgs) || !operation.labeledArgs.angle) {
return { reason: "Couldn't find angle argument" }
}
const angle = await stringToKclExpression(
codeManager.code.slice(
operation.labeledArgs.angle.sourceRange[0],
operation.labeledArgs.angle.sourceRange[1]
)
)
if (err(angle) || 'errors' in angle) {
return { reason: 'Error in angle argument retrieval' }
}
// Assemble the default argument values for the Offset Plane command,
// with `nodeToEdit` set, which will let the Offset Plane actor know
// to edit the node that corresponds to the StdLibCall.
const argDefaultValues: ModelingCommandSchema['Revolve'] = {
axisOrEdge,
axis,
edge,
selection,
angle,
nodeToEdit: getNodePathFromSourceRange(
kclManager.ast,
sourceRangeFromRust(operation.sourceRange)
),
}
return {
...baseCommand,
argDefaultValues,
}
}
/** /**
* A map of standard library calls to their corresponding information * A map of standard library calls to their corresponding information
* for use in the feature tree UI. * for use in the feature tree UI.
@ -872,6 +1029,7 @@ export const stdLibMap: Record<string, StdLibCallInfo> = {
revolve: { revolve: {
label: 'Revolve', label: 'Revolve',
icon: 'revolve', icon: 'revolve',
prepareToEdit: prepareToEditRevolve,
supportsAppearance: true, supportsAppearance: true,
}, },
shell: { shell: {

View File

@ -735,62 +735,6 @@ export const modelingMachine = setup({
sketchDetails: event.output, sketchDetails: event.output,
} }
}), }),
'AST revolve': ({ context: { store }, event }) => {
if (event.type !== 'Revolve') return
;(async () => {
if (!event.data) return
const { selection, angle, axis, edge, axisOrEdge } = event.data
let ast = kclManager.ast
if (
'variableName' in angle &&
angle.variableName &&
angle.insertIndex !== undefined
) {
const newBody = [...ast.body]
newBody.splice(angle.insertIndex, 0, angle.variableDeclarationAst)
ast.body = newBody
}
// This is the selection of the sketch that will be revolved
const pathToNode = getNodePathFromSourceRange(
ast,
selection.graphSelections[0]?.codeRef.range
)
const revolveSketchRes = revolveSketch(
ast,
pathToNode,
'variableName' in angle
? angle.variableIdentifierAst
: angle.valueAst,
axisOrEdge,
axis,
edge,
kclManager.artifactGraph,
selection.graphSelections[0]?.artifact
)
if (trap(revolveSketchRes)) return
const { modifiedAst, pathToRevolveArg } = revolveSketchRes
await updateModelingState(
modifiedAst,
EXECUTION_TYPE_REAL,
{
kclManager,
editorManager,
codeManager,
},
{
focusPath: [pathToRevolveArg],
zoomToFit: true,
zoomOnRangeAndType: {
range: selection.graphSelections[0]?.codeRef.range,
type: 'path',
},
}
)
})().catch(reportRejection)
},
'set selection filter to curves only': () => { 'set selection filter to curves only': () => {
;(async () => { ;(async () => {
await engineCommandManager.sendSceneCommand({ await engineCommandManager.sendSceneCommand({
@ -1837,6 +1781,87 @@ export const modelingMachine = setup({
} }
) )
}), }),
revolveAstMod: fromPromise<
unknown,
ModelingCommandSchema['Revolve'] | undefined
>(async ({ input }) => {
if (!input) return new Error('No input provided')
const { nodeToEdit, selection, angle, axis, edge, axisOrEdge } = input
let ast = kclManager.ast
let variableName: string | undefined = undefined
let insertIndex: number | undefined = undefined
// If this is an edit flow, first we're going to remove the old extrusion
if (nodeToEdit && typeof nodeToEdit[1][0] === 'number') {
// Extract the plane name from the node to edit
const nameNode = getNodeFromPath<VariableDeclaration>(
ast,
nodeToEdit,
'VariableDeclaration'
)
if (err(nameNode)) {
console.error('Error extracting plane name')
} else {
variableName = nameNode.node.declaration.id.name
}
// Removing the old extrusion statement
const newBody = [...ast.body]
newBody.splice(nodeToEdit[1][0], 1)
ast.body = newBody
insertIndex = nodeToEdit[1][0]
}
if (
'variableName' in angle &&
angle.variableName &&
angle.insertIndex !== undefined
) {
const newBody = [...ast.body]
newBody.splice(angle.insertIndex, 0, angle.variableDeclarationAst)
ast.body = newBody
if (insertIndex) {
// if editing need to offset that new var
insertIndex += 1
}
}
// This is the selection of the sketch that will be revolved
const pathToNode = getNodePathFromSourceRange(
ast,
selection.graphSelections[0]?.codeRef.range
)
const revolveSketchRes = revolveSketch(
ast,
pathToNode,
'variableName' in angle ? angle.variableIdentifierAst : angle.valueAst,
axisOrEdge,
axis,
edge,
variableName,
insertIndex
)
if (trap(revolveSketchRes)) return
const { modifiedAst, pathToRevolveArg } = revolveSketchRes
await updateModelingState(
modifiedAst,
EXECUTION_TYPE_REAL,
{
kclManager,
editorManager,
codeManager,
},
{
focusPath: [pathToRevolveArg],
zoomToFit: true,
zoomOnRangeAndType: {
range: selection.graphSelections[0]?.codeRef.range,
type: 'path',
},
}
)
}),
offsetPlaneAstMod: fromPromise( offsetPlaneAstMod: fromPromise(
async ({ async ({
input, input,
@ -2767,9 +2792,8 @@ export const modelingMachine = setup({
}, },
Revolve: { Revolve: {
target: 'idle', target: 'Applying revolve',
actions: ['AST revolve'], reenter: true,
reenter: false,
}, },
Sweep: { Sweep: {
@ -4023,6 +4047,22 @@ export const modelingMachine = setup({
}, },
}, },
'Applying revolve': {
invoke: {
src: 'revolveAstMod',
id: 'revolveAstMod',
input: ({ event }) => {
if (event.type !== 'Revolve') return undefined
return event.data
},
onDone: ['idle'],
onError: {
target: 'idle',
actions: 'toastError',
},
},
},
'Applying offset plane': { 'Applying offset plane': {
invoke: { invoke: {
src: 'offsetPlaneAstMod', src: 'offsetPlaneAstMod',

View File

@ -38,7 +38,7 @@ const SignIn = () => {
}?callbackUrl=${encodeURIComponent( }?callbackUrl=${encodeURIComponent(
typeof window !== 'undefined' && window.location.href.replace('signin', '') typeof window !== 'undefined' && window.location.href.replace('signin', '')
)}` )}`
const kclSampleUrl = `${VITE_KC_SITE_BASE_URL}/docs/kcl-samples/car-wheel` const kclSampleUrl = `${VITE_KC_SITE_BASE_URL}/docs/kcl-samples/car-wheel-assembly`
const getThemeText = useCallback( const getThemeText = useCallback(
(shouldContrast = true) => (shouldContrast = true) =>