Compare commits
	
		
			3 Commits
		
	
	
		
			andrewvarg
			...
			kurt-rust-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 194ab7df59 | |||
| b5d461eabd | |||
| a2b6652fd4 | 
| @ -35,17 +35,17 @@ export default defineConfig({ | |||||||
|  |  | ||||||
|   /* Configure projects for major browsers */ |   /* Configure projects for major browsers */ | ||||||
|   projects: [ |   projects: [ | ||||||
|     { |     // { | ||||||
|       name: 'Google Chrome', |     //   name: 'Google Chrome', | ||||||
|       use: { |     //   use: { | ||||||
|         ...devices['Desktop Chrome'], |     //     ...devices['Desktop Chrome'], | ||||||
|         channel: 'chrome', |     //     channel: 'chrome', | ||||||
|         contextOptions: { |     //     contextOptions: { | ||||||
|           /* Chromium is the only one with these permission types */ |     //       /* Chromium is the only one with these permission types */ | ||||||
|           permissions: ['clipboard-write', 'clipboard-read'], |     //       permissions: ['clipboard-write', 'clipboard-read'], | ||||||
|         }, |     //     }, | ||||||
|       }, // or 'chrome-beta' |     //   }, // or 'chrome-beta' | ||||||
|     }, |     // }, | ||||||
|     { |     { | ||||||
|       name: 'webkit', |       name: 'webkit', | ||||||
|       use: { ...devices['Desktop Safari'] }, |       use: { ...devices['Desktop Safari'] }, | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ export function AstExplorer() { | |||||||
|     kclManager.ast, |     kclManager.ast, | ||||||
|     context.selectionRanges.codeBasedSelections?.[0]?.range |     context.selectionRanges.codeBasedSelections?.[0]?.range | ||||||
|   ) |   ) | ||||||
|  |   console.log('demo', pathToNode) | ||||||
|   const [filterKeys, setFilterKeys] = useState<string[]>(['start', 'end']) |   const [filterKeys, setFilterKeys] = useState<string[]>(['start', 'end']) | ||||||
|  |  | ||||||
|   const _node = getNodeFromPath(kclManager.ast, pathToNode) |   const _node = getNodeFromPath(kclManager.ast, pathToNode) | ||||||
|  | |||||||
| @ -1,8 +1,14 @@ | |||||||
| import fs from 'node:fs' | import fs from 'node:fs' | ||||||
|  |  | ||||||
| import { parse, ProgramMemory, SketchGroup, initPromise } from './wasm' | import { parse, ProgramMemory, SketchGroup, initPromise, Program } from './wasm' | ||||||
| import { enginelessExecutor } from '../lib/testHelpers' | import { | ||||||
|  |   MockEngineCommandManager, | ||||||
|  |   enginelessExecutor, | ||||||
|  | } from '../lib/testHelpers' | ||||||
| import { KCLError } from './errors' | import { KCLError } from './errors' | ||||||
|  | import { executeAst } from './langHelpers' | ||||||
|  | import { EngineCommandManager } from './std/engineConnection' | ||||||
|  | import { getNodePathFromSourceRange } from './queryAst' | ||||||
|  |  | ||||||
| beforeAll(async () => { | beforeAll(async () => { | ||||||
|   await initPromise |   await initPromise | ||||||
| @ -108,32 +114,6 @@ const newVar = myVar + 1` | |||||||
|     expect(root.myVar.value).toBe(7) |     expect(root.myVar.value).toBe(7) | ||||||
|   }) |   }) | ||||||
|  |  | ||||||
|   // Enable rotations #152 |  | ||||||
|   // it('rotated sketch', async () => { |  | ||||||
|   //   const code = [ |  | ||||||
|   //     'const mySk1 = startSketchAt([0,0])', |  | ||||||
|   //     '  |> lineTo([1,1], %)', |  | ||||||
|   //     '  |> lineTo([0, 1], %, "myPath")', |  | ||||||
|   //     '  |> lineTo([1, 1], %)', |  | ||||||
|   //     'const rotated = rx(90, mySk1)', |  | ||||||
|   //   ].join('\n') |  | ||||||
|   //   const { root } = await exe(code) |  | ||||||
|   //   expect(root.mySk1.value).toHaveLength(3) |  | ||||||
|   //   expect(root?.rotated?.type).toBe('SketchGroup') |  | ||||||
|   //   if ( |  | ||||||
|   //     root?.mySk1?.type !== 'SketchGroup' || |  | ||||||
|   //     root?.rotated?.type !== 'SketchGroup' |  | ||||||
|   //   ) |  | ||||||
|   //     throw new Error('not a sketch group') |  | ||||||
|   //   expect(root.mySk1.rotation).toEqual([0, 0, 0, 1]) |  | ||||||
|   //   expect(root.rotated.rotation.map((a) => a.toFixed(4))).toEqual([ |  | ||||||
|   //     '0.7071', |  | ||||||
|   //     '0.0000', |  | ||||||
|   //     '0.0000', |  | ||||||
|   //     '0.7071', |  | ||||||
|   //   ]) |  | ||||||
|   // }) |  | ||||||
|  |  | ||||||
|   it('execute pipe sketch into call expression', async () => { |   it('execute pipe sketch into call expression', async () => { | ||||||
|     // Enable rotations #152 |     // Enable rotations #152 | ||||||
|     const code = [ |     const code = [ | ||||||
| @ -417,6 +397,75 @@ const theExtrude = startSketchOn('XY') | |||||||
|   }) |   }) | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  | describe('trying pathToNodeStuff', () => { | ||||||
|  |   it('source range should agree with path to node', async () => { | ||||||
|  |     const code = `const sketch001 = startSketchOn('XZ') | ||||||
|  |   |> startProfileAt([7.72, 4.13], %) | ||||||
|  |   |> line([7.11, 3.48], %) | ||||||
|  |   |> line([-3.29, -13.86], %) | ||||||
|  |   |> close(%) | ||||||
|  | const sketch002 = startSketchOn('XY') | ||||||
|  |   |> startProfileAt([8.57, 5.92], %) | ||||||
|  |   |> line([13.28, 4], %)` | ||||||
|  |     const manager = new MockEngineCommandManager({ | ||||||
|  |       setIsStreamReady: () => {}, | ||||||
|  |       setMediaStream: () => {}, | ||||||
|  |     }) as any as EngineCommandManager | ||||||
|  |     const ast = parse(code) as Program | ||||||
|  |     const yo = await executeAst({ | ||||||
|  |       ast, | ||||||
|  |       engineCommandManager: manager, | ||||||
|  |       useFakeExecutor: true, | ||||||
|  |     }) | ||||||
|  |     const sketch001 = yo.programMemory.root.sketch001 as SketchGroup | ||||||
|  |     let derivedPaths: [any, any, any][] = sketch001.value.map( | ||||||
|  |       ({ __geoMeta }) => { | ||||||
|  |         return [ | ||||||
|  |           getNodePathFromSourceRange(ast, __geoMeta.sourceRange).map((a) => [ | ||||||
|  |             String(a[0]), | ||||||
|  |             a[1], | ||||||
|  |           ]), | ||||||
|  |           __geoMeta.pathToNode, | ||||||
|  |           __geoMeta.sourceRange, | ||||||
|  |         ] | ||||||
|  |       } | ||||||
|  |     ) | ||||||
|  |     let snippets = [ | ||||||
|  |       'line([7.11, 3.48], %)', | ||||||
|  |       'line([-3.29, -13.86], %)', | ||||||
|  |       'close(%)', | ||||||
|  |     ] | ||||||
|  |     for (const [ | ||||||
|  |       index, | ||||||
|  |       [sourcePath, wasmPath, range], | ||||||
|  |     ] of derivedPaths.entries()) { | ||||||
|  |       expect(sourcePath).toEqual(wasmPath) | ||||||
|  |       const codeSlice = code.slice(range[0], range[1]) | ||||||
|  |       expect(snippets[index]).toBe(codeSlice) | ||||||
|  |     } | ||||||
|  |     const sketch002 = yo.programMemory.root.sketch002 as SketchGroup | ||||||
|  |     derivedPaths = sketch002.value.map(({ __geoMeta }) => { | ||||||
|  |       return [ | ||||||
|  |         getNodePathFromSourceRange(ast, __geoMeta.sourceRange).map((a) => [ | ||||||
|  |           String(a[0]), | ||||||
|  |           a[1], | ||||||
|  |         ]), | ||||||
|  |         __geoMeta.pathToNode, | ||||||
|  |         __geoMeta.sourceRange, | ||||||
|  |       ] | ||||||
|  |     }) | ||||||
|  |     snippets = ['line([13.28, 4], %)'] | ||||||
|  |     for (const [ | ||||||
|  |       index, | ||||||
|  |       [sourcePath, wasmPath, range], | ||||||
|  |     ] of derivedPaths.entries()) { | ||||||
|  |       expect(sourcePath).toEqual(wasmPath) | ||||||
|  |       const codeSlice = code.slice(range[0], range[1]) | ||||||
|  |       expect(snippets[index]).toBe(codeSlice) | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | }) | ||||||
|  |  | ||||||
| // helpers | // helpers | ||||||
|  |  | ||||||
| async function exe( | async function exe( | ||||||
|  | |||||||
| @ -5,7 +5,6 @@ import { | |||||||
|   programMemoryInit, |   programMemoryInit, | ||||||
|   kclLint, |   kclLint, | ||||||
| } from 'lang/wasm' | } from 'lang/wasm' | ||||||
| import { enginelessExecutor } from 'lib/testHelpers' |  | ||||||
| import { EngineCommandManager } from 'lang/std/engineConnection' | import { EngineCommandManager } from 'lang/std/engineConnection' | ||||||
| import { KCLError } from 'lang/errors' | import { KCLError } from 'lang/errors' | ||||||
| import { Diagnostic } from '@codemirror/lint' | import { Diagnostic } from '@codemirror/lint' | ||||||
| @ -65,7 +64,7 @@ export async function executeAst({ | |||||||
|       engineCommandManager.startNewSession() |       engineCommandManager.startNewSession() | ||||||
|     } |     } | ||||||
|     const programMemory = await (useFakeExecutor |     const programMemory = await (useFakeExecutor | ||||||
|       ? enginelessExecutor(ast, programMemoryOverride || programMemoryInit()) |       ? _executor(ast, programMemoryInit(), engineCommandManager, true) | ||||||
|       : _executor(ast, programMemoryInit(), engineCommandManager, false)) |       : _executor(ast, programMemoryInit(), engineCommandManager, false)) | ||||||
|  |  | ||||||
|     await engineCommandManager.waitForAllCommands() |     await engineCommandManager.waitForAllCommands() | ||||||
|  | |||||||
| @ -1809,7 +1809,7 @@ export class EngineCommandManager extends EventTarget { | |||||||
|     range: SourceRange |     range: SourceRange | ||||||
|     command: EngineCommand |     command: EngineCommand | ||||||
|     ast: Program |     ast: Program | ||||||
|     idToRangeMap?: { [key: string]: SourceRange } |     idToRangeMap?: { [key: string]: [SourceRange, PathToNode] } | ||||||
|   }): Promise<ResolveCommand | void> { |   }): Promise<ResolveCommand | void> { | ||||||
|     if (this.engineConnection === undefined) { |     if (this.engineConnection === undefined) { | ||||||
|       return Promise.resolve() |       return Promise.resolve() | ||||||
| @ -1878,7 +1878,8 @@ export class EngineCommandManager extends EventTarget { | |||||||
|     id: string, |     id: string, | ||||||
|     command: Models['ModelingCmd_type'], |     command: Models['ModelingCmd_type'], | ||||||
|     ast?: Program, |     ast?: Program, | ||||||
|     range?: SourceRange |     range?: SourceRange, | ||||||
|  |     _pathToNode?: PathToNode | ||||||
|   ): Promise<ResolveCommand | void> { |   ): Promise<ResolveCommand | void> { | ||||||
|     let resolve: (val: any) => void = () => {} |     let resolve: (val: any) => void = () => {} | ||||||
|     const promise: Promise<ResolveCommand | void> = new Promise( |     const promise: Promise<ResolveCommand | void> = new Promise( | ||||||
| @ -1899,7 +1900,9 @@ export class EngineCommandManager extends EventTarget { | |||||||
|       if (command.type === 'extrude') return command.target |       if (command.type === 'extrude') return command.target | ||||||
|       // handle other commands that have a parent here |       // handle other commands that have a parent here | ||||||
|     } |     } | ||||||
|     const pathToNode = ast |     const pathToNode = _pathToNode | ||||||
|  |       ? _pathToNode | ||||||
|  |       : ast | ||||||
|       ? getNodePathFromSourceRange(ast, range || [0, 0]) |       ? getNodePathFromSourceRange(ast, range || [0, 0]) | ||||||
|       : [] |       : [] | ||||||
|     this.artifactMap[id] = { |     this.artifactMap[id] = { | ||||||
| @ -1945,7 +1948,7 @@ export class EngineCommandManager extends EventTarget { | |||||||
|   async handlePendingBatchCommand( |   async handlePendingBatchCommand( | ||||||
|     id: string, |     id: string, | ||||||
|     commands: Models['ModelingCmdReq_type'][], |     commands: Models['ModelingCmdReq_type'][], | ||||||
|     idToRangeMap?: { [key: string]: SourceRange }, |     idToRangeMap?: { [key: string]: [SourceRange, PathToNode] }, | ||||||
|     ast?: Program, |     ast?: Program, | ||||||
|     range?: SourceRange |     range?: SourceRange | ||||||
|   ): Promise<ResolveCommand | void> { |   ): Promise<ResolveCommand | void> { | ||||||
| @ -1978,7 +1981,12 @@ export class EngineCommandManager extends EventTarget { | |||||||
|  |  | ||||||
|     Promise.all( |     Promise.all( | ||||||
|       commands.map((c) => |       commands.map((c) => | ||||||
|         this.handlePendingCommand(c.cmd_id, c.cmd, ast, idToRangeMap[c.cmd_id]) |         this.handlePendingCommand( | ||||||
|  |           c.cmd_id, | ||||||
|  |           c.cmd, | ||||||
|  |           ast, | ||||||
|  |           ...idToRangeMap[c.cmd_id] | ||||||
|  |         ) | ||||||
|       ) |       ) | ||||||
|     ) |     ) | ||||||
|     return promise |     return promise | ||||||
| @ -1986,9 +1994,16 @@ export class EngineCommandManager extends EventTarget { | |||||||
|   async sendModelingCommandFromWasm( |   async sendModelingCommandFromWasm( | ||||||
|     id: string, |     id: string, | ||||||
|     rangeStr: string, |     rangeStr: string, | ||||||
|  |     pathToNodeStr: string, | ||||||
|     commandStr: string, |     commandStr: string, | ||||||
|     idToRangeStr: string |     idToRangeStr: string | ||||||
|   ): Promise<string | void> { |   ): Promise<string | void> { | ||||||
|  |     console.log( | ||||||
|  |       'pathToNodeStr', | ||||||
|  |       pathToNodeStr, | ||||||
|  |       JSON.parse(commandStr), | ||||||
|  |       JSON.parse(idToRangeStr) | ||||||
|  |     ) | ||||||
|     if (this.engineConnection === undefined) { |     if (this.engineConnection === undefined) { | ||||||
|       return Promise.resolve() |       return Promise.resolve() | ||||||
|     } |     } | ||||||
| @ -2005,7 +2020,7 @@ export class EngineCommandManager extends EventTarget { | |||||||
|       return Promise.reject(new Error('commandStr is undefined')) |       return Promise.reject(new Error('commandStr is undefined')) | ||||||
|     } |     } | ||||||
|     const range: SourceRange = JSON.parse(rangeStr) |     const range: SourceRange = JSON.parse(rangeStr) | ||||||
|     const idToRangeMap: { [key: string]: SourceRange } = |     const idToRangeMap: { [key: string]: [SourceRange, PathToNode] } = | ||||||
|       JSON.parse(idToRangeStr) |       JSON.parse(idToRangeStr) | ||||||
|  |  | ||||||
|     const command: EngineCommand = JSON.parse(commandStr) |     const command: EngineCommand = JSON.parse(commandStr) | ||||||
|  | |||||||
| @ -19,7 +19,7 @@ const defaultPlanes: DefaultPlanes = { | |||||||
|   negYz: uuidv4(), |   negYz: uuidv4(), | ||||||
| } | } | ||||||
|  |  | ||||||
| class MockEngineCommandManager { | export class MockEngineCommandManager { | ||||||
|   // eslint-disable-next-line @typescript-eslint/no-useless-constructor |   // eslint-disable-next-line @typescript-eslint/no-useless-constructor | ||||||
|   constructor(mockParams: { |   constructor(mockParams: { | ||||||
|     setIsStreamReady: (isReady: boolean) => void |     setIsStreamReady: (isReady: boolean) => void | ||||||
| @ -37,6 +37,7 @@ class MockEngineCommandManager { | |||||||
|     range: SourceRange |     range: SourceRange | ||||||
|     command: EngineCommand |     command: EngineCommand | ||||||
|   }): Promise<any> { |   }): Promise<any> { | ||||||
|  |     console.log('YOYOYOYOY!!!!!!') | ||||||
|     const response: WebSocketResponse = { |     const response: WebSocketResponse = { | ||||||
|       success: true, |       success: true, | ||||||
|       resp: { |       resp: { | ||||||
| @ -51,11 +52,18 @@ class MockEngineCommandManager { | |||||||
|   async wasmGetDefaultPlanes(): Promise<string> { |   async wasmGetDefaultPlanes(): Promise<string> { | ||||||
|     return JSON.stringify(defaultPlanes) |     return JSON.stringify(defaultPlanes) | ||||||
|   } |   } | ||||||
|   sendModelingCommandFromWasm( |   yo: any[] = [] | ||||||
|  |   async sendModelingCommandFromWasm( | ||||||
|     id: string, |     id: string, | ||||||
|     rangeStr: string, |     rangeStr: string, | ||||||
|     commandStr: string |     pathToNodeStr: string, | ||||||
|  |     commandStr: string, | ||||||
|  |     idToRangeStr: string | ||||||
|   ): Promise<any> { |   ): Promise<any> { | ||||||
|  |     console.log('YOYOYOYOYO<') | ||||||
|  |     if (idToRangeStr) { | ||||||
|  |       this.yo.push(idToRangeStr) | ||||||
|  |     } | ||||||
|     if (id === undefined) { |     if (id === undefined) { | ||||||
|       return Promise.reject(new Error('id is undefined')) |       return Promise.reject(new Error('id is undefined')) | ||||||
|     } |     } | ||||||
| @ -71,6 +79,7 @@ class MockEngineCommandManager { | |||||||
|     return this.sendModelingCommand({ id, range, command }) |     return this.sendModelingCommand({ id, range, command }) | ||||||
|   } |   } | ||||||
|   sendSceneCommand() {} |   sendSceneCommand() {} | ||||||
|  |   clearDefaultPlanes() {} | ||||||
| } | } | ||||||
|  |  | ||||||
| export async function enginelessExecutor( | export async function enginelessExecutor( | ||||||
| @ -88,6 +97,7 @@ export async function enginelessExecutor( | |||||||
|   mockEngineCommandManager.startNewSession() |   mockEngineCommandManager.startNewSession() | ||||||
|   const programMemory = await _executor(ast, pm, mockEngineCommandManager, true) |   const programMemory = await _executor(ast, pm, mockEngineCommandManager, true) | ||||||
|   await mockEngineCommandManager.waitForAllCommands() |   await mockEngineCommandManager.waitForAllCommands() | ||||||
|  |   console.log('hey', (mockEngineCommandManager as any).yo) | ||||||
|   return programMemory |   return programMemory | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -456,7 +456,7 @@ fn do_stdlib_inner( | |||||||
|     if !errors.is_empty() { |     if !errors.is_empty() { | ||||||
|         errors.insert(0, Error::new_spanned(&ast.sig, "")); |         errors.insert(0, Error::new_spanned(&ast.sig, "")); | ||||||
|     } |     } | ||||||
|  |     println!("{}", stream); | ||||||
|     Ok((stream, errors)) |     Ok((stream, errors)) | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -802,6 +802,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr | |||||||
|                 .send_modeling_cmd( |                 .send_modeling_cmd( | ||||||
|                     uuid::Uuid::new_v4(), |                     uuid::Uuid::new_v4(), | ||||||
|                     crate::executor::SourceRange::default(), |                     crate::executor::SourceRange::default(), | ||||||
|  |                     crate::executor::PathToNode::default(), | ||||||
|                     kittycad::types::ModelingCmd::ZoomToFit { |                     kittycad::types::ModelingCmd::ZoomToFit { | ||||||
|                         object_ids: Default::default(), |                         object_ids: Default::default(), | ||||||
|                         padding: 0.1, |                         padding: 0.1, | ||||||
| @ -815,6 +816,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr | |||||||
|                 .send_modeling_cmd( |                 .send_modeling_cmd( | ||||||
|                     uuid::Uuid::new_v4(), |                     uuid::Uuid::new_v4(), | ||||||
|                     crate::executor::SourceRange::default(), |                     crate::executor::SourceRange::default(), | ||||||
|  |                     crate::executor::PathToNode::default(), | ||||||
|                     kittycad::types::ModelingCmd::TakeSnapshot { |                     kittycad::types::ModelingCmd::TakeSnapshot { | ||||||
|                         format: kittycad::types::ImageFormat::Png, |                         format: kittycad::types::ImageFormat::Png, | ||||||
|                     }, |                     }, | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ use crate::{ | |||||||
|     }, |     }, | ||||||
|     engine::EngineManager, |     engine::EngineManager, | ||||||
|     errors::{KclError, KclErrorDetails}, |     errors::{KclError, KclErrorDetails}, | ||||||
|     executor::{Point2d, SourceRange}, |     executor::{PathToNode, Point2d, SourceRange}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| @ -77,6 +77,7 @@ pub async fn modify_ast_for_sketch( | |||||||
|         .send_modeling_cmd( |         .send_modeling_cmd( | ||||||
|             uuid::Uuid::new_v4(), |             uuid::Uuid::new_v4(), | ||||||
|             SourceRange::default(), |             SourceRange::default(), | ||||||
|  |             PathToNode::default(), | ||||||
|             ModelingCmd::PathGetInfo { path_id: sketch_id }, |             ModelingCmd::PathGetInfo { path_id: sketch_id }, | ||||||
|         ) |         ) | ||||||
|         .await?; |         .await?; | ||||||
| @ -101,6 +102,7 @@ pub async fn modify_ast_for_sketch( | |||||||
|             let h = engine.send_modeling_cmd( |             let h = engine.send_modeling_cmd( | ||||||
|                 uuid::Uuid::new_v4(), |                 uuid::Uuid::new_v4(), | ||||||
|                 SourceRange::default(), |                 SourceRange::default(), | ||||||
|  |                 PathToNode::default(), | ||||||
|                 ModelingCmd::CurveGetControlPoints { curve_id: *command_id }, |                 ModelingCmd::CurveGetControlPoints { curve_id: *command_id }, | ||||||
|             ); |             ); | ||||||
|  |  | ||||||
|  | |||||||
| @ -1307,6 +1307,7 @@ impl CallExpression { | |||||||
|         for arg in &self.arguments { |         for arg in &self.arguments { | ||||||
|             let metadata = Metadata { |             let metadata = Metadata { | ||||||
|                 source_range: SourceRange([arg.start(), arg.end()]), |                 source_range: SourceRange([arg.start(), arg.end()]), | ||||||
|  |                 path_to_node: Some(memory.path_to_node.clone()), | ||||||
|             }; |             }; | ||||||
|             let result = ctx |             let result = ctx | ||||||
|                 .arg_into_mem_item(arg, memory, pipe_info, &metadata, StatementKind::Expression) |                 .arg_into_mem_item(arg, memory, pipe_info, &metadata, StatementKind::Expression) | ||||||
| @ -1872,6 +1873,7 @@ impl From<Literal> for MemoryItem { | |||||||
|             value: JValue::from(literal.value.clone()), |             value: JValue::from(literal.value.clone()), | ||||||
|             meta: vec![Metadata { |             meta: vec![Metadata { | ||||||
|                 source_range: literal.into(), |                 source_range: literal.into(), | ||||||
|  |                 path_to_node: None, | ||||||
|             }], |             }], | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| @ -1883,6 +1885,7 @@ impl From<&Box<Literal>> for MemoryItem { | |||||||
|             value: JValue::from(literal.value.clone()), |             value: JValue::from(literal.value.clone()), | ||||||
|             meta: vec![Metadata { |             meta: vec![Metadata { | ||||||
|                 source_range: literal.into(), |                 source_range: literal.into(), | ||||||
|  |                 path_to_node: None, | ||||||
|             }], |             }], | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| @ -1979,6 +1982,7 @@ impl From<&TagDeclarator> for TagIdentifier { | |||||||
|             value: tag.name.clone(), |             value: tag.name.clone(), | ||||||
|             meta: vec![Metadata { |             meta: vec![Metadata { | ||||||
|                 source_range: tag.into(), |                 source_range: tag.into(), | ||||||
|  |                 path_to_node: None, | ||||||
|             }], |             }], | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -2050,6 +2054,7 @@ impl TagDeclarator { | |||||||
|             value: self.name.clone(), |             value: self.name.clone(), | ||||||
|             meta: vec![Metadata { |             meta: vec![Metadata { | ||||||
|                 source_range: self.into(), |                 source_range: self.into(), | ||||||
|  |                 path_to_node: None, | ||||||
|             }], |             }], | ||||||
|         })); |         })); | ||||||
|  |  | ||||||
| @ -2270,6 +2275,7 @@ impl ArrayExpression { | |||||||
|             value: results.into(), |             value: results.into(), | ||||||
|             meta: vec![Metadata { |             meta: vec![Metadata { | ||||||
|                 source_range: self.into(), |                 source_range: self.into(), | ||||||
|  |                 path_to_node: None, | ||||||
|             }], |             }], | ||||||
|         })) |         })) | ||||||
|     } |     } | ||||||
| @ -2438,6 +2444,7 @@ impl ObjectExpression { | |||||||
|             value: object.into(), |             value: object.into(), | ||||||
|             meta: vec![Metadata { |             meta: vec![Metadata { | ||||||
|                 source_range: self.into(), |                 source_range: self.into(), | ||||||
|  |                 path_to_node: None, | ||||||
|             }], |             }], | ||||||
|         })) |         })) | ||||||
|     } |     } | ||||||
| @ -2676,6 +2683,7 @@ impl MemberExpression { | |||||||
|                     value: value.clone(), |                     value: value.clone(), | ||||||
|                     meta: vec![Metadata { |                     meta: vec![Metadata { | ||||||
|                         source_range: self.into(), |                         source_range: self.into(), | ||||||
|  |                         path_to_node: None, | ||||||
|                     }], |                     }], | ||||||
|                 })) |                 })) | ||||||
|             } else { |             } else { | ||||||
| @ -2733,6 +2741,7 @@ impl MemberExpression { | |||||||
|                     value: value.clone(), |                     value: value.clone(), | ||||||
|                     meta: vec![Metadata { |                     meta: vec![Metadata { | ||||||
|                         source_range: self.into(), |                         source_range: self.into(), | ||||||
|  |                         path_to_node: None, | ||||||
|                     }], |                     }], | ||||||
|                 })) |                 })) | ||||||
|             } else { |             } else { | ||||||
| @ -2894,6 +2903,7 @@ impl BinaryExpression { | |||||||
|                     value, |                     value, | ||||||
|                     meta: vec![Metadata { |                     meta: vec![Metadata { | ||||||
|                         source_range: self.into(), |                         source_range: self.into(), | ||||||
|  |                         path_to_node: None, | ||||||
|                     }], |                     }], | ||||||
|                 })); |                 })); | ||||||
|             } |             } | ||||||
| @ -2915,6 +2925,7 @@ impl BinaryExpression { | |||||||
|             value, |             value, | ||||||
|             meta: vec![Metadata { |             meta: vec![Metadata { | ||||||
|                 source_range: self.into(), |                 source_range: self.into(), | ||||||
|  |                 path_to_node: None, | ||||||
|             }], |             }], | ||||||
|         })) |         })) | ||||||
|     } |     } | ||||||
| @ -3101,6 +3112,7 @@ impl UnaryExpression { | |||||||
|             value: (-(num)).into(), |             value: (-(num)).into(), | ||||||
|             meta: vec![Metadata { |             meta: vec![Metadata { | ||||||
|                 source_range: self.into(), |                 source_range: self.into(), | ||||||
|  |                 path_to_node: None, | ||||||
|             }], |             }], | ||||||
|         })) |         })) | ||||||
|     } |     } | ||||||
| @ -3266,7 +3278,10 @@ impl PipeExpression { | |||||||
|         pipe_info: &PipeInfo, |         pipe_info: &PipeInfo, | ||||||
|         ctx: &ExecutorContext, |         ctx: &ExecutorContext, | ||||||
|     ) -> Result<MemoryItem, KclError> { |     ) -> Result<MemoryItem, KclError> { | ||||||
|         execute_pipe_body(memory, &self.body, pipe_info, self.into(), ctx).await |         memory.path_to_node.push(("body".to_string(), "PipeExpression".to_string())); | ||||||
|  |         let result = execute_pipe_body(memory, &self.body, pipe_info, self.into(), ctx).await; | ||||||
|  |         // memory.path_to_node.pop(); | ||||||
|  |         result | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Rename all identifiers that have the old name to the new given name. |     /// Rename all identifiers that have the old name to the new given name. | ||||||
| @ -3298,6 +3313,7 @@ async fn execute_pipe_body( | |||||||
|     // of its own. |     // of its own. | ||||||
|     let meta = Metadata { |     let meta = Metadata { | ||||||
|         source_range: SourceRange([first.start(), first.end()]), |         source_range: SourceRange([first.start(), first.end()]), | ||||||
|  |         path_to_node: Some(memory.path_to_node.clone()), | ||||||
|     }; |     }; | ||||||
|     let output = ctx |     let output = ctx | ||||||
|         .arg_into_mem_item(first, memory, pipe_info, &meta, StatementKind::Expression) |         .arg_into_mem_item(first, memory, pipe_info, &meta, StatementKind::Expression) | ||||||
| @ -3308,13 +3324,16 @@ async fn execute_pipe_body( | |||||||
|     let mut new_pipe_info = PipeInfo::new(); |     let mut new_pipe_info = PipeInfo::new(); | ||||||
|     new_pipe_info.previous_results = Some(output); |     new_pipe_info.previous_results = Some(output); | ||||||
|     // Evaluate remaining elements. |     // Evaluate remaining elements. | ||||||
|     for expression in body { |     for (indexYo, expression) in body.enumerate() { | ||||||
|  |         let mut _memory = memory.clone(); | ||||||
|  |         _memory.path_to_node.push(((indexYo+1).to_string(), "index".to_string())); | ||||||
|  |          | ||||||
|         let output = match expression { |         let output = match expression { | ||||||
|             Value::BinaryExpression(binary_expression) => { |             Value::BinaryExpression(binary_expression) => { | ||||||
|                 binary_expression.get_result(memory, &new_pipe_info, ctx).await? |                 binary_expression.get_result(&mut _memory, &new_pipe_info, ctx).await? | ||||||
|             } |             } | ||||||
|             Value::CallExpression(call_expression) => call_expression.execute(memory, &new_pipe_info, ctx).await?, |             Value::CallExpression(call_expression) => call_expression.execute(&mut _memory, &new_pipe_info, ctx).await?, | ||||||
|             Value::Identifier(identifier) => memory.get(&identifier.name, identifier.into())?.clone(), |             Value::Identifier(identifier) => _memory.get(&identifier.name, identifier.into())?.clone(), | ||||||
|             _ => { |             _ => { | ||||||
|                 // Return an error this should not happen. |                 // Return an error this should not happen. | ||||||
|                 return Err(KclError::Semantic(KclErrorDetails { |                 return Err(KclError::Semantic(KclErrorDetails { | ||||||
| @ -3324,6 +3343,7 @@ async fn execute_pipe_body( | |||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         new_pipe_info.previous_results = Some(output); |         new_pipe_info.previous_results = Some(output); | ||||||
|  |         // memory.path_to_node.pop(); | ||||||
|     } |     } | ||||||
|     // Safe to unwrap here, because `newpipe_info` always has something pushed in when the `match first` executes. |     // Safe to unwrap here, because `newpipe_info` always has something pushed in when the `match first` executes. | ||||||
|     let final_output = new_pipe_info.previous_results.unwrap(); |     let final_output = new_pipe_info.previous_results.unwrap(); | ||||||
|  | |||||||
| @ -33,8 +33,8 @@ pub struct EngineConnection { | |||||||
|     responses: Arc<DashMap<uuid::Uuid, WebSocketResponse>>, |     responses: Arc<DashMap<uuid::Uuid, WebSocketResponse>>, | ||||||
|     tcp_read_handle: Arc<TcpReadHandle>, |     tcp_read_handle: Arc<TcpReadHandle>, | ||||||
|     socket_health: Arc<Mutex<SocketHealth>>, |     socket_health: Arc<Mutex<SocketHealth>>, | ||||||
|     batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>, |     batch: Arc<Mutex<Vec<(WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>>, | ||||||
|     batch_end: Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>>, |     batch_end: Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>>, | ||||||
|  |  | ||||||
|     /// The default planes for the scene. |     /// The default planes for the scene. | ||||||
|     default_planes: Arc<RwLock<Option<DefaultPlanes>>>, |     default_planes: Arc<RwLock<Option<DefaultPlanes>>>, | ||||||
| @ -248,15 +248,15 @@ impl EngineConnection { | |||||||
|  |  | ||||||
| #[async_trait::async_trait] | #[async_trait::async_trait] | ||||||
| impl EngineManager for EngineConnection { | impl EngineManager for EngineConnection { | ||||||
|     fn batch(&self) -> Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>> { |     fn batch(&self) -> Arc<Mutex<Vec<(WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>> { | ||||||
|         self.batch.clone() |         self.batch.clone() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn batch_end(&self) -> Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>> { |     fn batch_end(&self) -> Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>> { | ||||||
|         self.batch_end.clone() |         self.batch_end.clone() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn default_planes(&self, source_range: crate::executor::SourceRange) -> Result<DefaultPlanes, KclError> { |     async fn default_planes(&self, source_range: crate::executor::SourceRange, path_to_node: crate::executor::PathToNode) -> Result<DefaultPlanes, KclError> { | ||||||
|         { |         { | ||||||
|             let opt = self.default_planes.read().await.as_ref().cloned(); |             let opt = self.default_planes.read().await.as_ref().cloned(); | ||||||
|             if let Some(planes) = opt { |             if let Some(planes) = opt { | ||||||
| @ -264,15 +264,15 @@ impl EngineManager for EngineConnection { | |||||||
|             } |             } | ||||||
|         } // drop the read lock |         } // drop the read lock | ||||||
|  |  | ||||||
|         let new_planes = self.new_default_planes(source_range).await?; |         let new_planes = self.new_default_planes(source_range, path_to_node).await?; | ||||||
|         *self.default_planes.write().await = Some(new_planes.clone()); |         *self.default_planes.write().await = Some(new_planes.clone()); | ||||||
|  |  | ||||||
|         Ok(new_planes) |         Ok(new_planes) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn clear_scene_post_hook(&self, source_range: crate::executor::SourceRange) -> Result<(), KclError> { |     async fn clear_scene_post_hook(&self, source_range: crate::executor::SourceRange, path_to_node: crate::executor::PathToNode) -> Result<(), KclError> { | ||||||
|         // Remake the default planes, since they would have been removed after the scene was cleared. |         // Remake the default planes, since they would have been removed after the scene was cleared. | ||||||
|         let new_planes = self.new_default_planes(source_range).await?; |         let new_planes = self.new_default_planes(source_range, path_to_node).await?; | ||||||
|         *self.default_planes.write().await = Some(new_planes); |         *self.default_planes.write().await = Some(new_planes); | ||||||
|  |  | ||||||
|         Ok(()) |         Ok(()) | ||||||
| @ -282,8 +282,9 @@ impl EngineManager for EngineConnection { | |||||||
|         &self, |         &self, | ||||||
|         id: uuid::Uuid, |         id: uuid::Uuid, | ||||||
|         source_range: crate::executor::SourceRange, |         source_range: crate::executor::SourceRange, | ||||||
|  |         path_to_node: crate::executor::PathToNode, | ||||||
|         cmd: kittycad::types::WebSocketRequest, |         cmd: kittycad::types::WebSocketRequest, | ||||||
|         _id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>, |         _id_to_source_range: std::collections::HashMap<uuid::Uuid, (crate::executor::SourceRange, crate::executor::PathToNode)>, | ||||||
|     ) -> Result<WebSocketResponse, KclError> { |     ) -> Result<WebSocketResponse, KclError> { | ||||||
|         let (tx, rx) = oneshot::channel(); |         let (tx, rx) = oneshot::channel(); | ||||||
|  |  | ||||||
|  | |||||||
| @ -13,8 +13,8 @@ use crate::{errors::KclError, executor::DefaultPlanes}; | |||||||
|  |  | ||||||
| #[derive(Debug, Clone)] | #[derive(Debug, Clone)] | ||||||
| pub struct EngineConnection { | pub struct EngineConnection { | ||||||
|     batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>, |     batch: Arc<Mutex<Vec<(WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>>, | ||||||
|     batch_end: Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>>, |     batch_end: Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>>, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl EngineConnection { | impl EngineConnection { | ||||||
| @ -28,19 +28,19 @@ impl EngineConnection { | |||||||
|  |  | ||||||
| #[async_trait::async_trait] | #[async_trait::async_trait] | ||||||
| impl crate::engine::EngineManager for EngineConnection { | impl crate::engine::EngineManager for EngineConnection { | ||||||
|     fn batch(&self) -> Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>> { |     fn batch(&self) -> Arc<Mutex<Vec<(WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>> { | ||||||
|         self.batch.clone() |         self.batch.clone() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn batch_end(&self) -> Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>> { |     fn batch_end(&self) -> Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>> { | ||||||
|         self.batch_end.clone() |         self.batch_end.clone() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn default_planes(&self, _source_range: crate::executor::SourceRange) -> Result<DefaultPlanes, KclError> { |     async fn default_planes(&self, _source_range: crate::executor::SourceRange, path_to_node: crate::executor::PathToNode) -> Result<DefaultPlanes, KclError> { | ||||||
|         Ok(DefaultPlanes::default()) |         Ok(DefaultPlanes::default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn clear_scene_post_hook(&self, _source_range: crate::executor::SourceRange) -> Result<(), KclError> { |     async fn clear_scene_post_hook(&self, _source_range: crate::executor::SourceRange, path_to_node: crate::executor::PathToNode) -> Result<(), KclError> { | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -48,8 +48,9 @@ impl crate::engine::EngineManager for EngineConnection { | |||||||
|         &self, |         &self, | ||||||
|         id: uuid::Uuid, |         id: uuid::Uuid, | ||||||
|         _source_range: crate::executor::SourceRange, |         _source_range: crate::executor::SourceRange, | ||||||
|  |         _path_to_node: crate::executor::PathToNode, | ||||||
|         cmd: kittycad::types::WebSocketRequest, |         cmd: kittycad::types::WebSocketRequest, | ||||||
|         _id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>, |         _id_to_source_range: std::collections::HashMap<uuid::Uuid, (crate::executor::SourceRange, crate::executor::PathToNode)>, | ||||||
|     ) -> Result<WebSocketResponse, KclError> { |     ) -> Result<WebSocketResponse, KclError> { | ||||||
|         match cmd { |         match cmd { | ||||||
|             WebSocketRequest::ModelingCmdBatchReq { |             WebSocketRequest::ModelingCmdBatchReq { | ||||||
|  | |||||||
| @ -24,6 +24,7 @@ extern "C" { | |||||||
|         this: &EngineCommandManager, |         this: &EngineCommandManager, | ||||||
|         id: String, |         id: String, | ||||||
|         rangeStr: String, |         rangeStr: String, | ||||||
|  |         pathToNodeStr: String, | ||||||
|         cmdStr: String, |         cmdStr: String, | ||||||
|         idToRangeStr: String, |         idToRangeStr: String, | ||||||
|     ) -> Result<js_sys::Promise, js_sys::Error>; |     ) -> Result<js_sys::Promise, js_sys::Error>; | ||||||
| @ -41,8 +42,8 @@ extern "C" { | |||||||
| #[derive(Debug, Clone)] | #[derive(Debug, Clone)] | ||||||
| pub struct EngineConnection { | pub struct EngineConnection { | ||||||
|     manager: Arc<EngineCommandManager>, |     manager: Arc<EngineCommandManager>, | ||||||
|     batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>, |     batch: Arc<Mutex<Vec<(WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>>, | ||||||
|     batch_end: Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>>, |     batch_end: Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>>, | ||||||
| } | } | ||||||
|  |  | ||||||
| // Safety: WebAssembly will only ever run in a single-threaded context. | // Safety: WebAssembly will only ever run in a single-threaded context. | ||||||
| @ -61,15 +62,15 @@ impl EngineConnection { | |||||||
|  |  | ||||||
| #[async_trait::async_trait] | #[async_trait::async_trait] | ||||||
| impl crate::engine::EngineManager for EngineConnection { | impl crate::engine::EngineManager for EngineConnection { | ||||||
|     fn batch(&self) -> Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>> { |     fn batch(&self) -> Arc<Mutex<Vec<(WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>> { | ||||||
|         self.batch.clone() |         self.batch.clone() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn batch_end(&self) -> Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>> { |     fn batch_end(&self) -> Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>> { | ||||||
|         self.batch_end.clone() |         self.batch_end.clone() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn default_planes(&self, source_range: crate::executor::SourceRange) -> Result<DefaultPlanes, KclError> { |     async fn default_planes(&self, source_range: crate::executor::SourceRange, path_to_node: crate::executor::PathToNode) -> Result<DefaultPlanes, KclError> { | ||||||
|         // Get the default planes. |         // Get the default planes. | ||||||
|         let promise = self.manager.get_default_planes().map_err(|e| { |         let promise = self.manager.get_default_planes().map_err(|e| { | ||||||
|             KclError::Engine(KclErrorDetails { |             KclError::Engine(KclErrorDetails { | ||||||
| @ -107,7 +108,7 @@ impl crate::engine::EngineManager for EngineConnection { | |||||||
|         Ok(default_planes) |         Ok(default_planes) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn clear_scene_post_hook(&self, source_range: crate::executor::SourceRange) -> Result<(), KclError> { |     async fn clear_scene_post_hook(&self, source_range: crate::executor::SourceRange, path_to_node: crate::executor::PathToNode) -> Result<(), KclError> { | ||||||
|         self.manager.clear_default_planes().map_err(|e| { |         self.manager.clear_default_planes().map_err(|e| { | ||||||
|             KclError::Engine(KclErrorDetails { |             KclError::Engine(KclErrorDetails { | ||||||
|                 message: e.to_string().into(), |                 message: e.to_string().into(), | ||||||
| @ -137,8 +138,10 @@ impl crate::engine::EngineManager for EngineConnection { | |||||||
|         &self, |         &self, | ||||||
|         id: uuid::Uuid, |         id: uuid::Uuid, | ||||||
|         source_range: crate::executor::SourceRange, |         source_range: crate::executor::SourceRange, | ||||||
|  |         // path_to_node: Vec<(String, String)>, | ||||||
|  |         path_to_node: crate::executor::PathToNode, | ||||||
|         cmd: kittycad::types::WebSocketRequest, |         cmd: kittycad::types::WebSocketRequest, | ||||||
|         id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>, |         id_to_source_range: std::collections::HashMap<uuid::Uuid, (crate::executor::SourceRange, crate::executor::PathToNode)>, | ||||||
|     ) -> Result<kittycad::types::WebSocketResponse, KclError> { |     ) -> Result<kittycad::types::WebSocketResponse, KclError> { | ||||||
|         let source_range_str = serde_json::to_string(&source_range).map_err(|e| { |         let source_range_str = serde_json::to_string(&source_range).map_err(|e| { | ||||||
|             KclError::Engine(KclErrorDetails { |             KclError::Engine(KclErrorDetails { | ||||||
| @ -146,6 +149,12 @@ impl crate::engine::EngineManager for EngineConnection { | |||||||
|                 source_ranges: vec![source_range], |                 source_ranges: vec![source_range], | ||||||
|             }) |             }) | ||||||
|         })?; |         })?; | ||||||
|  |         let path_to_node_str = serde_json::to_string(&path_to_node).map_err(|e| { | ||||||
|  |             KclError::Engine(KclErrorDetails { | ||||||
|  |                 message: format!("Failed to serialize path to node: {:?}", e), | ||||||
|  |                 source_ranges: vec![source_range], | ||||||
|  |             }) | ||||||
|  |         })?; | ||||||
|         let cmd_str = serde_json::to_string(&cmd).map_err(|e| { |         let cmd_str = serde_json::to_string(&cmd).map_err(|e| { | ||||||
|             KclError::Engine(KclErrorDetails { |             KclError::Engine(KclErrorDetails { | ||||||
|                 message: format!("Failed to serialize modeling command: {:?}", e), |                 message: format!("Failed to serialize modeling command: {:?}", e), | ||||||
| @ -161,7 +170,7 @@ impl crate::engine::EngineManager for EngineConnection { | |||||||
|  |  | ||||||
|         let promise = self |         let promise = self | ||||||
|             .manager |             .manager | ||||||
|             .send_modeling_cmd_from_wasm(id.to_string(), source_range_str, cmd_str, id_to_source_range_str) |             .send_modeling_cmd_from_wasm(id.to_string(), source_range_str, path_to_node_str, cmd_str, id_to_source_range_str) | ||||||
|             .map_err(|e| { |             .map_err(|e| { | ||||||
|                 KclError::Engine(KclErrorDetails { |                 KclError::Engine(KclErrorDetails { | ||||||
|                     message: e.to_string().into(), |                     message: e.to_string().into(), | ||||||
|  | |||||||
| @ -31,17 +31,18 @@ lazy_static::lazy_static! { | |||||||
| #[async_trait::async_trait] | #[async_trait::async_trait] | ||||||
| pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||||
|     /// Get the batch of commands to be sent to the engine. |     /// Get the batch of commands to be sent to the engine. | ||||||
|     fn batch(&self) -> Arc<Mutex<Vec<(kittycad::types::WebSocketRequest, crate::executor::SourceRange)>>>; |     fn batch(&self) -> Arc<Mutex<Vec<(kittycad::types::WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>>; | ||||||
|  |  | ||||||
|     /// Get the batch of end commands to be sent to the engine. |     /// Get the batch of end commands to be sent to the engine. | ||||||
|     fn batch_end( |     fn batch_end( | ||||||
|         &self, |         &self, | ||||||
|     ) -> Arc<Mutex<HashMap<uuid::Uuid, (kittycad::types::WebSocketRequest, crate::executor::SourceRange)>>>; |     ) -> Arc<Mutex<HashMap<uuid::Uuid, (kittycad::types::WebSocketRequest, (crate::executor::SourceRange, crate::executor::PathToNode))>>>; | ||||||
|  |  | ||||||
|     /// Get the default planes. |     /// Get the default planes. | ||||||
|     async fn default_planes( |     async fn default_planes( | ||||||
|         &self, |         &self, | ||||||
|         _source_range: crate::executor::SourceRange, |         _source_range: crate::executor::SourceRange, | ||||||
|  |         _path_to_node: crate::executor::PathToNode, | ||||||
|     ) -> Result<DefaultPlanes, crate::errors::KclError>; |     ) -> Result<DefaultPlanes, crate::errors::KclError>; | ||||||
|  |  | ||||||
|     /// Helpers to be called after clearing a scene. |     /// Helpers to be called after clearing a scene. | ||||||
| @ -49,6 +50,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|     async fn clear_scene_post_hook( |     async fn clear_scene_post_hook( | ||||||
|         &self, |         &self, | ||||||
|         source_range: crate::executor::SourceRange, |         source_range: crate::executor::SourceRange, | ||||||
|  |         path_to_node: crate::executor::PathToNode, | ||||||
|     ) -> Result<(), crate::errors::KclError>; |     ) -> Result<(), crate::errors::KclError>; | ||||||
|  |  | ||||||
|     /// Send a modeling command and wait for the response message. |     /// Send a modeling command and wait for the response message. | ||||||
| @ -56,24 +58,26 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         &self, |         &self, | ||||||
|         id: uuid::Uuid, |         id: uuid::Uuid, | ||||||
|         source_range: crate::executor::SourceRange, |         source_range: crate::executor::SourceRange, | ||||||
|  |         path_to_node: crate::executor::PathToNode, | ||||||
|         cmd: kittycad::types::WebSocketRequest, |         cmd: kittycad::types::WebSocketRequest, | ||||||
|         id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>, |         id_to_source_range: std::collections::HashMap<uuid::Uuid, (crate::executor::SourceRange, crate::executor::PathToNode)>, | ||||||
|     ) -> Result<kittycad::types::WebSocketResponse, crate::errors::KclError>; |     ) -> Result<kittycad::types::WebSocketResponse, crate::errors::KclError>; | ||||||
|  |  | ||||||
|     async fn clear_scene(&self, source_range: crate::executor::SourceRange) -> Result<(), crate::errors::KclError> { |     async fn clear_scene(&self, source_range: crate::executor::SourceRange, path_to_node: crate::executor::PathToNode) -> Result<(), crate::errors::KclError> { | ||||||
|         self.batch_modeling_cmd( |         self.batch_modeling_cmd( | ||||||
|             uuid::Uuid::new_v4(), |             uuid::Uuid::new_v4(), | ||||||
|             source_range, |             source_range, | ||||||
|  |             path_to_node.clone(), | ||||||
|             &kittycad::types::ModelingCmd::SceneClearAll {}, |             &kittycad::types::ModelingCmd::SceneClearAll {}, | ||||||
|         ) |         ) | ||||||
|         .await?; |         .await?; | ||||||
|  |  | ||||||
|         // Flush the batch queue, so clear is run right away. |         // Flush the batch queue, so clear is run right away. | ||||||
|         // Otherwise the hooks below won't work. |         // Otherwise the hooks below won't work. | ||||||
|         self.flush_batch(false, source_range).await?; |         self.flush_batch(false, source_range, path_to_node.clone()).await?; | ||||||
|  |  | ||||||
|         // Do the after clear scene hook. |         // Do the after clear scene hook. | ||||||
|         self.clear_scene_post_hook(source_range).await?; |         self.clear_scene_post_hook(source_range, path_to_node).await?; | ||||||
|  |  | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
| @ -83,6 +87,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         &self, |         &self, | ||||||
|         id: uuid::Uuid, |         id: uuid::Uuid, | ||||||
|         source_range: crate::executor::SourceRange, |         source_range: crate::executor::SourceRange, | ||||||
|  |         path_to_node: crate::executor::PathToNode, | ||||||
|         cmd: &kittycad::types::ModelingCmd, |         cmd: &kittycad::types::ModelingCmd, | ||||||
|     ) -> Result<(), crate::errors::KclError> { |     ) -> Result<(), crate::errors::KclError> { | ||||||
|         let req = WebSocketRequest::ModelingCmdReq { |         let req = WebSocketRequest::ModelingCmdReq { | ||||||
| @ -91,7 +96,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         // Add cmd to the batch. |         // Add cmd to the batch. | ||||||
|         self.batch().lock().unwrap().push((req, source_range)); |         self.batch().lock().unwrap().push((req, (source_range, path_to_node))); | ||||||
|  |  | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
| @ -103,6 +108,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         &self, |         &self, | ||||||
|         id: uuid::Uuid, |         id: uuid::Uuid, | ||||||
|         source_range: crate::executor::SourceRange, |         source_range: crate::executor::SourceRange, | ||||||
|  |         path_to_node: crate::executor::PathToNode, | ||||||
|         cmd: &kittycad::types::ModelingCmd, |         cmd: &kittycad::types::ModelingCmd, | ||||||
|     ) -> Result<(), crate::errors::KclError> { |     ) -> Result<(), crate::errors::KclError> { | ||||||
|         let req = WebSocketRequest::ModelingCmdReq { |         let req = WebSocketRequest::ModelingCmdReq { | ||||||
| @ -111,7 +117,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         // Add cmd to the batch end. |         // Add cmd to the batch end. | ||||||
|         self.batch_end().lock().unwrap().insert(id, (req, source_range)); |         self.batch_end().lock().unwrap().insert(id, (req, (source_range, path_to_node))); | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -122,12 +128,13 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         &self, |         &self, | ||||||
|         id: uuid::Uuid, |         id: uuid::Uuid, | ||||||
|         source_range: crate::executor::SourceRange, |         source_range: crate::executor::SourceRange, | ||||||
|  |         path_to_node: crate::executor::PathToNode, | ||||||
|         cmd: kittycad::types::ModelingCmd, |         cmd: kittycad::types::ModelingCmd, | ||||||
|     ) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> { |     ) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> { | ||||||
|         self.batch_modeling_cmd(id, source_range, &cmd).await?; |         self.batch_modeling_cmd(id, source_range, path_to_node.clone(), &cmd).await?; | ||||||
|  |  | ||||||
|         // Flush the batch queue. |         // Flush the batch queue. | ||||||
|         self.flush_batch(false, source_range).await |         self.flush_batch(false, source_range, path_to_node).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Force flush the batch queue. |     /// Force flush the batch queue. | ||||||
| @ -137,6 +144,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         // We only do this at the very end of the file. |         // We only do this at the very end of the file. | ||||||
|         batch_end: bool, |         batch_end: bool, | ||||||
|         source_range: crate::executor::SourceRange, |         source_range: crate::executor::SourceRange, | ||||||
|  |         path_to_node: crate::executor::PathToNode, | ||||||
|     ) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> { |     ) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> { | ||||||
|         let all_requests = if batch_end { |         let all_requests = if batch_end { | ||||||
|             let mut requests = self.batch().lock().unwrap().clone(); |             let mut requests = self.batch().lock().unwrap().clone(); | ||||||
| @ -183,12 +191,12 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         for (req, range) in all_requests.iter() { |         for (req, range) in all_requests.iter() { | ||||||
|             match req { |             match req { | ||||||
|                 WebSocketRequest::ModelingCmdReq { cmd: _, cmd_id } => { |                 WebSocketRequest::ModelingCmdReq { cmd: _, cmd_id } => { | ||||||
|                     id_to_source_range.insert(*cmd_id, *range); |                     id_to_source_range.insert(*cmd_id, range.clone()); | ||||||
|                 } |                 } | ||||||
|                 _ => { |                 _ => { | ||||||
|                     return Err(KclError::Engine(KclErrorDetails { |                     return Err(KclError::Engine(KclErrorDetails { | ||||||
|                         message: format!("The request is not a modeling command: {:?}", req), |                         message: format!("The request is not a modeling command: {:?}", req), | ||||||
|                         source_ranges: vec![*range], |                         source_ranges: vec![range.clone().0], | ||||||
|                     })); |                     })); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -210,7 +218,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|                 // Get the last command ID. |                 // Get the last command ID. | ||||||
|                 let last_id = requests.last().unwrap().cmd_id; |                 let last_id = requests.last().unwrap().cmd_id; | ||||||
|                 let ws_resp = self |                 let ws_resp = self | ||||||
|                     .inner_send_modeling_cmd(batch_id, source_range, final_req, id_to_source_range.clone()) |                     .inner_send_modeling_cmd(batch_id, source_range, path_to_node, final_req, id_to_source_range.clone()) | ||||||
|                     .await?; |                     .await?; | ||||||
|                 let response = self.parse_websocket_response(ws_resp, source_range)?; |                 let response = self.parse_websocket_response(ws_resp, source_range)?; | ||||||
|  |  | ||||||
| @ -240,9 +248,9 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|                     }) |                     }) | ||||||
|                 })?; |                 })?; | ||||||
|                 let ws_resp = self |                 let ws_resp = self | ||||||
|                     .inner_send_modeling_cmd(cmd_id, source_range, final_req, id_to_source_range) |                     .inner_send_modeling_cmd(cmd_id, source_range.0, path_to_node, final_req, id_to_source_range) | ||||||
|                     .await?; |                     .await?; | ||||||
|                 self.parse_websocket_response(ws_resp, source_range) |                 self.parse_websocket_response(ws_resp, source_range.0) | ||||||
|             } |             } | ||||||
|             _ => Err(KclError::Engine(KclErrorDetails { |             _ => Err(KclError::Engine(KclErrorDetails { | ||||||
|                 message: format!("The final request is not a modeling command: {:?}", final_req), |                 message: format!("The final request is not a modeling command: {:?}", final_req), | ||||||
| @ -266,6 +274,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         self.batch_modeling_cmd( |         self.batch_modeling_cmd( | ||||||
|             plane_id, |             plane_id, | ||||||
|             source_range, |             source_range, | ||||||
|  |             crate::executor::PathToNode::default(), | ||||||
|             &ModelingCmd::MakePlane { |             &ModelingCmd::MakePlane { | ||||||
|                 clobber: false, |                 clobber: false, | ||||||
|                 origin: default_origin, |                 origin: default_origin, | ||||||
| @ -282,6 +291,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|             self.batch_modeling_cmd( |             self.batch_modeling_cmd( | ||||||
|                 uuid::Uuid::new_v4(), |                 uuid::Uuid::new_v4(), | ||||||
|                 source_range, |                 source_range, | ||||||
|  |                 crate::executor::PathToNode::default(), | ||||||
|                 &ModelingCmd::PlaneSetColor { color, plane_id }, |                 &ModelingCmd::PlaneSetColor { color, plane_id }, | ||||||
|             ) |             ) | ||||||
|             .await?; |             .await?; | ||||||
| @ -290,7 +300,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         Ok(plane_id) |         Ok(plane_id) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn new_default_planes(&self, source_range: crate::executor::SourceRange) -> Result<DefaultPlanes, KclError> { |     async fn new_default_planes(&self, source_range: crate::executor::SourceRange, path_to_node: crate::executor::PathToNode) -> Result<DefaultPlanes, KclError> { | ||||||
|         let plane_settings: HashMap<PlaneName, (Point3d, Point3d, Option<Color>)> = HashMap::from([ |         let plane_settings: HashMap<PlaneName, (Point3d, Point3d, Option<Color>)> = HashMap::from([ | ||||||
|             ( |             ( | ||||||
|                 PlaneName::Xy, |                 PlaneName::Xy, | ||||||
| @ -378,7 +388,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Flush the batch queue, so these planes are created right away. |         // Flush the batch queue, so these planes are created right away. | ||||||
|         self.flush_batch(false, source_range).await?; |         self.flush_batch(false, source_range, path_to_node).await?; | ||||||
|  |  | ||||||
|         Ok(DefaultPlanes { |         Ok(DefaultPlanes { | ||||||
|             xy: planes[&PlaneName::Xy], |             xy: planes[&PlaneName::Xy], | ||||||
| @ -416,7 +426,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         // The last response we are looking for. |         // The last response we are looking for. | ||||||
|         id: uuid::Uuid, |         id: uuid::Uuid, | ||||||
|         // The mapping of source ranges to command IDs. |         // The mapping of source ranges to command IDs. | ||||||
|         id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>, |         id_to_source_range: std::collections::HashMap<uuid::Uuid, (crate::executor::SourceRange, crate::executor::PathToNode)>, | ||||||
|         // The response from the engine. |         // The response from the engine. | ||||||
|         responses: HashMap<String, kittycad::types::BatchResponse>, |         responses: HashMap<String, kittycad::types::BatchResponse>, | ||||||
|     ) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> { |     ) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> { | ||||||
| @ -425,7 +435,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|             let cmd_id = uuid::Uuid::parse_str(cmd_id).map_err(|e| { |             let cmd_id = uuid::Uuid::parse_str(cmd_id).map_err(|e| { | ||||||
|                 KclError::Engine(KclErrorDetails { |                 KclError::Engine(KclErrorDetails { | ||||||
|                     message: format!("Failed to parse command ID: {:?}", e), |                     message: format!("Failed to parse command ID: {:?}", e), | ||||||
|                     source_ranges: vec![id_to_source_range[&id]], |                     source_ranges: vec![id_to_source_range[&id].0], | ||||||
|                 }) |                 }) | ||||||
|             })?; |             })?; | ||||||
|  |  | ||||||
| @ -439,7 +449,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|                 })?; |                 })?; | ||||||
|                 return Err(KclError::Engine(KclErrorDetails { |                 return Err(KclError::Engine(KclErrorDetails { | ||||||
|                     message: format!("Modeling command failed: {:?}", errors), |                     message: format!("Modeling command failed: {:?}", errors), | ||||||
|                     source_ranges: vec![source_range], |                     source_ranges: vec![source_range.0], | ||||||
|                 })); |                 })); | ||||||
|             } |             } | ||||||
|             if let Some(response) = resp.response.as_ref() { |             if let Some(response) = resp.response.as_ref() { | ||||||
| @ -468,6 +478,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         self.batch_modeling_cmd( |         self.batch_modeling_cmd( | ||||||
|             uuid::Uuid::new_v4(), |             uuid::Uuid::new_v4(), | ||||||
|             Default::default(), |             Default::default(), | ||||||
|  |             Default::default(), | ||||||
|             &ModelingCmd::ObjectVisible { |             &ModelingCmd::ObjectVisible { | ||||||
|                 hidden, |                 hidden, | ||||||
|                 object_id: *GRID_OBJECT_ID, |                 object_id: *GRID_OBJECT_ID, | ||||||
| @ -479,6 +490,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         self.batch_modeling_cmd( |         self.batch_modeling_cmd( | ||||||
|             uuid::Uuid::new_v4(), |             uuid::Uuid::new_v4(), | ||||||
|             Default::default(), |             Default::default(), | ||||||
|  |             Default::default(), | ||||||
|             &ModelingCmd::ObjectVisible { |             &ModelingCmd::ObjectVisible { | ||||||
|                 hidden, |                 hidden, | ||||||
|                 object_id: *GRID_SCALE_TEXT_OBJECT_ID, |                 object_id: *GRID_SCALE_TEXT_OBJECT_ID, | ||||||
| @ -486,7 +498,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | |||||||
|         ) |         ) | ||||||
|         .await?; |         .await?; | ||||||
|  |  | ||||||
|         self.flush_batch(false, Default::default()).await?; |         self.flush_batch(false, Default::default(), Default::default()).await?; | ||||||
|  |  | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -26,6 +26,9 @@ pub struct ProgramMemory { | |||||||
|     pub root: HashMap<String, MemoryItem>, |     pub root: HashMap<String, MemoryItem>, | ||||||
|     #[serde(rename = "return")] |     #[serde(rename = "return")] | ||||||
|     pub return_: Option<ProgramReturn>, |     pub return_: Option<ProgramReturn>, | ||||||
|  |     #[serde(skip)] | ||||||
|  |     pub path_to_node: PathToNode, | ||||||
|  |     // pub path_to_node: Vec<(String, String)>, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl ProgramMemory { | impl ProgramMemory { | ||||||
| @ -62,6 +65,8 @@ impl ProgramMemory { | |||||||
|                 ), |                 ), | ||||||
|             ]), |             ]), | ||||||
|             return_: None, |             return_: None, | ||||||
|  |             // path_to_node: Vec::new(), | ||||||
|  |             path_to_node: PathToNode::new(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -1004,6 +1009,24 @@ pub enum BodyType { | |||||||
| #[ts(export)] | #[ts(export)] | ||||||
| pub struct SourceRange(#[ts(type = "[number, number]")] pub [usize; 2]); | pub struct SourceRange(#[ts(type = "[number, number]")] pub [usize; 2]); | ||||||
|  |  | ||||||
|  | #[derive(Debug, Default, Deserialize, Serialize, PartialEq, Clone, ts_rs::TS, JsonSchema, Hash, Eq)] | ||||||
|  | #[cfg_attr(feature = "pyo3", pyo3::pyclass)] | ||||||
|  | #[ts(export)] | ||||||
|  | pub struct PathToNode(#[ts(type = "Array<[string, string]>")] pub Vec<(String, String)>); | ||||||
|  |  | ||||||
|  | impl PathToNode { | ||||||
|  |     pub fn new() -> Self { | ||||||
|  |         Self(Vec::new()) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn push(&mut self, path: (String, String)) { | ||||||
|  |         self.0.push(path); | ||||||
|  |     } | ||||||
|  |     pub fn pop(&mut self) -> Option<(String, String)> { | ||||||
|  |         self.0.pop() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| impl SourceRange { | impl SourceRange { | ||||||
|     /// Create a new source range. |     /// Create a new source range. | ||||||
|     pub fn new(start: usize, end: usize) -> Self { |     pub fn new(start: usize, end: usize) -> Self { | ||||||
| @ -1132,11 +1155,16 @@ impl From<Point3d> for kittycad::types::Point3D { | |||||||
| pub struct Metadata { | pub struct Metadata { | ||||||
|     /// The source range. |     /// The source range. | ||||||
|     pub source_range: SourceRange, |     pub source_range: SourceRange, | ||||||
|  |  | ||||||
|  |     // pathToNode | ||||||
|  |     #[serde(default, skip_serializing_if = "Option::is_none")] | ||||||
|  |     pub path_to_node: Option<PathToNode>, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl From<SourceRange> for Metadata { | // Implement From trait for Metadata from a tuple of SourceRange and PathToNode | ||||||
|     fn from(source_range: SourceRange) -> Self { | impl From<(SourceRange, Option<PathToNode>)> for Metadata { | ||||||
|         Self { source_range } |     fn from((source_range, path_to_node): (SourceRange, Option<PathToNode>)) -> Self { | ||||||
|  |         Self { source_range, path_to_node } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -1349,6 +1377,8 @@ pub struct ExecutorContext { | |||||||
|     /// Mock mode is only for the modeling app when they just want to mock engine calls and not |     /// Mock mode is only for the modeling app when they just want to mock engine calls and not | ||||||
|     /// actually make them. |     /// actually make them. | ||||||
|     pub is_mock: bool, |     pub is_mock: bool, | ||||||
|  |     // an array of tuples (string| number, string)[] | ||||||
|  |     // pub path_to_node: Vec<(String, String)>, | ||||||
| } | } | ||||||
|  |  | ||||||
| /// The executor settings. | /// The executor settings. | ||||||
| @ -1438,6 +1468,7 @@ impl ExecutorContext { | |||||||
|             .batch_modeling_cmd( |             .batch_modeling_cmd( | ||||||
|                 uuid::Uuid::new_v4(), |                 uuid::Uuid::new_v4(), | ||||||
|                 SourceRange::default(), |                 SourceRange::default(), | ||||||
|  |                 PathToNode::default(), | ||||||
|                 &kittycad::types::ModelingCmd::EdgeLinesVisible { |                 &kittycad::types::ModelingCmd::EdgeLinesVisible { | ||||||
|                     hidden: !settings.highlight_edges, |                     hidden: !settings.highlight_edges, | ||||||
|                 }, |                 }, | ||||||
| @ -1450,6 +1481,7 @@ impl ExecutorContext { | |||||||
|             stdlib: Arc::new(StdLib::new()), |             stdlib: Arc::new(StdLib::new()), | ||||||
|             settings, |             settings, | ||||||
|             is_mock: false, |             is_mock: false, | ||||||
|  |             // path_to_node: Vec::new(), | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -1499,6 +1531,7 @@ impl ExecutorContext { | |||||||
|             .send_modeling_cmd( |             .send_modeling_cmd( | ||||||
|                 uuid::Uuid::new_v4(), |                 uuid::Uuid::new_v4(), | ||||||
|                 SourceRange::default(), |                 SourceRange::default(), | ||||||
|  |                 PathToNode::default(), | ||||||
|                 kittycad::types::ModelingCmd::SceneClearAll {}, |                 kittycad::types::ModelingCmd::SceneClearAll {}, | ||||||
|             ) |             ) | ||||||
|             .await?; |             .await?; | ||||||
| @ -1518,6 +1551,7 @@ impl ExecutorContext { | |||||||
|             .batch_modeling_cmd( |             .batch_modeling_cmd( | ||||||
|                 uuid::Uuid::new_v4(), |                 uuid::Uuid::new_v4(), | ||||||
|                 SourceRange::default(), |                 SourceRange::default(), | ||||||
|  |                 PathToNode::default(), | ||||||
|                 &kittycad::types::ModelingCmd::SetSceneUnits { |                 &kittycad::types::ModelingCmd::SetSceneUnits { | ||||||
|                     unit: self.settings.units.into(), |                     unit: self.settings.units.into(), | ||||||
|                 }, |                 }, | ||||||
| @ -1541,9 +1575,11 @@ impl ExecutorContext { | |||||||
|         body_type: BodyType, |         body_type: BodyType, | ||||||
|     ) -> Result<ProgramMemory, KclError> { |     ) -> Result<ProgramMemory, KclError> { | ||||||
|         let pipe_info = PipeInfo::default(); |         let pipe_info = PipeInfo::default(); | ||||||
|  |         memory.path_to_node.push(("body".to_string(), "".to_string())); | ||||||
|          |          | ||||||
|         // Iterate over the body of the program. |         // Iterate over the body of the program. | ||||||
|         for statement in &program.body { |         for (index, statement) in program.body.iter().enumerate() { | ||||||
|  |             memory.path_to_node.push((index.to_string(), "index".to_string())); | ||||||
|             match statement { |             match statement { | ||||||
|                 BodyItem::ExpressionStatement(expression_statement) => { |                 BodyItem::ExpressionStatement(expression_statement) => { | ||||||
|                     if let Value::PipeExpression(pipe_expr) = &expression_statement.expression { |                     if let Value::PipeExpression(pipe_expr) = &expression_statement.expression { | ||||||
| @ -1554,6 +1590,7 @@ impl ExecutorContext { | |||||||
|                         for arg in &call_expr.arguments { |                         for arg in &call_expr.arguments { | ||||||
|                             let metadata = Metadata { |                             let metadata = Metadata { | ||||||
|                                 source_range: SourceRange([arg.start(), arg.end()]), |                                 source_range: SourceRange([arg.start(), arg.end()]), | ||||||
|  |                                 path_to_node: Some(memory.path_to_node.clone()), | ||||||
|                             }; |                             }; | ||||||
|                             let mem_item = self |                             let mem_item = self | ||||||
|                                 .arg_into_mem_item(arg, memory, &pipe_info, &metadata, StatementKind::Expression) |                                 .arg_into_mem_item(arg, memory, &pipe_info, &metadata, StatementKind::Expression) | ||||||
| @ -1587,10 +1624,14 @@ impl ExecutorContext { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 BodyItem::VariableDeclaration(variable_declaration) => { |                 BodyItem::VariableDeclaration(variable_declaration) => { | ||||||
|                     for declaration in &variable_declaration.declarations { |                     // let mut _memory = memory.clone(); | ||||||
|  |                     memory.path_to_node.push(("declarations".to_string(), "VariableDeclaration".to_string())); | ||||||
|  |                     for (index, declaration) in variable_declaration.declarations.iter().enumerate() { | ||||||
|  |                         memory.path_to_node.push((index.to_string(), "index".to_string())); | ||||||
|  |                         memory.path_to_node.push(("init".to_string(), "".to_string())); | ||||||
|                         let var_name = declaration.id.name.to_string(); |                         let var_name = declaration.id.name.to_string(); | ||||||
|                         let source_range: SourceRange = declaration.init.clone().into(); |                         let source_range: SourceRange = declaration.init.clone().into(); | ||||||
|                         let metadata = Metadata { source_range }; |                         let metadata = Metadata { source_range, path_to_node: Some(memory.path_to_node.clone())}; | ||||||
|  |  | ||||||
|                         let memory_item = self |                         let memory_item = self | ||||||
|                             .arg_into_mem_item( |                             .arg_into_mem_item( | ||||||
| @ -1602,7 +1643,10 @@ impl ExecutorContext { | |||||||
|                             ) |                             ) | ||||||
|                             .await?; |                             .await?; | ||||||
|                         memory.add(&var_name, memory_item, source_range)?; |                         memory.add(&var_name, memory_item, source_range)?; | ||||||
|  |                         // _memory.path_to_node.pop(); | ||||||
|  |                         // _memory.path_to_node.pop(); | ||||||
|                     } |                     } | ||||||
|  |                     // _memory.path_to_node.pop(); | ||||||
|                 } |                 } | ||||||
|                 BodyItem::ReturnStatement(return_statement) => match &return_statement.argument { |                 BodyItem::ReturnStatement(return_statement) => match &return_statement.argument { | ||||||
|                     Value::BinaryExpression(bin_expr) => { |                     Value::BinaryExpression(bin_expr) => { | ||||||
| @ -1650,6 +1694,7 @@ impl ExecutorContext { | |||||||
|                     } |                     } | ||||||
|                 }, |                 }, | ||||||
|             } |             } | ||||||
|  |             // memory.path_to_node.pop(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if BodyType::Root == body_type { |         if BodyType::Root == body_type { | ||||||
| @ -1660,6 +1705,7 @@ impl ExecutorContext { | |||||||
|                     // and chamfers where the engine would otherwise eat the ID of the segments. |                     // and chamfers where the engine would otherwise eat the ID of the segments. | ||||||
|                     true, |                     true, | ||||||
|                     SourceRange([program.end, program.end]), |                     SourceRange([program.end, program.end]), | ||||||
|  |                     memory.path_to_node.clone(), | ||||||
|                 ) |                 ) | ||||||
|                 .await?; |                 .await?; | ||||||
|         } |         } | ||||||
| @ -1753,6 +1799,7 @@ impl ExecutorContext { | |||||||
|             .send_modeling_cmd( |             .send_modeling_cmd( | ||||||
|                 uuid::Uuid::new_v4(), |                 uuid::Uuid::new_v4(), | ||||||
|                 crate::executor::SourceRange::default(), |                 crate::executor::SourceRange::default(), | ||||||
|  |                 crate::executor::PathToNode::default(), | ||||||
|                 kittycad::types::ModelingCmd::ZoomToFit { |                 kittycad::types::ModelingCmd::ZoomToFit { | ||||||
|                     object_ids: Default::default(), |                     object_ids: Default::default(), | ||||||
|                     padding: 0.1, |                     padding: 0.1, | ||||||
| @ -1766,6 +1813,7 @@ impl ExecutorContext { | |||||||
|             .send_modeling_cmd( |             .send_modeling_cmd( | ||||||
|                 uuid::Uuid::new_v4(), |                 uuid::Uuid::new_v4(), | ||||||
|                 crate::executor::SourceRange::default(), |                 crate::executor::SourceRange::default(), | ||||||
|  |                 crate::executor::PathToNode::default(), | ||||||
|                 kittycad::types::ModelingCmd::TakeSnapshot { |                 kittycad::types::ModelingCmd::TakeSnapshot { | ||||||
|                     format: kittycad::types::ImageFormat::Png, |                     format: kittycad::types::ImageFormat::Png, | ||||||
|                 }, |                 }, | ||||||
| @ -1861,6 +1909,7 @@ mod tests { | |||||||
|             stdlib: Arc::new(crate::std::StdLib::new()), |             stdlib: Arc::new(crate::std::StdLib::new()), | ||||||
|             settings: Default::default(), |             settings: Default::default(), | ||||||
|             is_mock: true, |             is_mock: true, | ||||||
|  |             // path_to_node: Vec::new(), | ||||||
|         }; |         }; | ||||||
|         let memory = ctx.run(&program, None).await?; |         let memory = ctx.run(&program, None).await?; | ||||||
|  |  | ||||||
|  | |||||||
| @ -41,7 +41,7 @@ use tower_lsp::{ | |||||||
|  |  | ||||||
| use crate::{ | use crate::{ | ||||||
|     ast::types::{Value, VariableKind}, |     ast::types::{Value, VariableKind}, | ||||||
|     executor::SourceRange, |     executor::{PathToNode, SourceRange}, | ||||||
|     lint::checks, |     lint::checks, | ||||||
|     lsp::{backend::Backend as _, util::IntoDiagnostic}, |     lsp::{backend::Backend as _, util::IntoDiagnostic}, | ||||||
|     parser::PIPE_OPERATOR, |     parser::PIPE_OPERATOR, | ||||||
| @ -589,7 +589,7 @@ impl Backend { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Clear the scene, before we execute so it's not fugly as shit. |         // Clear the scene, before we execute so it's not fugly as shit. | ||||||
|         executor_ctx.engine.clear_scene(SourceRange::default()).await?; |         executor_ctx.engine.clear_scene(SourceRange::default(), PathToNode::default()).await?; | ||||||
|  |  | ||||||
|         let memory = match executor_ctx.run(ast, None).await { |         let memory = match executor_ctx.run(ast, None).await { | ||||||
|             Ok(memory) => memory, |             Ok(memory) => memory, | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ use uuid::Uuid; | |||||||
|  |  | ||||||
| use crate::{ | use crate::{ | ||||||
|     errors::{KclError, KclErrorDetails}, |     errors::{KclError, KclErrorDetails}, | ||||||
|     executor::{ExtrudeGroup, FilletOrChamfer, MemoryItem, TagIdentifier, UserVal}, |     executor::{ExtrudeGroup, FilletOrChamfer, MemoryItem, TagIdentifier, UserVal, Metadata}, | ||||||
|     std::Args, |     std::Args, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @ -148,7 +148,7 @@ pub async fn get_opposite_edge(args: Args) -> Result<MemoryItem, KclError> { | |||||||
|                 source_ranges: vec![args.source_range], |                 source_ranges: vec![args.source_range], | ||||||
|             }) |             }) | ||||||
|         })?, |         })?, | ||||||
|         meta: vec![args.source_range.into()], |         meta: vec![Metadata::from((args.source_range, Some(args.path_to_node.clone())))], | ||||||
|     })) |     })) | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -238,7 +238,7 @@ pub async fn get_next_adjacent_edge(args: Args) -> Result<MemoryItem, KclError> | |||||||
|                 source_ranges: vec![args.source_range], |                 source_ranges: vec![args.source_range], | ||||||
|             }) |             }) | ||||||
|         })?, |         })?, | ||||||
|         meta: vec![args.source_range.into()], |         meta: vec![Metadata::from((args.source_range, Some(args.path_to_node.clone())))], | ||||||
|     })) |     })) | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -333,7 +333,7 @@ pub async fn get_previous_adjacent_edge(args: Args) -> Result<MemoryItem, KclErr | |||||||
|                 source_ranges: vec![args.source_range], |                 source_ranges: vec![args.source_range], | ||||||
|             }) |             }) | ||||||
|         })?, |         })?, | ||||||
|         meta: vec![args.source_range.into()], |         meta: vec![Metadata::from((args.source_range, Some(args.path_to_node.clone())))], | ||||||
|     })) |     })) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ use schemars::JsonSchema; | |||||||
|  |  | ||||||
| use crate::{ | use crate::{ | ||||||
|     errors::{KclError, KclErrorDetails}, |     errors::{KclError, KclErrorDetails}, | ||||||
|     executor::{ImportedGeometry, MemoryItem}, |     executor::{ImportedGeometry, MemoryItem, Metadata}, | ||||||
|     fs::FileSystem, |     fs::FileSystem, | ||||||
|     std::Args, |     std::Args, | ||||||
| }; | }; | ||||||
| @ -272,7 +272,7 @@ async fn inner_import( | |||||||
|         return Ok(ImportedGeometry { |         return Ok(ImportedGeometry { | ||||||
|             id: uuid::Uuid::new_v4(), |             id: uuid::Uuid::new_v4(), | ||||||
|             value: import_files.iter().map(|f| f.path.to_string()).collect(), |             value: import_files.iter().map(|f| f.path.to_string()).collect(), | ||||||
|             meta: vec![args.source_range.into()], |             meta: vec![Metadata::from((args.source_range, Some(args.path_to_node.clone())))], | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -300,7 +300,7 @@ async fn inner_import( | |||||||
|     Ok(ImportedGeometry { |     Ok(ImportedGeometry { | ||||||
|         id: imported_files.object_id, |         id: imported_files.object_id, | ||||||
|         value: import_files.iter().map(|f| f.path.to_string()).collect(), |         value: import_files.iter().map(|f| f.path.to_string()).collect(), | ||||||
|         meta: vec![args.source_range.into()], |         meta: vec![Metadata::from((args.source_range, Some(args.path_to_node.clone())))], | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -33,7 +33,7 @@ use crate::{ | |||||||
|     errors::{KclError, KclErrorDetails}, |     errors::{KclError, KclErrorDetails}, | ||||||
|     executor::{ |     executor::{ | ||||||
|         ExecutorContext, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, MemoryItem, Metadata, ProgramMemory, |         ExecutorContext, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, MemoryItem, Metadata, ProgramMemory, | ||||||
|         SketchGroup, SketchGroupSet, SketchSurface, SourceRange, TagIdentifier, |         SketchGroup, SketchGroupSet, SketchSurface, SourceRange, PathToNode, TagIdentifier, | ||||||
|     }, |     }, | ||||||
|     std::{kcl_stdlib::KclStdLibFn, sketch::FaceTag}, |     std::{kcl_stdlib::KclStdLibFn, sketch::FaceTag}, | ||||||
| }; | }; | ||||||
| @ -209,6 +209,7 @@ pub enum FunctionKind { | |||||||
| pub struct Args { | pub struct Args { | ||||||
|     pub args: Vec<MemoryItem>, |     pub args: Vec<MemoryItem>, | ||||||
|     pub source_range: SourceRange, |     pub source_range: SourceRange, | ||||||
|  |     pub path_to_node: PathToNode, | ||||||
|     pub ctx: ExecutorContext, |     pub ctx: ExecutorContext, | ||||||
|     pub current_program_memory: ProgramMemory, |     pub current_program_memory: ProgramMemory, | ||||||
| } | } | ||||||
| @ -217,12 +218,15 @@ impl Args { | |||||||
|     pub fn new( |     pub fn new( | ||||||
|         args: Vec<MemoryItem>, |         args: Vec<MemoryItem>, | ||||||
|         source_range: SourceRange, |         source_range: SourceRange, | ||||||
|  |         // path_to_node: PathToNode, | ||||||
|         ctx: ExecutorContext, |         ctx: ExecutorContext, | ||||||
|         current_program_memory: ProgramMemory, |         current_program_memory: ProgramMemory, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         Self { |         Self { | ||||||
|             args, |             args, | ||||||
|             source_range, |             source_range, | ||||||
|  |             path_to_node: current_program_memory.path_to_node.clone(), | ||||||
|  |             // path_to_node, | ||||||
|             ctx, |             ctx, | ||||||
|             current_program_memory, |             current_program_memory, | ||||||
|         } |         } | ||||||
| @ -234,7 +238,7 @@ impl Args { | |||||||
|         id: uuid::Uuid, |         id: uuid::Uuid, | ||||||
|         cmd: kittycad::types::ModelingCmd, |         cmd: kittycad::types::ModelingCmd, | ||||||
|     ) -> Result<(), crate::errors::KclError> { |     ) -> Result<(), crate::errors::KclError> { | ||||||
|         self.ctx.engine.batch_modeling_cmd(id, self.source_range, &cmd).await |         self.ctx.engine.batch_modeling_cmd(id, self.source_range, self.path_to_node.clone(), &cmd).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Add a modeling command to the batch that gets executed at the end of the file. |     // Add a modeling command to the batch that gets executed at the end of the file. | ||||||
| @ -245,7 +249,7 @@ impl Args { | |||||||
|         id: uuid::Uuid, |         id: uuid::Uuid, | ||||||
|         cmd: kittycad::types::ModelingCmd, |         cmd: kittycad::types::ModelingCmd, | ||||||
|     ) -> Result<(), crate::errors::KclError> { |     ) -> Result<(), crate::errors::KclError> { | ||||||
|         self.ctx.engine.batch_end_cmd(id, self.source_range, &cmd).await |         self.ctx.engine.batch_end_cmd(id, self.source_range, self.path_to_node.clone(), &cmd).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Send the modeling cmd and wait for the response. |     /// Send the modeling cmd and wait for the response. | ||||||
| @ -254,7 +258,7 @@ impl Args { | |||||||
|         id: uuid::Uuid, |         id: uuid::Uuid, | ||||||
|         cmd: kittycad::types::ModelingCmd, |         cmd: kittycad::types::ModelingCmd, | ||||||
|     ) -> Result<OkWebSocketResponseData, KclError> { |     ) -> Result<OkWebSocketResponseData, KclError> { | ||||||
|         self.ctx.engine.send_modeling_cmd(id, self.source_range, cmd).await |         self.ctx.engine.send_modeling_cmd(id, self.source_range, self.path_to_node.clone(), cmd).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Flush just the fillets and chamfers for this specific ExtrudeGroupSet. |     /// Flush just the fillets and chamfers for this specific ExtrudeGroupSet. | ||||||
| @ -303,7 +307,7 @@ impl Args { | |||||||
|  |  | ||||||
|         // Run flush. |         // Run flush. | ||||||
|         // Yes, we do need to actually flush the batch here, or references will fail later. |         // Yes, we do need to actually flush the batch here, or references will fail later. | ||||||
|         self.ctx.engine.flush_batch(false, SourceRange::default()).await?; |         self.ctx.engine.flush_batch(false, SourceRange::default(), self.path_to_node.clone()).await?; | ||||||
|  |  | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
| @ -313,6 +317,8 @@ impl Args { | |||||||
|             value: j, |             value: j, | ||||||
|             meta: vec![Metadata { |             meta: vec![Metadata { | ||||||
|                 source_range: self.source_range, |                 source_range: self.source_range, | ||||||
|  |                 // path_to_node: self.path_to_node.clone(), | ||||||
|  |                 path_to_node: None, | ||||||
|             }], |             }], | ||||||
|         })) |         })) | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ use crate::{ | |||||||
|     errors::{KclError, KclErrorDetails}, |     errors::{KclError, KclErrorDetails}, | ||||||
|     executor::{ |     executor::{ | ||||||
|         ExtrudeGroup, ExtrudeGroupSet, Geometries, Geometry, MemoryItem, Point3d, ProgramReturn, SketchGroup, |         ExtrudeGroup, ExtrudeGroupSet, Geometries, Geometry, MemoryItem, Point3d, ProgramReturn, SketchGroup, | ||||||
|         SketchGroupSet, SourceRange, UserVal, |         SketchGroupSet, SourceRange, UserVal, Metadata, | ||||||
|     }, |     }, | ||||||
|     function_param::FunctionParam, |     function_param::FunctionParam, | ||||||
|     std::{types::Uint, Args}, |     std::{types::Uint, Args}, | ||||||
| @ -85,7 +85,7 @@ pub async fn pattern_transform(args: Args) -> Result<MemoryItem, KclError> { | |||||||
|         FunctionParam { |         FunctionParam { | ||||||
|             inner: transform.func, |             inner: transform.func, | ||||||
|             fn_expr: transform.expr, |             fn_expr: transform.expr, | ||||||
|             meta: vec![args.source_range.into()], |             meta: vec![Metadata::from((args.source_range, Some(args.path_to_node.clone())))], | ||||||
|             ctx: args.ctx.clone(), |             ctx: args.ctx.clone(), | ||||||
|             memory: args.current_program_memory.clone(), |             memory: args.current_program_memory.clone(), | ||||||
|         }, |         }, | ||||||
| @ -204,7 +204,7 @@ async fn make_transform<'a>( | |||||||
|     // Call the transform fn for this repetition. |     // Call the transform fn for this repetition. | ||||||
|     let repetition_num = MemoryItem::UserVal(UserVal { |     let repetition_num = MemoryItem::UserVal(UserVal { | ||||||
|         value: serde_json::Value::Number(i.into()), |         value: serde_json::Value::Number(i.into()), | ||||||
|         meta: vec![source_range.into()], |         meta: vec![Metadata::from((source_range, None))], | ||||||
|     }); |     }); | ||||||
|     let transform_fn_args = vec![repetition_num]; |     let transform_fn_args = vec![repetition_num]; | ||||||
|     let transform_fn_return = transform_function.call(transform_fn_args).await?; |     let transform_fn_return = transform_function.call(transform_fn_args).await?; | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ use uuid::Uuid; | |||||||
|  |  | ||||||
| use crate::{ | use crate::{ | ||||||
|     errors::{KclError, KclErrorDetails}, |     errors::{KclError, KclErrorDetails}, | ||||||
|     executor::{ExtrudeGroup, MemoryItem, SketchGroup, TagIdentifier, UserVal}, |     executor::{ExtrudeGroup, MemoryItem, SketchGroup, TagIdentifier, UserVal, Metadata}, | ||||||
|     std::{ |     std::{ | ||||||
|         extrude::do_post_extrude, |         extrude::do_post_extrude, | ||||||
|         fillet::{EdgeReference, DEFAULT_TOLERANCE}, |         fillet::{EdgeReference, DEFAULT_TOLERANCE}, | ||||||
| @ -300,7 +300,7 @@ pub async fn get_edge(args: Args) -> Result<MemoryItem, KclError> { | |||||||
|                 source_ranges: vec![args.source_range], |                 source_ranges: vec![args.source_range], | ||||||
|             }) |             }) | ||||||
|         })?, |         })?, | ||||||
|         meta: vec![args.source_range.into()], |         meta: vec![Metadata::from((args.source_range, Some(args.path_to_node.clone()))),], | ||||||
|     })) |     })) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ use crate::{ | |||||||
|     errors::{KclError, KclErrorDetails}, |     errors::{KclError, KclErrorDetails}, | ||||||
|     executor::{ |     executor::{ | ||||||
|         BasePath, ExtrudeGroup, Face, GeoMeta, MemoryItem, Path, Plane, PlaneType, Point2d, Point3d, SketchGroup, |         BasePath, ExtrudeGroup, Face, GeoMeta, MemoryItem, Path, Plane, PlaneType, Point2d, Point3d, SketchGroup, | ||||||
|         SketchGroupSet, SketchSurface, SourceRange, TagIdentifier, UserVal, |         SketchGroupSet, SketchSurface, SourceRange, TagIdentifier, UserVal, Metadata | ||||||
|     }, |     }, | ||||||
|     std::{ |     std::{ | ||||||
|         utils::{ |         utils::{ | ||||||
| @ -141,7 +141,7 @@ async fn inner_line_to( | |||||||
|             tag, |             tag, | ||||||
|             geo_meta: GeoMeta { |             geo_meta: GeoMeta { | ||||||
|                 id, |                 id, | ||||||
|                 metadata: args.source_range.into(), |                 metadata: Metadata::from((args.source_range, Some(args.path_to_node.clone()))), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| @ -309,7 +309,7 @@ async fn inner_line( | |||||||
|             tag, |             tag, | ||||||
|             geo_meta: GeoMeta { |             geo_meta: GeoMeta { | ||||||
|                 id, |                 id, | ||||||
|                 metadata: args.source_range.into(), |                 metadata: Metadata::from((args.source_range, Some(args.path_to_node.clone()))), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| @ -493,7 +493,7 @@ async fn inner_angled_line( | |||||||
|             tag, |             tag, | ||||||
|             geo_meta: GeoMeta { |             geo_meta: GeoMeta { | ||||||
|                 id, |                 id, | ||||||
|                 metadata: args.source_range.into(), |                 metadata: Metadata::from((args.source_range, Some(args.path_to_node.clone()))), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| @ -1076,7 +1076,7 @@ async fn start_sketch_on_face( | |||||||
|         y_axis: extrude_group.sketch_group.on.y_axis(), |         y_axis: extrude_group.sketch_group.on.y_axis(), | ||||||
|         z_axis: extrude_group.sketch_group.on.z_axis(), |         z_axis: extrude_group.sketch_group.on.z_axis(), | ||||||
|         extrude_group, |         extrude_group, | ||||||
|         meta: vec![args.source_range.into()], |         meta: vec![Metadata::from((args.source_range, Some(args.path_to_node.clone()))),], | ||||||
|     })) |     })) | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -1084,7 +1084,7 @@ async fn start_sketch_on_plane(data: PlaneData, args: Args) -> Result<Box<Plane> | |||||||
|     let mut plane: Plane = data.clone().into(); |     let mut plane: Plane = data.clone().into(); | ||||||
|  |  | ||||||
|     // Get the default planes. |     // Get the default planes. | ||||||
|     let default_planes = args.ctx.engine.default_planes(args.source_range).await?; |     let default_planes = args.ctx.engine.default_planes(args.source_range, args.path_to_node.clone()).await?; | ||||||
|  |  | ||||||
|     plane.id = match data { |     plane.id = match data { | ||||||
|         PlaneData::XY => default_planes.xy, |         PlaneData::XY => default_planes.xy, | ||||||
| @ -1223,7 +1223,7 @@ pub(crate) async fn inner_start_profile_at( | |||||||
|         tag: tag.clone(), |         tag: tag.clone(), | ||||||
|         geo_meta: GeoMeta { |         geo_meta: GeoMeta { | ||||||
|             id, |             id, | ||||||
|             metadata: args.source_range.into(), |             metadata: Metadata::from((args.source_range, Some(args.path_to_node.clone()))), | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @ -1232,7 +1232,7 @@ pub(crate) async fn inner_start_profile_at( | |||||||
|         on: sketch_surface.clone(), |         on: sketch_surface.clone(), | ||||||
|         value: vec![], |         value: vec![], | ||||||
|         start: current_path, |         start: current_path, | ||||||
|         meta: vec![args.source_range.into()], |         meta: vec![Metadata::from((args.source_range, Some(args.path_to_node.clone()))),], | ||||||
|         tags: if let Some(tag) = &tag { |         tags: if let Some(tag) = &tag { | ||||||
|             HashMap::from([(tag.name.to_string(), tag.into())]) |             HashMap::from([(tag.name.to_string(), tag.into())]) | ||||||
|         } else { |         } else { | ||||||
| @ -1382,7 +1382,7 @@ pub(crate) async fn inner_close( | |||||||
|             tag, |             tag, | ||||||
|             geo_meta: GeoMeta { |             geo_meta: GeoMeta { | ||||||
|                 id, |                 id, | ||||||
|                 metadata: args.source_range.into(), |                 metadata: Metadata::from((args.source_range, Some(args.path_to_node.clone()))), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|     }); |     }); | ||||||
| @ -1495,7 +1495,7 @@ pub(crate) async fn inner_arc( | |||||||
|             tag, |             tag, | ||||||
|             geo_meta: GeoMeta { |             geo_meta: GeoMeta { | ||||||
|                 id, |                 id, | ||||||
|                 metadata: args.source_range.into(), |                 metadata: Metadata::from((args.source_range, Some(args.path_to_node.clone()))), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| @ -1605,7 +1605,7 @@ async fn inner_tangential_arc( | |||||||
|             tag, |             tag, | ||||||
|             geo_meta: GeoMeta { |             geo_meta: GeoMeta { | ||||||
|                 id, |                 id, | ||||||
|                 metadata: args.source_range.into(), |                 metadata: Metadata::from((args.source_range, Some(args.path_to_node.clone()))), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| @ -1713,7 +1713,7 @@ async fn inner_tangential_arc_to( | |||||||
|             tag, |             tag, | ||||||
|             geo_meta: GeoMeta { |             geo_meta: GeoMeta { | ||||||
|                 id, |                 id, | ||||||
|                 metadata: args.source_range.into(), |                 metadata: Metadata::from((args.source_range, Some(args.path_to_node.clone()))), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         center: result.center, |         center: result.center, | ||||||
| @ -1818,7 +1818,7 @@ async fn inner_bezier_curve( | |||||||
|             tag, |             tag, | ||||||
|             geo_meta: GeoMeta { |             geo_meta: GeoMeta { | ||||||
|                 id, |                 id, | ||||||
|                 metadata: args.source_range.into(), |                 metadata: Metadata::from((args.source_range, Some(args.path_to_node.clone()))), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
|  | |||||||
| @ -85,7 +85,7 @@ pub async fn make_default_planes( | |||||||
|         .await |         .await | ||||||
|         .map_err(|e| format!("{:?}", e))?; |         .map_err(|e| format!("{:?}", e))?; | ||||||
|     let default_planes = engine |     let default_planes = engine | ||||||
|         .new_default_planes(Default::default()) |         .new_default_planes(Default::default(), Default::default()) | ||||||
|         .await |         .await | ||||||
|         .map_err(String::from)?; |         .map_err(String::from)?; | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	