diff --git a/src/clientSideScene/sceneEntities.ts b/src/clientSideScene/sceneEntities.ts index 952b32da8..521e3ab97 100644 --- a/src/clientSideScene/sceneEntities.ts +++ b/src/clientSideScene/sceneEntities.ts @@ -123,6 +123,8 @@ import { Node } from '@rust/kcl-lib/bindings/Node' import { radToDeg } from 'three/src/math/MathUtils' import toast from 'react-hot-toast' import { getArtifactFromRange, codeRefFromRange } from 'lang/std/artifactGraph' +import { updateModelingState } from 'lang/modelingWorkflows' +import { EXECUTION_TYPE_MOCK } from 'lib/constants' type DraftSegment = 'line' | 'tangentialArcTo' @@ -1075,7 +1077,11 @@ export class SceneEntities { return } - await kclManager.executeAstMock(modifiedAst) + await updateModelingState(modifiedAst, EXECUTION_TYPE_MOCK, { + kclManager, + editorManager, + codeManager, + }) if (intersectsProfileStart) { sceneInfra.modelingSend({ type: 'Close sketch' }) @@ -1090,8 +1096,6 @@ export class SceneEntities { segmentName ) } - - await codeManager.updateEditorWithAstAndWriteToFile(modifiedAst) }, onMove: (args) => { const expressionIndex = Number(sketchEntryNodePath[1][0]) @@ -1303,13 +1307,16 @@ export class SceneEntities { _ast = pResult.program // Update the primary AST and unequip the rectangle tool - await kclManager.executeAstMock(_ast) - sceneInfra.modelingSend({ type: 'Finish rectangle' }) - + // // lee: I had this at the bottom of the function, but it's // possible sketchFromKclValue "fails" when sketching on a face, // and this couldn't wouldn't run. - await codeManager.updateEditorWithAstAndWriteToFile(_ast) + await updateModelingState(_ast, EXECUTION_TYPE_MOCK, { + kclManager, + editorManager, + codeManager, + }) + sceneInfra.modelingSend({ type: 'Finish rectangle' }) }, }) return { @@ -1493,13 +1500,16 @@ export class SceneEntities { _ast = pResult.program // Update the primary AST and unequip the rectangle tool - await kclManager.executeAstMock(_ast) - sceneInfra.modelingSend({ type: 'Finish center rectangle' }) - + // // lee: I had this at the bottom of the function, but it's // possible sketchFromKclValue "fails" when sketching on a face, // and this couldn't wouldn't run. - await codeManager.updateEditorWithAstAndWriteToFile(_ast) + await updateModelingState(_ast, EXECUTION_TYPE_MOCK, { + kclManager, + editorManager, + codeManager, + }) + sceneInfra.modelingSend({ type: 'Finish center rectangle' }) } }, }) @@ -1678,9 +1688,12 @@ export class SceneEntities { _ast = pResult.program // Update the primary AST and unequip the rectangle tool - await kclManager.executeAstMock(_ast) + await updateModelingState(_ast, EXECUTION_TYPE_MOCK, { + kclManager, + editorManager, + codeManager, + }) sceneInfra.modelingSend({ type: 'Finish circle three point' }) - await codeManager.updateEditorWithAstAndWriteToFile(_ast) } }, }) @@ -1912,9 +1925,12 @@ export class SceneEntities { _ast = pResult.program // Update the primary AST and unequip the arc tool - await kclManager.executeAstMock(_ast) + await updateModelingState(_ast, EXECUTION_TYPE_MOCK, { + kclManager, + editorManager, + codeManager, + }) sceneInfra.modelingSend({ type: 'Finish arc' }) - await codeManager.updateEditorWithAstAndWriteToFile(_ast) } }, }) @@ -2166,13 +2182,16 @@ export class SceneEntities { _ast = pResult.program // Update the primary AST and unequip the arc tool - await kclManager.executeAstMock(_ast) + await updateModelingState(_ast, EXECUTION_TYPE_MOCK, { + kclManager, + editorManager, + codeManager, + }) if (intersectsProfileStart) { sceneInfra.modelingSend({ type: 'Close sketch' }) } else { sceneInfra.modelingSend({ type: 'Finish arc' }) } - await codeManager.updateEditorWithAstAndWriteToFile(_ast) } }, }) @@ -2364,9 +2383,12 @@ export class SceneEntities { _ast = pResult.program // Update the primary AST and unequip the rectangle tool - await kclManager.executeAstMock(_ast) + await updateModelingState(_ast, EXECUTION_TYPE_MOCK, { + kclManager, + editorManager, + codeManager, + }) sceneInfra.modelingSend({ type: 'Finish circle' }) - await codeManager.updateEditorWithAstAndWriteToFile(_ast) } }, }) diff --git a/src/components/ModelingMachineProvider.tsx b/src/components/ModelingMachineProvider.tsx index 114cb524e..ccabff146 100644 --- a/src/components/ModelingMachineProvider.tsx +++ b/src/components/ModelingMachineProvider.tsx @@ -119,6 +119,8 @@ import { EXPORT_TOAST_MESSAGES, MAKE_TOAST_MESSAGES } from 'lib/constants' import { exportMake } from 'lib/exportMake' import { exportSave } from 'lib/exportSave' import { Plane } from '@rust/kcl-lib/bindings/Plane' +import { updateModelingState } from 'lang/modelingWorkflows' +import { EXECUTION_TYPE_MOCK } from 'lib/constants' export const ModelingMachineContext = createContext( {} as { @@ -1660,7 +1662,7 @@ export const ModelingMachineProvider = ({ sketchDetails.sketchEntryNodePath ) if (err(doesNeedSplitting)) return reject(doesNeedSplitting) - let moddedAst: Program = structuredClone(kclManager.ast) + let moddedAst: Node = structuredClone(kclManager.ast) let pathToProfile = sketchDetails.sketchEntryNodePath let updatedSketchNodePaths = sketchDetails.sketchNodePaths if (doesNeedSplitting) { @@ -1722,8 +1724,11 @@ export const ModelingMachineProvider = ({ indexToDelete >= 0 || isLastInPipeThreePointArc ) { - await kclManager.executeAstMock(moddedAst) - await codeManager.updateEditorWithAstAndWriteToFile(moddedAst) + await updateModelingState(moddedAst, EXECUTION_TYPE_MOCK, { + kclManager, + editorManager, + codeManager, + }) } return { updatedEntryNodePath: pathToProfile, diff --git a/src/lang/KclSingleton.ts b/src/lang/KclSingleton.ts index b2fe7b99b..45def4d56 100644 --- a/src/lang/KclSingleton.ts +++ b/src/lang/KclSingleton.ts @@ -2,12 +2,12 @@ import { executeAst, executeAstMock, lintAst } from 'lang/langHelpers' import { handleSelectionBatch, Selections } from 'lib/selections' import { KCLError, - complilationErrorsToDiagnostics, + compilationErrorsToDiagnostics, kclErrorsToDiagnostics, } from './errors' import { uuidv4 } from 'lib/utils' import { EngineCommandManager } from './std/engineConnection' -import { err } from 'lib/trap' +import { err, reportRejection } from 'lib/trap' import { EXECUTE_AST_INTERRUPT_ERROR_MESSAGE } from 'lib/constants' import { @@ -295,8 +295,8 @@ export class KclManager { this._astParseFailed = false if (err(result)) { - const kclerror: KCLError = result as KCLError - this.diagnostics = kclErrorsToDiagnostics([kclerror]) + const kclError: KCLError = result as KCLError + this.diagnostics = kclErrorsToDiagnostics([kclError]) this._astParseFailed = true await this.checkIfSwitchedFilesShouldClear() @@ -310,8 +310,8 @@ export class KclManager { this._kclErrorsCallBack([]) this._logsCallBack([]) - this.addDiagnostics(complilationErrorsToDiagnostics(result.errors)) - this.addDiagnostics(complilationErrorsToDiagnostics(result.warnings)) + this.addDiagnostics(compilationErrorsToDiagnostics(result.errors)) + this.addDiagnostics(compilationErrorsToDiagnostics(result.warnings)) if (result.errors.length > 0) { this._astParseFailed = true @@ -337,8 +337,8 @@ export class KclManager { private _cancelTokens: Map = new Map() // This NEVER updates the code, if you want to update the code DO NOT add to - // this function, too many other things that don't want it exist. - // just call to codeManager from wherever you want in other files. + // this function, too many other things that don't want it exist. For that, + // use updateModelingState(). async executeAst(args: ExecuteArgs = {}): Promise { if (this.isExecuting) { this.executeIsStale = args @@ -420,7 +420,7 @@ export class KclManager { this.addDiagnostics(isInterrupted ? [] : kclErrorsToDiagnostics(errors)) // Add warnings and non-fatal errors this.addDiagnostics( - isInterrupted ? [] : complilationErrorsToDiagnostics(execState.errors) + isInterrupted ? [] : compilationErrorsToDiagnostics(execState.errors) ) this.execState = execState if (!errors.length) { @@ -460,7 +460,6 @@ export class KclManager { markOnce('code/endExecuteAst') } - // NOTE: this always updates the code state and editor. // DO NOT CALL THIS from codemirror ever. async executeAstMock(ast: Program) { await this.ensureWasmInit() @@ -472,7 +471,7 @@ export class KclManager { } const newAst = await this.safeParse(newCode) if (!newAst) { - // By clearning the AST we indicate to our callers that there was an issue with execution and + // By clearing the AST we indicate to our callers that there was an issue with execution and // the pre-execution state should be restored. this.clearAst() return @@ -501,7 +500,7 @@ export class KclManager { const ast = await this.safeParse(codeManager.code) if (!ast) { - // By clearning the AST we indicate to our callers that there was an issue with execution and + // By clearing the AST we indicate to our callers that there was an issue with execution and // the pre-execution state should be restored. this.clearAst() return @@ -516,8 +515,8 @@ export class KclManager { * This will override the zoom to fit to zoom into the model if the previous AST was empty. * Workflows this improves, * When someone comments the entire file then uncomments the entire file it zooms to the model - * When someone CRTL+A and deletes the code then adds the code back it zooms to the model - * When someone CRTL+A and copies new code into the editor it zooms to the model + * When someone CTRL+A and deletes the code then adds the code back it zooms to the model + * When someone CTRL+A and copies new code into the editor it zooms to the model */ tryToZoomToFitOnCodeUpdate( ast: Node, @@ -555,12 +554,16 @@ export class KclManager { codeManager.updateCodeStateEditor(code) // Write back to the file system. - void codeManager.writeToFile().then(() => this.executeCode()) + void codeManager + .writeToFile() + .then(() => this.executeCode()) + .catch(reportRejection) } + // There's overlapping responsibility between updateAst and executeAst. // updateAst was added as it was used a lot before xState migration so makes the port easier. // but should probably have think about which of the function to keep - // This always updates the code state and editor and writes to the file system. + // This never updates the code state or editor and doesn't write to the file system. async updateAst( ast: Node, execute: boolean, @@ -627,7 +630,6 @@ export class KclManager { // When we don't re-execute, we still want to update the program // memory with the new ast. So we will hit the mock executor // instead.. - // Execute ast mock will update the code state and editor. await this.executeAstMock(astWithUpdatedSource) } diff --git a/src/lang/codeManager.ts b/src/lang/codeManager.ts index 4a36dac80..96ea4fa2c 100644 --- a/src/lang/codeManager.ts +++ b/src/lang/codeManager.ts @@ -165,10 +165,11 @@ export default class CodeManager { } async updateEditorWithAstAndWriteToFile(ast: Program) { - // We clear the AST when there it cannot be parsed, so if we are trying to write an empty AST, its - // probably because of an earlier error. That's a bad state to be in and it's not going to be - // pretty, but at the least, lets not permanently delete the user's code. - // If you want to clear the scene, call updateCodeStateEditor directly. + // We clear the AST when it cannot be parsed. If we are trying to write an + // empty AST, it's probably because of an earlier error. That's a bad state + // to be in, and it's not going to be pretty, but at the least, let's not + // permanently delete the user's code. If you want to clear the scene, call + // updateCodeStateEditor directly. if (ast.body.length === 0) return const newCode = recast(ast) if (err(newCode)) return diff --git a/src/lang/errors.ts b/src/lang/errors.ts index 7570830ff..efb35ca67 100644 --- a/src/lang/errors.ts +++ b/src/lang/errors.ts @@ -320,7 +320,7 @@ export function kclErrorsToDiagnostics( }) } -export function complilationErrorsToDiagnostics( +export function compilationErrorsToDiagnostics( errors: CompilationError[] ): CodeMirrorDiagnostic[] { return errors diff --git a/src/lang/modelingWorkflows.ts b/src/lang/modelingWorkflows.ts index 9882cfc65..d77bcf4b3 100644 --- a/src/lang/modelingWorkflows.ts +++ b/src/lang/modelingWorkflows.ts @@ -8,6 +8,12 @@ import { Node } from '@rust/kcl-lib/bindings/Node' import { KclManager } from 'lang/KclSingleton' +import { ExecutionType } from 'lib/constants' +import { + EXECUTION_TYPE_MOCK, + EXECUTION_TYPE_NONE, + EXECUTION_TYPE_REAL, +} from 'lib/constants' import { PathToNode, Program, SourceRange } from 'lang/wasm' import EditorManager from 'editor/manager' import CodeManager from 'lang/codeManager' @@ -32,12 +38,13 @@ import CodeManager from 'lang/codeManager' * regardless of geometric validity issues. * * @param ast - AST to commit + * @param executionType - How to execute the AST * @param dependencies - Required system components * @param options - Optional parameters for focus, zoom, etc. */ - export async function updateModelingState( ast: Node, + executionType: ExecutionType, dependencies: { kclManager: KclManager editorManager: EditorManager @@ -55,6 +62,7 @@ export async function updateModelingState( // Step 1: Update AST without executing (prepare selections) const updatedAst = await dependencies.kclManager.updateAst( ast, + // false == mock execution. Is this what we want? false, // Execution handled separately for error resilience options ) @@ -69,14 +77,20 @@ export async function updateModelingState( dependencies.editorManager.selectRange(updatedAst.selections) } - // Step 4: Try to execute the new code in the engine + // Step 4: Try to execute the new code // and continue regardless of errors try { - await dependencies.kclManager.executeAst({ - ast: updatedAst.newAst, - zoomToFit: options?.zoomToFit, - zoomOnRangeAndType: options?.zoomOnRangeAndType, - }) + if (executionType === EXECUTION_TYPE_REAL) { + await dependencies.kclManager.executeAst({ + ast: updatedAst.newAst, + zoomToFit: options?.zoomToFit, + zoomOnRangeAndType: options?.zoomOnRangeAndType, + }) + } else if (executionType === EXECUTION_TYPE_MOCK) { + await dependencies.kclManager.executeAstMock(updatedAst.newAst) + } else if (executionType === EXECUTION_TYPE_NONE) { + // No execution. + } } catch (e) { console.error('Engine execution error (UI is still updated):', e) } diff --git a/src/lang/modifyAst.ts b/src/lang/modifyAst.ts index ca11775a7..f6197dd49 100644 --- a/src/lang/modifyAst.ts +++ b/src/lang/modifyAst.ts @@ -673,7 +673,7 @@ export function sketchOnExtrudedFace( sketchPathToNode: PathToNode, extrudePathToNode: PathToNode, info: ExtrudeFacePlane['faceInfo'] = { type: 'wall' } -): { modifiedAst: Program; pathToNode: PathToNode } | Error { +): { modifiedAst: Node; pathToNode: PathToNode } | Error { let _node = { ...node } const newSketchName = findUniqueName( node, @@ -1375,7 +1375,7 @@ export function moveValueIntoNewVariablePath( pathToNode: PathToNode, variableName: string ): { - modifiedAst: Program + modifiedAst: Node pathToReplacedNode?: PathToNode } { const meta = isNodeSafeToReplacePath(ast, pathToNode) @@ -1975,11 +1975,11 @@ making it safe for later code that uses part001 (the extrude in this example) * */ export function splitPipedProfile( - ast: Program, + ast: Node, pathToPipe: PathToNode ): | { - modifiedAst: Program + modifiedAst: Node pathToProfile: PathToNode pathToPlane: PathToNode } diff --git a/src/lang/modifyAst/addEdgeTreatment.ts b/src/lang/modifyAst/addEdgeTreatment.ts index 50afe408e..2b4e7de5c 100644 --- a/src/lang/modifyAst/addEdgeTreatment.ts +++ b/src/lang/modifyAst/addEdgeTreatment.ts @@ -39,6 +39,7 @@ import { Artifact, getSweepArtifactFromSelection } from 'lang/std/artifactGraph' import { Node } from '@rust/kcl-lib/bindings/Node' import { findKwArg } from 'lang/util' import { KclManager } from 'lang/KclSingleton' +import { EXECUTION_TYPE_REAL } from 'lib/constants' import { EngineCommandManager } from 'lang/std/engineConnection' import EditorManager from 'editor/manager' import CodeManager from 'lang/codeManager' @@ -86,6 +87,7 @@ export async function applyEdgeTreatmentToSelection( // 2. update ast await updateModelingState( modifiedAst, + EXECUTION_TYPE_REAL, { kclManager: dependencies.kclManager, editorManager: dependencies.editorManager, diff --git a/src/lang/modifyAst/deleteSelection.ts b/src/lang/modifyAst/deleteSelection.ts index 7941ddc8c..5d09ec5db 100644 --- a/src/lang/modifyAst/deleteSelection.ts +++ b/src/lang/modifyAst/deleteSelection.ts @@ -3,12 +3,15 @@ import { getFaceDetails } from 'clientSideScene/sceneEntities' import { deleteFromSelection } from 'lang/modifyAst' import { codeManager, + editorManager, engineCommandManager, kclManager, rustContext, } from 'lib/singletons' import { err } from 'lib/trap' import { executeAstMock } from 'lang/langHelpers' +import { updateModelingState } from 'lang/modelingWorkflows' +import { EXECUTION_TYPE_REAL } from 'lib/constants' export const deletionErrorMessage = 'Unable to delete selection. Please edit manually in code pane.' @@ -36,7 +39,9 @@ export async function deleteSelectionPromise( if (testExecute.errors.length) { return new Error(deletionErrorMessage) } - - await kclManager.updateAst(modifiedAst, true) - await codeManager.updateEditorWithAstAndWriteToFile(modifiedAst) + await updateModelingState(modifiedAst, EXECUTION_TYPE_REAL, { + kclManager, + editorManager, + codeManager, + }) } diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 4c3aab6e0..21344fb29 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -167,3 +167,17 @@ export const ZOO_STUDIO_PROTOCOL = 'zoo-studio' * to "open in desktop app" when present in the URL */ export const ASK_TO_OPEN_QUERY_PARAM = 'ask-open-desktop' + +/** Real execution. */ +export const EXECUTION_TYPE_REAL = 'real' as const +/** Mock execution. */ +export const EXECUTION_TYPE_MOCK = 'mock' as const +/** No execution. */ +export const EXECUTION_TYPE_NONE = 'none' as const +/** + * Enum of engine execution kinds. + */ +export type ExecutionType = + | typeof EXECUTION_TYPE_REAL + | typeof EXECUTION_TYPE_MOCK + | typeof EXECUTION_TYPE_NONE diff --git a/src/machines/modelingMachine.ts b/src/machines/modelingMachine.ts index 0989e2426..454d3d65c 100644 --- a/src/machines/modelingMachine.ts +++ b/src/machines/modelingMachine.ts @@ -102,6 +102,7 @@ import { setAppearance } from 'lang/modifyAst/setAppearance' import { DRAFT_DASHED_LINE } from 'clientSideScene/sceneEntities' import { Node } from '@rust/kcl-lib/bindings/Node' import { updateModelingState } from 'lang/modelingWorkflows' +import { EXECUTION_TYPE_REAL } from 'lib/constants' export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY' @@ -751,20 +752,23 @@ export const modelingMachine = setup({ if (trap(revolveSketchRes)) return const { modifiedAst, pathToRevolveArg } = revolveSketchRes - const updatedAst = await kclManager.updateAst(modifiedAst, true, { - focusPath: [pathToRevolveArg], - zoomToFit: true, - zoomOnRangeAndType: { - range: selection.graphSelections[0]?.codeRef.range, - type: 'path', + await updateModelingState( + modifiedAst, + EXECUTION_TYPE_REAL, + { + kclManager, + editorManager, + codeManager, }, - }) - - await codeManager.updateEditorWithAstAndWriteToFile(updatedAst.newAst) - - if (updatedAst?.selections) { - editorManager.selectRange(updatedAst?.selections) - } + { + focusPath: [pathToRevolveArg], + zoomToFit: true, + zoomOnRangeAndType: { + range: selection.graphSelections[0]?.codeRef.range, + type: 'path', + }, + } + ) })().catch(reportRejection) }, 'set selection filter to curves only': () => { @@ -1797,20 +1801,23 @@ export const modelingMachine = setup({ pathToExtrudeArg[1][0]++ } - const updatedAst = await kclManager.updateAst(modifiedAst, true, { - focusPath: [pathToExtrudeArg], - zoomToFit: true, - zoomOnRangeAndType: { - range: selection.graphSelections[0]?.codeRef.range, - type: 'path', + await updateModelingState( + modifiedAst, + EXECUTION_TYPE_REAL, + { + kclManager, + editorManager, + codeManager, }, - }) - - await codeManager.updateEditorWithAstAndWriteToFile(updatedAst.newAst) - - if (updatedAst?.selections) { - editorManager.selectRange(updatedAst?.selections) - } + { + focusPath: [pathToExtrudeArg], + zoomToFit: true, + zoomOnRangeAndType: { + range: selection.graphSelections[0]?.codeRef.range, + type: 'path', + }, + } + ) }), offsetPlaneAstMod: fromPromise( async ({ @@ -1880,21 +1887,18 @@ export const modelingMachine = setup({ offsetPlaneResult.pathToNode[1][0]++ } - const updateAstResult = await kclManager.updateAst( + await updateModelingState( offsetPlaneResult.modifiedAst, - true, + EXECUTION_TYPE_REAL, + { + kclManager, + editorManager, + codeManager, + }, { focusPath: [offsetPlaneResult.pathToNode], } ) - - await codeManager.updateEditorWithAstAndWriteToFile( - updateAstResult.newAst - ) - - if (updateAstResult?.selections) { - editorManager.selectRange(updateAstResult?.selections) - } } ), helixAstMod: fromPromise( @@ -1995,6 +1999,7 @@ export const modelingMachine = setup({ }) await updateModelingState( modifiedAst, + EXECUTION_TYPE_REAL, { kclManager, editorManager, @@ -2088,6 +2093,7 @@ export const modelingMachine = setup({ }) await updateModelingState( modifiedAst, + EXECUTION_TYPE_REAL, { kclManager, editorManager, @@ -2126,21 +2132,18 @@ export const modelingMachine = setup({ // Perform the loft const loftSketchesRes = loftSketches(ast, declarators) - const updateAstResult = await kclManager.updateAst( + await updateModelingState( loftSketchesRes.modifiedAst, - true, + EXECUTION_TYPE_REAL, + { + kclManager, + editorManager, + codeManager, + }, { focusPath: [loftSketchesRes.pathToNode], } ) - - await codeManager.updateEditorWithAstAndWriteToFile( - updateAstResult.newAst - ) - - if (updateAstResult?.selections) { - editorManager.selectRange(updateAstResult?.selections) - } } ), shellAstMod: fromPromise( @@ -2306,21 +2309,18 @@ export const modelingMachine = setup({ addResult.pathToNode[1][0]++ } - const updateAstResult = await kclManager.updateAst( + await updateModelingState( addResult.modifiedAst, - true, + EXECUTION_TYPE_REAL, + { + kclManager, + editorManager, + codeManager, + }, { focusPath: [addResult.pathToNode], } ) - - await codeManager.updateEditorWithAstAndWriteToFile( - updateAstResult.newAst - ) - - if (updateAstResult?.selections) { - editorManager.selectRange(updateAstResult?.selections) - } } ), filletAstMod: fromPromise( @@ -2372,15 +2372,11 @@ export const modelingMachine = setup({ node: kclManager.ast, newExpression: value, }) - const updateAstResult = await kclManager.updateAst(newAst, true) - - await codeManager.updateEditorWithAstAndWriteToFile( - updateAstResult.newAst - ) - - if (updateAstResult?.selections) { - editorManager.selectRange(updateAstResult?.selections) - } + await updateModelingState(newAst, EXECUTION_TYPE_REAL, { + kclManager, + editorManager, + codeManager, + }) } ), 'actor.parameter.edit': fromPromise( @@ -2409,7 +2405,7 @@ export const modelingMachine = setup({ // Mutate the variable's value variableNode.node.init = value.valueAst - await updateModelingState(newAst, { + await updateModelingState(newAst, EXECUTION_TYPE_REAL, { codeManager, editorManager, kclManager, @@ -2575,21 +2571,18 @@ export const modelingMachine = setup({ return err(result) } - const updateAstResult = await kclManager.updateAst( + await updateModelingState( result.modifiedAst, - true, + EXECUTION_TYPE_REAL, + { + kclManager, + editorManager, + codeManager, + }, { focusPath: [result.pathToNode], } ) - - await codeManager.updateEditorWithAstAndWriteToFile( - updateAstResult.newAst - ) - - if (updateAstResult?.selections) { - editorManager.selectRange(updateAstResult?.selections) - } } ), exportFromEngine: fromPromise(