Add Rust side artifacts for startSketchOn face or plane (#4834)
* Add Rust side artifacts for startSketchOn face or plane * move ast digging --------- Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
This commit is contained in:
@ -357,7 +357,10 @@ export class KclManager {
|
|||||||
}
|
}
|
||||||
this.ast = { ...ast }
|
this.ast = { ...ast }
|
||||||
// updateArtifactGraph relies on updated executeState/programMemory
|
// updateArtifactGraph relies on updated executeState/programMemory
|
||||||
await this.engineCommandManager.updateArtifactGraph(this.ast)
|
await this.engineCommandManager.updateArtifactGraph(
|
||||||
|
this.ast,
|
||||||
|
execState.artifacts
|
||||||
|
)
|
||||||
this._executeCallback()
|
this._executeCallback()
|
||||||
if (!isInterrupted)
|
if (!isInterrupted)
|
||||||
sceneInfra.modelingSend({ type: 'code edit during sketch' })
|
sceneInfra.modelingSend({ type: 'code edit during sketch' })
|
||||||
|
@ -212,7 +212,19 @@ Map {
|
|||||||
"type": "wall",
|
"type": "wall",
|
||||||
},
|
},
|
||||||
"UUID-10" => {
|
"UUID-10" => {
|
||||||
"codeRef": undefined,
|
"codeRef": {
|
||||||
|
"pathToNode": [
|
||||||
|
[
|
||||||
|
"body",
|
||||||
|
"",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
"range": [
|
||||||
|
312,
|
||||||
|
344,
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
},
|
||||||
"edgeCutEdgeIds": [],
|
"edgeCutEdgeIds": [],
|
||||||
"id": "UUID",
|
"id": "UUID",
|
||||||
"pathIds": [
|
"pathIds": [
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
import { makeDefaultPlanes, assertParse, initPromise, Program } from 'lang/wasm'
|
import {
|
||||||
|
makeDefaultPlanes,
|
||||||
|
assertParse,
|
||||||
|
initPromise,
|
||||||
|
Program,
|
||||||
|
ExecState,
|
||||||
|
} from 'lang/wasm'
|
||||||
import { Models } from '@kittycad/lib'
|
import { Models } from '@kittycad/lib'
|
||||||
import {
|
import {
|
||||||
OrderedCommand,
|
OrderedCommand,
|
||||||
@ -123,6 +129,7 @@ type CacheShape = {
|
|||||||
[key in CodeKey]: {
|
[key in CodeKey]: {
|
||||||
orderedCommands: OrderedCommand[]
|
orderedCommands: OrderedCommand[]
|
||||||
responseMap: ResponseMap
|
responseMap: ResponseMap
|
||||||
|
execStateArtifacts: ExecState['artifacts']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,6 +161,7 @@ beforeAll(async () => {
|
|||||||
cacheToWriteToFileTemp[codeKey] = {
|
cacheToWriteToFileTemp[codeKey] = {
|
||||||
orderedCommands: engineCommandManager.orderedCommands,
|
orderedCommands: engineCommandManager.orderedCommands,
|
||||||
responseMap: engineCommandManager.responseMap,
|
responseMap: engineCommandManager.responseMap,
|
||||||
|
execStateArtifacts: kclManager.execState.artifacts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const cache = JSON.stringify(cacheToWriteToFileTemp)
|
const cache = JSON.stringify(cacheToWriteToFileTemp)
|
||||||
@ -181,9 +189,15 @@ describe('testing createArtifactGraph', () => {
|
|||||||
orderedCommands,
|
orderedCommands,
|
||||||
responseMap,
|
responseMap,
|
||||||
ast: _ast,
|
ast: _ast,
|
||||||
|
execStateArtifacts,
|
||||||
} = getCommands('exampleCodeOffsetPlanes')
|
} = getCommands('exampleCodeOffsetPlanes')
|
||||||
ast = _ast
|
ast = _ast
|
||||||
theMap = createArtifactGraph({ orderedCommands, responseMap, ast })
|
theMap = createArtifactGraph({
|
||||||
|
orderedCommands,
|
||||||
|
responseMap,
|
||||||
|
ast,
|
||||||
|
execStateArtifacts,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`there should be one sketch`, () => {
|
it(`there should be one sketch`, () => {
|
||||||
@ -226,9 +240,15 @@ describe('testing createArtifactGraph', () => {
|
|||||||
orderedCommands,
|
orderedCommands,
|
||||||
responseMap,
|
responseMap,
|
||||||
ast: _ast,
|
ast: _ast,
|
||||||
|
execStateArtifacts,
|
||||||
} = getCommands('exampleCode1')
|
} = getCommands('exampleCode1')
|
||||||
ast = _ast
|
ast = _ast
|
||||||
theMap = createArtifactGraph({ orderedCommands, responseMap, ast })
|
theMap = createArtifactGraph({
|
||||||
|
orderedCommands,
|
||||||
|
responseMap,
|
||||||
|
ast,
|
||||||
|
execStateArtifacts,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('there should be two planes for the extrusion and the sketch on face', () => {
|
it('there should be two planes for the extrusion and the sketch on face', () => {
|
||||||
@ -321,9 +341,15 @@ describe('testing createArtifactGraph', () => {
|
|||||||
orderedCommands,
|
orderedCommands,
|
||||||
responseMap,
|
responseMap,
|
||||||
ast: _ast,
|
ast: _ast,
|
||||||
|
execStateArtifacts,
|
||||||
} = getCommands('exampleCodeNo3D')
|
} = getCommands('exampleCodeNo3D')
|
||||||
ast = _ast
|
ast = _ast
|
||||||
theMap = createArtifactGraph({ orderedCommands, responseMap, ast })
|
theMap = createArtifactGraph({
|
||||||
|
orderedCommands,
|
||||||
|
responseMap,
|
||||||
|
ast,
|
||||||
|
execStateArtifacts,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('there should be two planes, one for each sketch path', () => {
|
it('there should be two planes, one for each sketch path', () => {
|
||||||
@ -386,9 +412,15 @@ describe('capture graph of sketchOnFaceOnFace...', () => {
|
|||||||
orderedCommands,
|
orderedCommands,
|
||||||
responseMap,
|
responseMap,
|
||||||
ast: _ast,
|
ast: _ast,
|
||||||
|
execStateArtifacts,
|
||||||
} = getCommands('sketchOnFaceOnFaceEtc')
|
} = getCommands('sketchOnFaceOnFaceEtc')
|
||||||
ast = _ast
|
ast = _ast
|
||||||
theMap = createArtifactGraph({ orderedCommands, responseMap, ast })
|
theMap = createArtifactGraph({
|
||||||
|
orderedCommands,
|
||||||
|
responseMap,
|
||||||
|
ast,
|
||||||
|
execStateArtifacts,
|
||||||
|
})
|
||||||
|
|
||||||
// Ostensibly this takes a screen shot of the graph of the artifactGraph
|
// Ostensibly this takes a screen shot of the graph of the artifactGraph
|
||||||
// but it's it also tests that all of the id links are correct because if one
|
// but it's it also tests that all of the id links are correct because if one
|
||||||
@ -409,10 +441,12 @@ function getCommands(
|
|||||||
// these either already exist from the last run, or were created in
|
// these either already exist from the last run, or were created in
|
||||||
const orderedCommands = parsed[codeKey].orderedCommands
|
const orderedCommands = parsed[codeKey].orderedCommands
|
||||||
const responseMap = parsed[codeKey].responseMap
|
const responseMap = parsed[codeKey].responseMap
|
||||||
|
const execStateArtifacts = parsed[codeKey].execStateArtifacts
|
||||||
return {
|
return {
|
||||||
orderedCommands,
|
orderedCommands,
|
||||||
responseMap,
|
responseMap,
|
||||||
ast,
|
ast,
|
||||||
|
execStateArtifacts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,8 +672,14 @@ async function GraphTheGraph(
|
|||||||
|
|
||||||
describe('testing getArtifactsToUpdate', () => {
|
describe('testing getArtifactsToUpdate', () => {
|
||||||
it('should return an array of artifacts to update', () => {
|
it('should return an array of artifacts to update', () => {
|
||||||
const { orderedCommands, responseMap, ast } = getCommands('exampleCode1')
|
const { orderedCommands, responseMap, ast, execStateArtifacts } =
|
||||||
const map = createArtifactGraph({ orderedCommands, responseMap, ast })
|
getCommands('exampleCode1')
|
||||||
|
const map = createArtifactGraph({
|
||||||
|
orderedCommands,
|
||||||
|
responseMap,
|
||||||
|
ast,
|
||||||
|
execStateArtifacts,
|
||||||
|
})
|
||||||
const getArtifact = (id: string) => map.get(id)
|
const getArtifact = (id: string) => map.get(id)
|
||||||
const currentPlaneId = 'UUID-1'
|
const currentPlaneId = 'UUID-1'
|
||||||
const getUpdateObjects = (type: Models['ModelingCmd_type']['type']) => {
|
const getUpdateObjects = (type: Models['ModelingCmd_type']['type']) => {
|
||||||
@ -652,6 +692,7 @@ describe('testing getArtifactsToUpdate', () => {
|
|||||||
getArtifact,
|
getArtifact,
|
||||||
currentPlaneId,
|
currentPlaneId,
|
||||||
ast,
|
ast,
|
||||||
|
execStateArtifacts,
|
||||||
})
|
})
|
||||||
return artifactsToUpdate.map(({ artifact }) => artifact)
|
return artifactsToUpdate.map(({ artifact }) => artifact)
|
||||||
}
|
}
|
||||||
@ -779,6 +820,10 @@ describe('testing getArtifactsToUpdate', () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'wall',
|
type: 'wall',
|
||||||
|
codeRef: {
|
||||||
|
pathToNode: [['body', '']],
|
||||||
|
range: [312, 344, true],
|
||||||
|
},
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
segId: expect.any(String),
|
segId: expect.any(String),
|
||||||
edgeCutEdgeIds: [],
|
edgeCutEdgeIds: [],
|
||||||
|
@ -1,16 +1,6 @@
|
|||||||
import {
|
import { ExecState, Expr, PathToNode, Program, SourceRange } from 'lang/wasm'
|
||||||
Expr,
|
|
||||||
PathToNode,
|
|
||||||
Program,
|
|
||||||
SourceRange,
|
|
||||||
VariableDeclaration,
|
|
||||||
} from 'lang/wasm'
|
|
||||||
import { Models } from '@kittycad/lib'
|
import { Models } from '@kittycad/lib'
|
||||||
import {
|
import { getNodePathFromSourceRange } from 'lang/queryAst'
|
||||||
getNodeFromPath,
|
|
||||||
getNodePathFromSourceRange,
|
|
||||||
traverse,
|
|
||||||
} from 'lang/queryAst'
|
|
||||||
import { err } from 'lib/trap'
|
import { err } from 'lib/trap'
|
||||||
import { engineCommandManager, kclManager } from 'lib/singletons'
|
import { engineCommandManager, kclManager } from 'lib/singletons'
|
||||||
import { Node } from 'wasm-lib/kcl/bindings/Node'
|
import { Node } from 'wasm-lib/kcl/bindings/Node'
|
||||||
@ -174,10 +164,12 @@ export function createArtifactGraph({
|
|||||||
orderedCommands,
|
orderedCommands,
|
||||||
responseMap,
|
responseMap,
|
||||||
ast,
|
ast,
|
||||||
|
execStateArtifacts,
|
||||||
}: {
|
}: {
|
||||||
orderedCommands: Array<OrderedCommand>
|
orderedCommands: Array<OrderedCommand>
|
||||||
responseMap: ResponseMap
|
responseMap: ResponseMap
|
||||||
ast: Node<Program>
|
ast: Node<Program>
|
||||||
|
execStateArtifacts: ExecState['artifacts']
|
||||||
}) {
|
}) {
|
||||||
const myMap = new Map<ArtifactId, Artifact>()
|
const myMap = new Map<ArtifactId, Artifact>()
|
||||||
|
|
||||||
@ -199,6 +191,7 @@ export function createArtifactGraph({
|
|||||||
getArtifact: (id: ArtifactId) => myMap.get(id),
|
getArtifact: (id: ArtifactId) => myMap.get(id),
|
||||||
currentPlaneId,
|
currentPlaneId,
|
||||||
ast,
|
ast,
|
||||||
|
execStateArtifacts,
|
||||||
})
|
})
|
||||||
artifactsToUpdate.forEach(({ id, artifact }) => {
|
artifactsToUpdate.forEach(({ id, artifact }) => {
|
||||||
const mergedArtifact = mergeArtifacts(myMap.get(id), artifact)
|
const mergedArtifact = mergeArtifacts(myMap.get(id), artifact)
|
||||||
@ -250,6 +243,7 @@ export function getArtifactsToUpdate({
|
|||||||
responseMap,
|
responseMap,
|
||||||
currentPlaneId,
|
currentPlaneId,
|
||||||
ast,
|
ast,
|
||||||
|
execStateArtifacts,
|
||||||
}: {
|
}: {
|
||||||
orderedCommand: OrderedCommand
|
orderedCommand: OrderedCommand
|
||||||
responseMap: ResponseMap
|
responseMap: ResponseMap
|
||||||
@ -257,6 +251,7 @@ export function getArtifactsToUpdate({
|
|||||||
getArtifact: (id: ArtifactId) => Artifact | undefined
|
getArtifact: (id: ArtifactId) => Artifact | undefined
|
||||||
currentPlaneId: ArtifactId
|
currentPlaneId: ArtifactId
|
||||||
ast: Node<Program>
|
ast: Node<Program>
|
||||||
|
execStateArtifacts: ExecState['artifacts']
|
||||||
}): Array<{
|
}): Array<{
|
||||||
id: ArtifactId
|
id: ArtifactId
|
||||||
artifact: Artifact
|
artifact: Artifact
|
||||||
@ -292,13 +287,6 @@ export function getArtifactsToUpdate({
|
|||||||
plane?.type === 'plane' ? plane?.codeRef : { range, pathToNode }
|
plane?.type === 'plane' ? plane?.codeRef : { range, pathToNode }
|
||||||
const existingPlane = getArtifact(currentPlaneId)
|
const existingPlane = getArtifact(currentPlaneId)
|
||||||
if (existingPlane?.type === 'wall') {
|
if (existingPlane?.type === 'wall') {
|
||||||
let existingPlaneCodeRef = existingPlane.codeRef
|
|
||||||
if (!existingPlaneCodeRef) {
|
|
||||||
const astWalkCodeRef = getWallOrCapPlaneCodeRef(ast, codeRef.pathToNode)
|
|
||||||
if (!err(astWalkCodeRef)) {
|
|
||||||
existingPlaneCodeRef = astWalkCodeRef
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: currentPlaneId,
|
id: currentPlaneId,
|
||||||
@ -309,18 +297,11 @@ export function getArtifactsToUpdate({
|
|||||||
edgeCutEdgeIds: existingPlane.edgeCutEdgeIds,
|
edgeCutEdgeIds: existingPlane.edgeCutEdgeIds,
|
||||||
sweepId: existingPlane.sweepId,
|
sweepId: existingPlane.sweepId,
|
||||||
pathIds: existingPlane.pathIds,
|
pathIds: existingPlane.pathIds,
|
||||||
codeRef: existingPlaneCodeRef,
|
codeRef: existingPlane.codeRef,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
} else if (existingPlane?.type === 'cap') {
|
} else if (existingPlane?.type === 'cap') {
|
||||||
let existingPlaneCodeRef = existingPlane.codeRef
|
|
||||||
if (!existingPlaneCodeRef) {
|
|
||||||
const astWalkCodeRef = getWallOrCapPlaneCodeRef(ast, codeRef.pathToNode)
|
|
||||||
if (!err(astWalkCodeRef)) {
|
|
||||||
existingPlaneCodeRef = astWalkCodeRef
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: currentPlaneId,
|
id: currentPlaneId,
|
||||||
@ -331,7 +312,7 @@ export function getArtifactsToUpdate({
|
|||||||
edgeCutEdgeIds: existingPlane.edgeCutEdgeIds,
|
edgeCutEdgeIds: existingPlane.edgeCutEdgeIds,
|
||||||
sweepId: existingPlane.sweepId,
|
sweepId: existingPlane.sweepId,
|
||||||
pathIds: existingPlane.pathIds,
|
pathIds: existingPlane.pathIds,
|
||||||
codeRef: existingPlaneCodeRef,
|
codeRef: existingPlane.codeRef,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -467,16 +448,33 @@ export function getArtifactsToUpdate({
|
|||||||
const path = getArtifact(seg.pathId)
|
const path = getArtifact(seg.pathId)
|
||||||
if (path?.type === 'path' && seg?.type === 'segment') {
|
if (path?.type === 'path' && seg?.type === 'segment') {
|
||||||
lastPath = path
|
lastPath = path
|
||||||
returnArr.push({
|
const extraArtifact = Object.values(execStateArtifacts).find(
|
||||||
id: face_id,
|
(a) => a?.type === 'StartSketchOnFace' && a.faceId === face_id
|
||||||
artifact: {
|
)
|
||||||
|
const sketchOnFaceSourceRange = extraArtifact?.sourceRange
|
||||||
|
const wallArtifact: Artifact = {
|
||||||
type: 'wall',
|
type: 'wall',
|
||||||
id: face_id,
|
id: face_id,
|
||||||
segId: curve_id,
|
segId: curve_id,
|
||||||
edgeCutEdgeIds: [],
|
edgeCutEdgeIds: [],
|
||||||
sweepId: path.sweepId,
|
sweepId: path.sweepId,
|
||||||
pathIds: [],
|
pathIds: [],
|
||||||
},
|
}
|
||||||
|
|
||||||
|
if (sketchOnFaceSourceRange) {
|
||||||
|
const range: SourceRange = [
|
||||||
|
sketchOnFaceSourceRange[0],
|
||||||
|
sketchOnFaceSourceRange[1],
|
||||||
|
true,
|
||||||
|
]
|
||||||
|
wallArtifact.codeRef = {
|
||||||
|
range,
|
||||||
|
pathToNode: getNodePathFromSourceRange(ast, range),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
returnArr.push({
|
||||||
|
id: face_id,
|
||||||
|
artifact: wallArtifact,
|
||||||
})
|
})
|
||||||
returnArr.push({
|
returnArr.push({
|
||||||
id: curve_id,
|
id: curve_id,
|
||||||
@ -500,16 +498,33 @@ export function getArtifactsToUpdate({
|
|||||||
if ((cap === 'top' || cap === 'bottom') && face_id) {
|
if ((cap === 'top' || cap === 'bottom') && face_id) {
|
||||||
const path = lastPath
|
const path = lastPath
|
||||||
if (path?.type === 'path') {
|
if (path?.type === 'path') {
|
||||||
returnArr.push({
|
const extraArtifact = Object.values(execStateArtifacts).find(
|
||||||
id: face_id,
|
(a) => a?.type === 'StartSketchOnFace' && a.faceId === face_id
|
||||||
artifact: {
|
)
|
||||||
|
const sketchOnFaceSourceRange = extraArtifact?.sourceRange
|
||||||
|
const capArtifact: Artifact = {
|
||||||
type: 'cap',
|
type: 'cap',
|
||||||
id: face_id,
|
id: face_id,
|
||||||
subType: cap === 'bottom' ? 'start' : 'end',
|
subType: cap === 'bottom' ? 'start' : 'end',
|
||||||
edgeCutEdgeIds: [],
|
edgeCutEdgeIds: [],
|
||||||
sweepId: path.sweepId,
|
sweepId: path.sweepId,
|
||||||
pathIds: [],
|
pathIds: [],
|
||||||
},
|
}
|
||||||
|
if (sketchOnFaceSourceRange) {
|
||||||
|
const range: SourceRange = [
|
||||||
|
sketchOnFaceSourceRange[0],
|
||||||
|
sketchOnFaceSourceRange[1],
|
||||||
|
true,
|
||||||
|
]
|
||||||
|
|
||||||
|
capArtifact.codeRef = {
|
||||||
|
range,
|
||||||
|
pathToNode: getNodePathFromSourceRange(ast, range),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
returnArr.push({
|
||||||
|
id: face_id,
|
||||||
|
artifact: capArtifact,
|
||||||
})
|
})
|
||||||
const sweep = getArtifact(path.sweepId)
|
const sweep = getArtifact(path.sweepId)
|
||||||
if (sweep?.type !== 'sweep') return
|
if (sweep?.type !== 'sweep') return
|
||||||
@ -1131,84 +1146,6 @@ function isNodeSafe(node: Expr): boolean {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@deprecated} this information should come from the ArtifactGraph not digging around in the AST */
|
|
||||||
function getWallOrCapPlaneCodeRef(
|
|
||||||
ast: Node<Program>,
|
|
||||||
pathToNode: PathToNode
|
|
||||||
): CodeRef | Error {
|
|
||||||
const varDec = getNodeFromPath<VariableDeclaration>(
|
|
||||||
ast,
|
|
||||||
pathToNode,
|
|
||||||
'VariableDeclaration'
|
|
||||||
)
|
|
||||||
if (err(varDec)) return varDec
|
|
||||||
if (varDec.node.type !== 'VariableDeclaration')
|
|
||||||
return new Error('Expected VariableDeclaration')
|
|
||||||
const init = varDec.node.declaration.init
|
|
||||||
let varName = ''
|
|
||||||
if (
|
|
||||||
init.type === 'CallExpression' &&
|
|
||||||
init.callee.type === 'Identifier' &&
|
|
||||||
(init.callee.name === 'circle' || init.callee.name === 'startProfileAt')
|
|
||||||
) {
|
|
||||||
const secondArg = init.arguments[1]
|
|
||||||
if (secondArg.type === 'Identifier') {
|
|
||||||
varName = secondArg.name
|
|
||||||
}
|
|
||||||
} else if (init.type === 'PipeExpression') {
|
|
||||||
const firstExpr = init.body[0]
|
|
||||||
if (
|
|
||||||
firstExpr.type === 'CallExpression' &&
|
|
||||||
firstExpr.callee.type === 'Identifier' &&
|
|
||||||
firstExpr.callee.name === 'startProfileAt'
|
|
||||||
) {
|
|
||||||
const secondArg = firstExpr.arguments[1]
|
|
||||||
if (secondArg.type === 'Identifier') {
|
|
||||||
varName = secondArg.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (varName === '') return new Error('Could not find variable name')
|
|
||||||
|
|
||||||
let currentVariableName = ''
|
|
||||||
const planeCodeRef: Array<{
|
|
||||||
path: PathToNode
|
|
||||||
sketchName: string
|
|
||||||
range: SourceRange
|
|
||||||
}> = []
|
|
||||||
traverse(ast, {
|
|
||||||
leave: (node) => {
|
|
||||||
if (node.type === 'VariableDeclaration') {
|
|
||||||
currentVariableName = ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
enter: (node, path) => {
|
|
||||||
if (node.type === 'VariableDeclaration') {
|
|
||||||
currentVariableName = node.declaration.id.name
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
// match `${varName} = startSketchOn(...)`
|
|
||||||
node.type === 'CallExpression' &&
|
|
||||||
node.callee.name === 'startSketchOn' &&
|
|
||||||
node.arguments[0].type === 'Identifier' &&
|
|
||||||
currentVariableName === varName
|
|
||||||
) {
|
|
||||||
planeCodeRef.push({
|
|
||||||
path,
|
|
||||||
sketchName: currentVariableName,
|
|
||||||
range: [node.start, node.end, true],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if (!planeCodeRef.length)
|
|
||||||
return new Error('No paths found depending on extrude')
|
|
||||||
|
|
||||||
return {
|
|
||||||
pathToNode: planeCodeRef[0].path,
|
|
||||||
range: planeCodeRef[0].range,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Get an artifact from a code source range
|
* Get an artifact from a code source range
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
defaultRustSourceRange,
|
defaultRustSourceRange,
|
||||||
defaultSourceRange,
|
defaultSourceRange,
|
||||||
|
ExecState,
|
||||||
Program,
|
Program,
|
||||||
RustSourceRange,
|
RustSourceRange,
|
||||||
SourceRange,
|
SourceRange,
|
||||||
@ -2116,11 +2117,15 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
Object.values(this.pendingCommands).map((a) => a.promise)
|
Object.values(this.pendingCommands).map((a) => a.promise)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
updateArtifactGraph(ast: Node<Program>) {
|
updateArtifactGraph(
|
||||||
|
ast: Node<Program>,
|
||||||
|
execStateArtifacts: ExecState['artifacts']
|
||||||
|
) {
|
||||||
this.artifactGraph = createArtifactGraph({
|
this.artifactGraph = createArtifactGraph({
|
||||||
orderedCommands: this.orderedCommands,
|
orderedCommands: this.orderedCommands,
|
||||||
responseMap: this.responseMap,
|
responseMap: this.responseMap,
|
||||||
ast,
|
ast,
|
||||||
|
execStateArtifacts,
|
||||||
})
|
})
|
||||||
// TODO check if these still need to be deferred once e2e tests are working again.
|
// TODO check if these still need to be deferred once e2e tests are working again.
|
||||||
if (this.artifactGraph.size) {
|
if (this.artifactGraph.size) {
|
||||||
|
@ -44,7 +44,11 @@ import { CompilationError } from 'wasm-lib/kcl/bindings/CompilationError'
|
|||||||
import { SourceRange as RustSourceRange } from 'wasm-lib/kcl/bindings/SourceRange'
|
import { SourceRange as RustSourceRange } from 'wasm-lib/kcl/bindings/SourceRange'
|
||||||
import { getAllCurrentSettings } from 'lib/settings/settingsUtils'
|
import { getAllCurrentSettings } from 'lib/settings/settingsUtils'
|
||||||
import { KclErrorWithOutputs } from 'wasm-lib/kcl/bindings/KclErrorWithOutputs'
|
import { KclErrorWithOutputs } from 'wasm-lib/kcl/bindings/KclErrorWithOutputs'
|
||||||
|
import { Artifact } from 'wasm-lib/kcl/bindings/Artifact'
|
||||||
|
import { ArtifactId } from 'wasm-lib/kcl/bindings/ArtifactId'
|
||||||
|
|
||||||
|
export type { Artifact } from 'wasm-lib/kcl/bindings/Artifact'
|
||||||
|
export type { ArtifactId } from 'wasm-lib/kcl/bindings/ArtifactId'
|
||||||
export type { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
|
export type { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
|
||||||
export type { Program } from '../wasm-lib/kcl/bindings/Program'
|
export type { Program } from '../wasm-lib/kcl/bindings/Program'
|
||||||
export type { Expr } from '../wasm-lib/kcl/bindings/Expr'
|
export type { Expr } from '../wasm-lib/kcl/bindings/Expr'
|
||||||
@ -245,6 +249,7 @@ export const isPathToNodeNumber = (
|
|||||||
|
|
||||||
export interface ExecState {
|
export interface ExecState {
|
||||||
memory: ProgramMemory
|
memory: ProgramMemory
|
||||||
|
artifacts: { [key in ArtifactId]?: Artifact }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -254,12 +259,14 @@ export interface ExecState {
|
|||||||
export function emptyExecState(): ExecState {
|
export function emptyExecState(): ExecState {
|
||||||
return {
|
return {
|
||||||
memory: ProgramMemory.empty(),
|
memory: ProgramMemory.empty(),
|
||||||
|
artifacts: {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function execStateFromRaw(raw: RawExecState): ExecState {
|
function execStateFromRaw(raw: RawExecState): ExecState {
|
||||||
return {
|
return {
|
||||||
memory: ProgramMemory.fromRaw(raw.modLocal.memory),
|
memory: ProgramMemory.fromRaw(raw.modLocal.memory),
|
||||||
|
artifacts: raw.global.artifacts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
47
src/wasm-lib/kcl/src/execution/artifact.rs
Normal file
47
src/wasm-lib/kcl/src/execution/artifact.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use schemars::JsonSchema;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::SourceRange;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Hash, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
pub struct ArtifactId(Uuid);
|
||||||
|
|
||||||
|
impl ArtifactId {
|
||||||
|
pub fn new(uuid: Uuid) -> Self {
|
||||||
|
Self(uuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Uuid> for ArtifactId {
|
||||||
|
fn from(uuid: Uuid) -> Self {
|
||||||
|
Self::new(uuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Uuid> for ArtifactId {
|
||||||
|
fn from(uuid: &Uuid) -> Self {
|
||||||
|
Self::new(*uuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Artifact {
|
||||||
|
pub id: ArtifactId,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub inner: ArtifactInner,
|
||||||
|
pub source_range: SourceRange,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum ArtifactInner {
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
StartSketchOnFace { face_id: Uuid },
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
StartSketchOnPlane { plane_id: Uuid },
|
||||||
|
}
|
@ -25,6 +25,7 @@ pub use kcl_value::{KclObjectFields, KclValue};
|
|||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
mod annotations;
|
mod annotations;
|
||||||
|
mod artifact;
|
||||||
pub(crate) mod cache;
|
pub(crate) mod cache;
|
||||||
mod cad_op;
|
mod cad_op;
|
||||||
mod exec_ast;
|
mod exec_ast;
|
||||||
@ -47,6 +48,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Re-exports.
|
// Re-exports.
|
||||||
|
pub use artifact::{Artifact, ArtifactId, ArtifactInner};
|
||||||
pub use cad_op::Operation;
|
pub use cad_op::Operation;
|
||||||
|
|
||||||
/// State for executing a program.
|
/// State for executing a program.
|
||||||
@ -68,6 +70,8 @@ pub struct GlobalState {
|
|||||||
pub path_to_source_id: IndexMap<std::path::PathBuf, ModuleId>,
|
pub path_to_source_id: IndexMap<std::path::PathBuf, ModuleId>,
|
||||||
/// Map from module ID to module info.
|
/// Map from module ID to module info.
|
||||||
pub module_infos: IndexMap<ModuleId, ModuleInfo>,
|
pub module_infos: IndexMap<ModuleId, ModuleInfo>,
|
||||||
|
/// Output map of UUIDs to artifacts.
|
||||||
|
pub artifacts: IndexMap<ArtifactId, Artifact>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
@ -134,6 +138,11 @@ impl ExecState {
|
|||||||
self.global.id_generator.next_uuid()
|
self.global.id_generator.next_uuid()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_artifact(&mut self, artifact: Artifact) {
|
||||||
|
let id = artifact.id;
|
||||||
|
self.global.artifacts.insert(id, artifact);
|
||||||
|
}
|
||||||
|
|
||||||
async fn add_module(
|
async fn add_module(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: std::path::PathBuf,
|
path: std::path::PathBuf,
|
||||||
@ -171,6 +180,7 @@ impl GlobalState {
|
|||||||
id_generator: Default::default(),
|
id_generator: Default::default(),
|
||||||
path_to_source_id: Default::default(),
|
path_to_source_id: Default::default(),
|
||||||
module_infos: Default::default(),
|
module_infos: Default::default(),
|
||||||
|
artifacts: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO(#4434): Use the top-level file's path.
|
// TODO(#4434): Use the top-level file's path.
|
||||||
|
@ -11,6 +11,7 @@ use parse_display::{Display, FromStr};
|
|||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::execution::{Artifact, ArtifactId, ArtifactInner};
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
@ -1075,7 +1076,17 @@ async fn inner_start_sketch_on(
|
|||||||
let plane = make_sketch_plane_from_orientation(plane_data, exec_state, args).await?;
|
let plane = make_sketch_plane_from_orientation(plane_data, exec_state, args).await?;
|
||||||
Ok(SketchSurface::Plane(plane))
|
Ok(SketchSurface::Plane(plane))
|
||||||
}
|
}
|
||||||
SketchData::Plane(plane) => Ok(SketchSurface::Plane(plane)),
|
SketchData::Plane(plane) => {
|
||||||
|
// Create artifact used only by the UI, not the engine.
|
||||||
|
let id = exec_state.next_uuid();
|
||||||
|
exec_state.add_artifact(Artifact {
|
||||||
|
id: ArtifactId::from(id),
|
||||||
|
inner: ArtifactInner::StartSketchOnPlane { plane_id: plane.id },
|
||||||
|
source_range: args.source_range,
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(SketchSurface::Plane(plane))
|
||||||
|
}
|
||||||
SketchData::Solid(solid) => {
|
SketchData::Solid(solid) => {
|
||||||
let Some(tag) = tag else {
|
let Some(tag) = tag else {
|
||||||
return Err(KclError::Type(KclErrorDetails {
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
@ -1084,6 +1095,15 @@ async fn inner_start_sketch_on(
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
let face = start_sketch_on_face(solid, tag, exec_state, args).await?;
|
let face = start_sketch_on_face(solid, tag, exec_state, args).await?;
|
||||||
|
|
||||||
|
// Create artifact used only by the UI, not the engine.
|
||||||
|
let id = exec_state.next_uuid();
|
||||||
|
exec_state.add_artifact(Artifact {
|
||||||
|
id: ArtifactId::from(id),
|
||||||
|
inner: ArtifactInner::StartSketchOnFace { face_id: face.id },
|
||||||
|
source_range: args.source_range,
|
||||||
|
});
|
||||||
|
|
||||||
Ok(SketchSurface::Face(face))
|
Ok(SketchSurface::Face(face))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user