Compare commits
	
		
			3 Commits
		
	
	
		
			kcl-57
			...
			kurt-rust-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 194ab7df59 | |||
| b5d461eabd | |||
| a2b6652fd4 | 
| @ -35,17 +35,17 @@ export default defineConfig({ | ||||
|  | ||||
|   /* Configure projects for major browsers */ | ||||
|   projects: [ | ||||
|     { | ||||
|       name: 'Google Chrome', | ||||
|       use: { | ||||
|         ...devices['Desktop Chrome'], | ||||
|         channel: 'chrome', | ||||
|         contextOptions: { | ||||
|           /* Chromium is the only one with these permission types */ | ||||
|           permissions: ['clipboard-write', 'clipboard-read'], | ||||
|         }, | ||||
|       }, // or 'chrome-beta' | ||||
|     }, | ||||
|     // { | ||||
|     //   name: 'Google Chrome', | ||||
|     //   use: { | ||||
|     //     ...devices['Desktop Chrome'], | ||||
|     //     channel: 'chrome', | ||||
|     //     contextOptions: { | ||||
|     //       /* Chromium is the only one with these permission types */ | ||||
|     //       permissions: ['clipboard-write', 'clipboard-read'], | ||||
|     //     }, | ||||
|     //   }, // or 'chrome-beta' | ||||
|     // }, | ||||
|     { | ||||
|       name: 'webkit', | ||||
|       use: { ...devices['Desktop Safari'] }, | ||||
|  | ||||
| @ -11,6 +11,7 @@ export function AstExplorer() { | ||||
|     kclManager.ast, | ||||
|     context.selectionRanges.codeBasedSelections?.[0]?.range | ||||
|   ) | ||||
|   console.log('demo', pathToNode) | ||||
|   const [filterKeys, setFilterKeys] = useState<string[]>(['start', 'end']) | ||||
|  | ||||
|   const _node = getNodeFromPath(kclManager.ast, pathToNode) | ||||
|  | ||||
| @ -1,8 +1,14 @@ | ||||
| import fs from 'node:fs' | ||||
|  | ||||
| import { parse, ProgramMemory, SketchGroup, initPromise } from './wasm' | ||||
| import { enginelessExecutor } from '../lib/testHelpers' | ||||
| import { parse, ProgramMemory, SketchGroup, initPromise, Program } from './wasm' | ||||
| import { | ||||
|   MockEngineCommandManager, | ||||
|   enginelessExecutor, | ||||
| } from '../lib/testHelpers' | ||||
| import { KCLError } from './errors' | ||||
| import { executeAst } from './langHelpers' | ||||
| import { EngineCommandManager } from './std/engineConnection' | ||||
| import { getNodePathFromSourceRange } from './queryAst' | ||||
|  | ||||
| beforeAll(async () => { | ||||
|   await initPromise | ||||
| @ -108,32 +114,6 @@ const newVar = myVar + 1` | ||||
|     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 () => { | ||||
|     // Enable rotations #152 | ||||
|     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 | ||||
|  | ||||
| async function exe( | ||||
|  | ||||
| @ -5,7 +5,6 @@ import { | ||||
|   programMemoryInit, | ||||
|   kclLint, | ||||
| } from 'lang/wasm' | ||||
| import { enginelessExecutor } from 'lib/testHelpers' | ||||
| import { EngineCommandManager } from 'lang/std/engineConnection' | ||||
| import { KCLError } from 'lang/errors' | ||||
| import { Diagnostic } from '@codemirror/lint' | ||||
| @ -65,7 +64,7 @@ export async function executeAst({ | ||||
|       engineCommandManager.startNewSession() | ||||
|     } | ||||
|     const programMemory = await (useFakeExecutor | ||||
|       ? enginelessExecutor(ast, programMemoryOverride || programMemoryInit()) | ||||
|       ? _executor(ast, programMemoryInit(), engineCommandManager, true) | ||||
|       : _executor(ast, programMemoryInit(), engineCommandManager, false)) | ||||
|  | ||||
|     await engineCommandManager.waitForAllCommands() | ||||
|  | ||||
| @ -1809,7 +1809,7 @@ export class EngineCommandManager extends EventTarget { | ||||
|     range: SourceRange | ||||
|     command: EngineCommand | ||||
|     ast: Program | ||||
|     idToRangeMap?: { [key: string]: SourceRange } | ||||
|     idToRangeMap?: { [key: string]: [SourceRange, PathToNode] } | ||||
|   }): Promise<ResolveCommand | void> { | ||||
|     if (this.engineConnection === undefined) { | ||||
|       return Promise.resolve() | ||||
| @ -1878,7 +1878,8 @@ export class EngineCommandManager extends EventTarget { | ||||
|     id: string, | ||||
|     command: Models['ModelingCmd_type'], | ||||
|     ast?: Program, | ||||
|     range?: SourceRange | ||||
|     range?: SourceRange, | ||||
|     _pathToNode?: PathToNode | ||||
|   ): Promise<ResolveCommand | void> { | ||||
|     let resolve: (val: any) => void = () => {} | ||||
|     const promise: Promise<ResolveCommand | void> = new Promise( | ||||
| @ -1899,7 +1900,9 @@ export class EngineCommandManager extends EventTarget { | ||||
|       if (command.type === 'extrude') return command.target | ||||
|       // handle other commands that have a parent here | ||||
|     } | ||||
|     const pathToNode = ast | ||||
|     const pathToNode = _pathToNode | ||||
|       ? _pathToNode | ||||
|       : ast | ||||
|       ? getNodePathFromSourceRange(ast, range || [0, 0]) | ||||
|       : [] | ||||
|     this.artifactMap[id] = { | ||||
| @ -1945,7 +1948,7 @@ export class EngineCommandManager extends EventTarget { | ||||
|   async handlePendingBatchCommand( | ||||
|     id: string, | ||||
|     commands: Models['ModelingCmdReq_type'][], | ||||
|     idToRangeMap?: { [key: string]: SourceRange }, | ||||
|     idToRangeMap?: { [key: string]: [SourceRange, PathToNode] }, | ||||
|     ast?: Program, | ||||
|     range?: SourceRange | ||||
|   ): Promise<ResolveCommand | void> { | ||||
| @ -1978,7 +1981,12 @@ export class EngineCommandManager extends EventTarget { | ||||
|  | ||||
|     Promise.all( | ||||
|       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 | ||||
| @ -1986,9 +1994,16 @@ export class EngineCommandManager extends EventTarget { | ||||
|   async sendModelingCommandFromWasm( | ||||
|     id: string, | ||||
|     rangeStr: string, | ||||
|     pathToNodeStr: string, | ||||
|     commandStr: string, | ||||
|     idToRangeStr: string | ||||
|   ): Promise<string | void> { | ||||
|     console.log( | ||||
|       'pathToNodeStr', | ||||
|       pathToNodeStr, | ||||
|       JSON.parse(commandStr), | ||||
|       JSON.parse(idToRangeStr) | ||||
|     ) | ||||
|     if (this.engineConnection === undefined) { | ||||
|       return Promise.resolve() | ||||
|     } | ||||
| @ -2005,7 +2020,7 @@ export class EngineCommandManager extends EventTarget { | ||||
|       return Promise.reject(new Error('commandStr is undefined')) | ||||
|     } | ||||
|     const range: SourceRange = JSON.parse(rangeStr) | ||||
|     const idToRangeMap: { [key: string]: SourceRange } = | ||||
|     const idToRangeMap: { [key: string]: [SourceRange, PathToNode] } = | ||||
|       JSON.parse(idToRangeStr) | ||||
|  | ||||
|     const command: EngineCommand = JSON.parse(commandStr) | ||||
|  | ||||
| @ -19,7 +19,7 @@ const defaultPlanes: DefaultPlanes = { | ||||
|   negYz: uuidv4(), | ||||
| } | ||||
|  | ||||
| class MockEngineCommandManager { | ||||
| export class MockEngineCommandManager { | ||||
|   // eslint-disable-next-line @typescript-eslint/no-useless-constructor | ||||
|   constructor(mockParams: { | ||||
|     setIsStreamReady: (isReady: boolean) => void | ||||
| @ -37,6 +37,7 @@ class MockEngineCommandManager { | ||||
|     range: SourceRange | ||||
|     command: EngineCommand | ||||
|   }): Promise<any> { | ||||
|     console.log('YOYOYOYOY!!!!!!') | ||||
|     const response: WebSocketResponse = { | ||||
|       success: true, | ||||
|       resp: { | ||||
| @ -51,11 +52,18 @@ class MockEngineCommandManager { | ||||
|   async wasmGetDefaultPlanes(): Promise<string> { | ||||
|     return JSON.stringify(defaultPlanes) | ||||
|   } | ||||
|   sendModelingCommandFromWasm( | ||||
|   yo: any[] = [] | ||||
|   async sendModelingCommandFromWasm( | ||||
|     id: string, | ||||
|     rangeStr: string, | ||||
|     commandStr: string | ||||
|     pathToNodeStr: string, | ||||
|     commandStr: string, | ||||
|     idToRangeStr: string | ||||
|   ): Promise<any> { | ||||
|     console.log('YOYOYOYOYO<') | ||||
|     if (idToRangeStr) { | ||||
|       this.yo.push(idToRangeStr) | ||||
|     } | ||||
|     if (id === undefined) { | ||||
|       return Promise.reject(new Error('id is undefined')) | ||||
|     } | ||||
| @ -71,6 +79,7 @@ class MockEngineCommandManager { | ||||
|     return this.sendModelingCommand({ id, range, command }) | ||||
|   } | ||||
|   sendSceneCommand() {} | ||||
|   clearDefaultPlanes() {} | ||||
| } | ||||
|  | ||||
| export async function enginelessExecutor( | ||||
| @ -88,6 +97,7 @@ export async function enginelessExecutor( | ||||
|   mockEngineCommandManager.startNewSession() | ||||
|   const programMemory = await _executor(ast, pm, mockEngineCommandManager, true) | ||||
|   await mockEngineCommandManager.waitForAllCommands() | ||||
|   console.log('hey', (mockEngineCommandManager as any).yo) | ||||
|   return programMemory | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -456,7 +456,7 @@ fn do_stdlib_inner( | ||||
|     if !errors.is_empty() { | ||||
|         errors.insert(0, Error::new_spanned(&ast.sig, "")); | ||||
|     } | ||||
|  | ||||
|     println!("{}", stream); | ||||
|     Ok((stream, errors)) | ||||
| } | ||||
|  | ||||
| @ -802,6 +802,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr | ||||
|                 .send_modeling_cmd( | ||||
|                     uuid::Uuid::new_v4(), | ||||
|                     crate::executor::SourceRange::default(), | ||||
|                     crate::executor::PathToNode::default(), | ||||
|                     kittycad::types::ModelingCmd::ZoomToFit { | ||||
|                         object_ids: Default::default(), | ||||
|                         padding: 0.1, | ||||
| @ -815,6 +816,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr | ||||
|                 .send_modeling_cmd( | ||||
|                     uuid::Uuid::new_v4(), | ||||
|                     crate::executor::SourceRange::default(), | ||||
|                     crate::executor::PathToNode::default(), | ||||
|                     kittycad::types::ModelingCmd::TakeSnapshot { | ||||
|                         format: kittycad::types::ImageFormat::Png, | ||||
|                     }, | ||||
|  | ||||
| @ -9,7 +9,7 @@ use crate::{ | ||||
|     }, | ||||
|     engine::EngineManager, | ||||
|     errors::{KclError, KclErrorDetails}, | ||||
|     executor::{Point2d, SourceRange}, | ||||
|     executor::{PathToNode, Point2d, SourceRange}, | ||||
| }; | ||||
|  | ||||
| #[derive(Debug)] | ||||
| @ -77,6 +77,7 @@ pub async fn modify_ast_for_sketch( | ||||
|         .send_modeling_cmd( | ||||
|             uuid::Uuid::new_v4(), | ||||
|             SourceRange::default(), | ||||
|             PathToNode::default(), | ||||
|             ModelingCmd::PathGetInfo { path_id: sketch_id }, | ||||
|         ) | ||||
|         .await?; | ||||
| @ -101,6 +102,7 @@ pub async fn modify_ast_for_sketch( | ||||
|             let h = engine.send_modeling_cmd( | ||||
|                 uuid::Uuid::new_v4(), | ||||
|                 SourceRange::default(), | ||||
|                 PathToNode::default(), | ||||
|                 ModelingCmd::CurveGetControlPoints { curve_id: *command_id }, | ||||
|             ); | ||||
|  | ||||
|  | ||||
| @ -1307,6 +1307,7 @@ impl CallExpression { | ||||
|         for arg in &self.arguments { | ||||
|             let metadata = Metadata { | ||||
|                 source_range: SourceRange([arg.start(), arg.end()]), | ||||
|                 path_to_node: Some(memory.path_to_node.clone()), | ||||
|             }; | ||||
|             let result = ctx | ||||
|                 .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()), | ||||
|             meta: vec![Metadata { | ||||
|                 source_range: literal.into(), | ||||
|                 path_to_node: None, | ||||
|             }], | ||||
|         }) | ||||
|     } | ||||
| @ -1883,6 +1885,7 @@ impl From<&Box<Literal>> for MemoryItem { | ||||
|             value: JValue::from(literal.value.clone()), | ||||
|             meta: vec![Metadata { | ||||
|                 source_range: literal.into(), | ||||
|                 path_to_node: None, | ||||
|             }], | ||||
|         }) | ||||
|     } | ||||
| @ -1979,6 +1982,7 @@ impl From<&TagDeclarator> for TagIdentifier { | ||||
|             value: tag.name.clone(), | ||||
|             meta: vec![Metadata { | ||||
|                 source_range: tag.into(), | ||||
|                 path_to_node: None, | ||||
|             }], | ||||
|         } | ||||
|     } | ||||
| @ -2050,6 +2054,7 @@ impl TagDeclarator { | ||||
|             value: self.name.clone(), | ||||
|             meta: vec![Metadata { | ||||
|                 source_range: self.into(), | ||||
|                 path_to_node: None, | ||||
|             }], | ||||
|         })); | ||||
|  | ||||
| @ -2270,6 +2275,7 @@ impl ArrayExpression { | ||||
|             value: results.into(), | ||||
|             meta: vec![Metadata { | ||||
|                 source_range: self.into(), | ||||
|                 path_to_node: None, | ||||
|             }], | ||||
|         })) | ||||
|     } | ||||
| @ -2438,6 +2444,7 @@ impl ObjectExpression { | ||||
|             value: object.into(), | ||||
|             meta: vec![Metadata { | ||||
|                 source_range: self.into(), | ||||
|                 path_to_node: None, | ||||
|             }], | ||||
|         })) | ||||
|     } | ||||
| @ -2676,6 +2683,7 @@ impl MemberExpression { | ||||
|                     value: value.clone(), | ||||
|                     meta: vec![Metadata { | ||||
|                         source_range: self.into(), | ||||
|                         path_to_node: None, | ||||
|                     }], | ||||
|                 })) | ||||
|             } else { | ||||
| @ -2733,6 +2741,7 @@ impl MemberExpression { | ||||
|                     value: value.clone(), | ||||
|                     meta: vec![Metadata { | ||||
|                         source_range: self.into(), | ||||
|                         path_to_node: None, | ||||
|                     }], | ||||
|                 })) | ||||
|             } else { | ||||
| @ -2894,6 +2903,7 @@ impl BinaryExpression { | ||||
|                     value, | ||||
|                     meta: vec![Metadata { | ||||
|                         source_range: self.into(), | ||||
|                         path_to_node: None, | ||||
|                     }], | ||||
|                 })); | ||||
|             } | ||||
| @ -2915,6 +2925,7 @@ impl BinaryExpression { | ||||
|             value, | ||||
|             meta: vec![Metadata { | ||||
|                 source_range: self.into(), | ||||
|                 path_to_node: None, | ||||
|             }], | ||||
|         })) | ||||
|     } | ||||
| @ -3101,6 +3112,7 @@ impl UnaryExpression { | ||||
|             value: (-(num)).into(), | ||||
|             meta: vec![Metadata { | ||||
|                 source_range: self.into(), | ||||
|                 path_to_node: None, | ||||
|             }], | ||||
|         })) | ||||
|     } | ||||
| @ -3266,7 +3278,10 @@ impl PipeExpression { | ||||
|         pipe_info: &PipeInfo, | ||||
|         ctx: &ExecutorContext, | ||||
|     ) -> 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. | ||||
| @ -3298,6 +3313,7 @@ async fn execute_pipe_body( | ||||
|     // of its own. | ||||
|     let meta = Metadata { | ||||
|         source_range: SourceRange([first.start(), first.end()]), | ||||
|         path_to_node: Some(memory.path_to_node.clone()), | ||||
|     }; | ||||
|     let output = ctx | ||||
|         .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(); | ||||
|     new_pipe_info.previous_results = Some(output); | ||||
|     // 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 { | ||||
|             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::Identifier(identifier) => memory.get(&identifier.name, identifier.into())?.clone(), | ||||
|             Value::CallExpression(call_expression) => call_expression.execute(&mut _memory, &new_pipe_info, ctx).await?, | ||||
|             Value::Identifier(identifier) => _memory.get(&identifier.name, identifier.into())?.clone(), | ||||
|             _ => { | ||||
|                 // Return an error this should not happen. | ||||
|                 return Err(KclError::Semantic(KclErrorDetails { | ||||
| @ -3324,6 +3343,7 @@ async fn execute_pipe_body( | ||||
|             } | ||||
|         }; | ||||
|         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. | ||||
|     let final_output = new_pipe_info.previous_results.unwrap(); | ||||
|  | ||||
| @ -33,8 +33,8 @@ pub struct EngineConnection { | ||||
|     responses: Arc<DashMap<uuid::Uuid, WebSocketResponse>>, | ||||
|     tcp_read_handle: Arc<TcpReadHandle>, | ||||
|     socket_health: Arc<Mutex<SocketHealth>>, | ||||
|     batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>, | ||||
|     batch_end: Arc<Mutex<HashMap<uuid::Uuid, (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, crate::executor::PathToNode))>>>, | ||||
|  | ||||
|     /// The default planes for the scene. | ||||
|     default_planes: Arc<RwLock<Option<DefaultPlanes>>>, | ||||
| @ -248,15 +248,15 @@ impl EngineConnection { | ||||
|  | ||||
| #[async_trait::async_trait] | ||||
| 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() | ||||
|     } | ||||
|  | ||||
|     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() | ||||
|     } | ||||
|  | ||||
|     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(); | ||||
|             if let Some(planes) = opt { | ||||
| @ -264,15 +264,15 @@ impl EngineManager for EngineConnection { | ||||
|             } | ||||
|         } // 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()); | ||||
|  | ||||
|         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. | ||||
|         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); | ||||
|  | ||||
|         Ok(()) | ||||
| @ -282,8 +282,9 @@ impl EngineManager for EngineConnection { | ||||
|         &self, | ||||
|         id: uuid::Uuid, | ||||
|         source_range: crate::executor::SourceRange, | ||||
|         path_to_node: crate::executor::PathToNode, | ||||
|         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> { | ||||
|         let (tx, rx) = oneshot::channel(); | ||||
|  | ||||
|  | ||||
| @ -13,8 +13,8 @@ use crate::{errors::KclError, executor::DefaultPlanes}; | ||||
|  | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct EngineConnection { | ||||
|     batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>, | ||||
|     batch_end: Arc<Mutex<HashMap<uuid::Uuid, (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, crate::executor::PathToNode))>>>, | ||||
| } | ||||
|  | ||||
| impl EngineConnection { | ||||
| @ -28,19 +28,19 @@ impl EngineConnection { | ||||
|  | ||||
| #[async_trait::async_trait] | ||||
| 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() | ||||
|     } | ||||
|  | ||||
|     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() | ||||
|     } | ||||
|  | ||||
|     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()) | ||||
|     } | ||||
|  | ||||
|     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(()) | ||||
|     } | ||||
|  | ||||
| @ -48,8 +48,9 @@ impl crate::engine::EngineManager for EngineConnection { | ||||
|         &self, | ||||
|         id: uuid::Uuid, | ||||
|         _source_range: crate::executor::SourceRange, | ||||
|         _path_to_node: crate::executor::PathToNode, | ||||
|         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> { | ||||
|         match cmd { | ||||
|             WebSocketRequest::ModelingCmdBatchReq { | ||||
|  | ||||
| @ -24,6 +24,7 @@ extern "C" { | ||||
|         this: &EngineCommandManager, | ||||
|         id: String, | ||||
|         rangeStr: String, | ||||
|         pathToNodeStr: String, | ||||
|         cmdStr: String, | ||||
|         idToRangeStr: String, | ||||
|     ) -> Result<js_sys::Promise, js_sys::Error>; | ||||
| @ -41,8 +42,8 @@ extern "C" { | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct EngineConnection { | ||||
|     manager: Arc<EngineCommandManager>, | ||||
|     batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>, | ||||
|     batch_end: Arc<Mutex<HashMap<uuid::Uuid, (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, crate::executor::PathToNode))>>>, | ||||
| } | ||||
|  | ||||
| // Safety: WebAssembly will only ever run in a single-threaded context. | ||||
| @ -61,15 +62,15 @@ impl EngineConnection { | ||||
|  | ||||
| #[async_trait::async_trait] | ||||
| 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() | ||||
|     } | ||||
|  | ||||
|     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() | ||||
|     } | ||||
|  | ||||
|     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. | ||||
|         let promise = self.manager.get_default_planes().map_err(|e| { | ||||
|             KclError::Engine(KclErrorDetails { | ||||
| @ -107,7 +108,7 @@ impl crate::engine::EngineManager for EngineConnection { | ||||
|         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| { | ||||
|             KclError::Engine(KclErrorDetails { | ||||
|                 message: e.to_string().into(), | ||||
| @ -137,8 +138,10 @@ impl crate::engine::EngineManager for EngineConnection { | ||||
|         &self, | ||||
|         id: uuid::Uuid, | ||||
|         source_range: crate::executor::SourceRange, | ||||
|         // path_to_node: Vec<(String, String)>, | ||||
|         path_to_node: crate::executor::PathToNode, | ||||
|         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> { | ||||
|         let source_range_str = serde_json::to_string(&source_range).map_err(|e| { | ||||
|             KclError::Engine(KclErrorDetails { | ||||
| @ -146,6 +149,12 @@ impl crate::engine::EngineManager for EngineConnection { | ||||
|                 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| { | ||||
|             KclError::Engine(KclErrorDetails { | ||||
|                 message: format!("Failed to serialize modeling command: {:?}", e), | ||||
| @ -161,7 +170,7 @@ impl crate::engine::EngineManager for EngineConnection { | ||||
|  | ||||
|         let promise = self | ||||
|             .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| { | ||||
|                 KclError::Engine(KclErrorDetails { | ||||
|                     message: e.to_string().into(), | ||||
|  | ||||
| @ -31,17 +31,18 @@ lazy_static::lazy_static! { | ||||
| #[async_trait::async_trait] | ||||
| pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|     /// 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. | ||||
|     fn batch_end( | ||||
|         &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. | ||||
|     async fn default_planes( | ||||
|         &self, | ||||
|         _source_range: crate::executor::SourceRange, | ||||
|         _path_to_node: crate::executor::PathToNode, | ||||
|     ) -> Result<DefaultPlanes, crate::errors::KclError>; | ||||
|  | ||||
|     /// 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( | ||||
|         &self, | ||||
|         source_range: crate::executor::SourceRange, | ||||
|         path_to_node: crate::executor::PathToNode, | ||||
|     ) -> Result<(), crate::errors::KclError>; | ||||
|  | ||||
|     /// Send a modeling command and wait for the response message. | ||||
| @ -56,24 +58,26 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|         &self, | ||||
|         id: uuid::Uuid, | ||||
|         source_range: crate::executor::SourceRange, | ||||
|         path_to_node: crate::executor::PathToNode, | ||||
|         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>; | ||||
|  | ||||
|     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( | ||||
|             uuid::Uuid::new_v4(), | ||||
|             source_range, | ||||
|             path_to_node.clone(), | ||||
|             &kittycad::types::ModelingCmd::SceneClearAll {}, | ||||
|         ) | ||||
|         .await?; | ||||
|  | ||||
|         // Flush the batch queue, so clear is run right away. | ||||
|         // 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. | ||||
|         self.clear_scene_post_hook(source_range).await?; | ||||
|         self.clear_scene_post_hook(source_range, path_to_node).await?; | ||||
|  | ||||
|         Ok(()) | ||||
|     } | ||||
| @ -83,6 +87,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|         &self, | ||||
|         id: uuid::Uuid, | ||||
|         source_range: crate::executor::SourceRange, | ||||
|         path_to_node: crate::executor::PathToNode, | ||||
|         cmd: &kittycad::types::ModelingCmd, | ||||
|     ) -> Result<(), crate::errors::KclError> { | ||||
|         let req = WebSocketRequest::ModelingCmdReq { | ||||
| @ -91,7 +96,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|         }; | ||||
|  | ||||
|         // 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(()) | ||||
|     } | ||||
| @ -103,6 +108,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|         &self, | ||||
|         id: uuid::Uuid, | ||||
|         source_range: crate::executor::SourceRange, | ||||
|         path_to_node: crate::executor::PathToNode, | ||||
|         cmd: &kittycad::types::ModelingCmd, | ||||
|     ) -> Result<(), crate::errors::KclError> { | ||||
|         let req = WebSocketRequest::ModelingCmdReq { | ||||
| @ -111,7 +117,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|         }; | ||||
|  | ||||
|         // 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(()) | ||||
|     } | ||||
|  | ||||
| @ -122,12 +128,13 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|         &self, | ||||
|         id: uuid::Uuid, | ||||
|         source_range: crate::executor::SourceRange, | ||||
|         path_to_node: crate::executor::PathToNode, | ||||
|         cmd: kittycad::types::ModelingCmd, | ||||
|     ) -> 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. | ||||
|         self.flush_batch(false, source_range).await | ||||
|         self.flush_batch(false, source_range, path_to_node).await | ||||
|     } | ||||
|  | ||||
|     /// 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. | ||||
|         batch_end: bool, | ||||
|         source_range: crate::executor::SourceRange, | ||||
|         path_to_node: crate::executor::PathToNode, | ||||
|     ) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> { | ||||
|         let all_requests = if batch_end { | ||||
|             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() { | ||||
|             match req { | ||||
|                 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 { | ||||
|                         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. | ||||
|                 let last_id = requests.last().unwrap().cmd_id; | ||||
|                 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?; | ||||
|                 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 | ||||
|                     .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?; | ||||
|                 self.parse_websocket_response(ws_resp, source_range) | ||||
|                 self.parse_websocket_response(ws_resp, source_range.0) | ||||
|             } | ||||
|             _ => Err(KclError::Engine(KclErrorDetails { | ||||
|                 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( | ||||
|             plane_id, | ||||
|             source_range, | ||||
|             crate::executor::PathToNode::default(), | ||||
|             &ModelingCmd::MakePlane { | ||||
|                 clobber: false, | ||||
|                 origin: default_origin, | ||||
| @ -282,6 +291,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|             self.batch_modeling_cmd( | ||||
|                 uuid::Uuid::new_v4(), | ||||
|                 source_range, | ||||
|                 crate::executor::PathToNode::default(), | ||||
|                 &ModelingCmd::PlaneSetColor { color, plane_id }, | ||||
|             ) | ||||
|             .await?; | ||||
| @ -290,7 +300,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|         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([ | ||||
|             ( | ||||
|                 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. | ||||
|         self.flush_batch(false, source_range).await?; | ||||
|         self.flush_batch(false, source_range, path_to_node).await?; | ||||
|  | ||||
|         Ok(DefaultPlanes { | ||||
|             xy: planes[&PlaneName::Xy], | ||||
| @ -416,7 +426,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|         // The last response we are looking for. | ||||
|         id: uuid::Uuid, | ||||
|         // 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. | ||||
|         responses: HashMap<String, kittycad::types::BatchResponse>, | ||||
|     ) -> 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| { | ||||
|                 KclError::Engine(KclErrorDetails { | ||||
|                     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 { | ||||
|                     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() { | ||||
| @ -468,6 +478,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|         self.batch_modeling_cmd( | ||||
|             uuid::Uuid::new_v4(), | ||||
|             Default::default(), | ||||
|             Default::default(), | ||||
|             &ModelingCmd::ObjectVisible { | ||||
|                 hidden, | ||||
|                 object_id: *GRID_OBJECT_ID, | ||||
| @ -479,6 +490,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|         self.batch_modeling_cmd( | ||||
|             uuid::Uuid::new_v4(), | ||||
|             Default::default(), | ||||
|             Default::default(), | ||||
|             &ModelingCmd::ObjectVisible { | ||||
|                 hidden, | ||||
|                 object_id: *GRID_SCALE_TEXT_OBJECT_ID, | ||||
| @ -486,7 +498,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { | ||||
|         ) | ||||
|         .await?; | ||||
|  | ||||
|         self.flush_batch(false, Default::default()).await?; | ||||
|         self.flush_batch(false, Default::default(), Default::default()).await?; | ||||
|  | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @ -26,6 +26,9 @@ pub struct ProgramMemory { | ||||
|     pub root: HashMap<String, MemoryItem>, | ||||
|     #[serde(rename = "return")] | ||||
|     pub return_: Option<ProgramReturn>, | ||||
|     #[serde(skip)] | ||||
|     pub path_to_node: PathToNode, | ||||
|     // pub path_to_node: Vec<(String, String)>, | ||||
| } | ||||
|  | ||||
| impl ProgramMemory { | ||||
| @ -62,6 +65,8 @@ impl ProgramMemory { | ||||
|                 ), | ||||
|             ]), | ||||
|             return_: None, | ||||
|             // path_to_node: Vec::new(), | ||||
|             path_to_node: PathToNode::new(), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -1004,6 +1009,24 @@ pub enum BodyType { | ||||
| #[ts(export)] | ||||
| 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 { | ||||
|     /// Create a new source range. | ||||
|     pub fn new(start: usize, end: usize) -> Self { | ||||
| @ -1132,11 +1155,16 @@ impl From<Point3d> for kittycad::types::Point3D { | ||||
| pub struct Metadata { | ||||
|     /// The source range. | ||||
|     pub source_range: SourceRange, | ||||
|  | ||||
|     // pathToNode | ||||
|     #[serde(default, skip_serializing_if = "Option::is_none")] | ||||
|     pub path_to_node: Option<PathToNode>, | ||||
| } | ||||
|  | ||||
| impl From<SourceRange> for Metadata { | ||||
|     fn from(source_range: SourceRange) -> Self { | ||||
|         Self { source_range } | ||||
| // Implement From trait for Metadata from a tuple of SourceRange and PathToNode | ||||
| impl From<(SourceRange, Option<PathToNode>)> for Metadata { | ||||
|     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 | ||||
|     /// actually make them. | ||||
|     pub is_mock: bool, | ||||
|     // an array of tuples (string| number, string)[] | ||||
|     // pub path_to_node: Vec<(String, String)>, | ||||
| } | ||||
|  | ||||
| /// The executor settings. | ||||
| @ -1438,6 +1468,7 @@ impl ExecutorContext { | ||||
|             .batch_modeling_cmd( | ||||
|                 uuid::Uuid::new_v4(), | ||||
|                 SourceRange::default(), | ||||
|                 PathToNode::default(), | ||||
|                 &kittycad::types::ModelingCmd::EdgeLinesVisible { | ||||
|                     hidden: !settings.highlight_edges, | ||||
|                 }, | ||||
| @ -1450,6 +1481,7 @@ impl ExecutorContext { | ||||
|             stdlib: Arc::new(StdLib::new()), | ||||
|             settings, | ||||
|             is_mock: false, | ||||
|             // path_to_node: Vec::new(), | ||||
|         }) | ||||
|     } | ||||
|  | ||||
| @ -1499,6 +1531,7 @@ impl ExecutorContext { | ||||
|             .send_modeling_cmd( | ||||
|                 uuid::Uuid::new_v4(), | ||||
|                 SourceRange::default(), | ||||
|                 PathToNode::default(), | ||||
|                 kittycad::types::ModelingCmd::SceneClearAll {}, | ||||
|             ) | ||||
|             .await?; | ||||
| @ -1518,6 +1551,7 @@ impl ExecutorContext { | ||||
|             .batch_modeling_cmd( | ||||
|                 uuid::Uuid::new_v4(), | ||||
|                 SourceRange::default(), | ||||
|                 PathToNode::default(), | ||||
|                 &kittycad::types::ModelingCmd::SetSceneUnits { | ||||
|                     unit: self.settings.units.into(), | ||||
|                 }, | ||||
| @ -1541,9 +1575,11 @@ impl ExecutorContext { | ||||
|         body_type: BodyType, | ||||
|     ) -> Result<ProgramMemory, KclError> { | ||||
|         let pipe_info = PipeInfo::default(); | ||||
|         memory.path_to_node.push(("body".to_string(), "".to_string())); | ||||
|          | ||||
|         // 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 { | ||||
|                 BodyItem::ExpressionStatement(expression_statement) => { | ||||
|                     if let Value::PipeExpression(pipe_expr) = &expression_statement.expression { | ||||
| @ -1554,6 +1590,7 @@ impl ExecutorContext { | ||||
|                         for arg in &call_expr.arguments { | ||||
|                             let metadata = Metadata { | ||||
|                                 source_range: SourceRange([arg.start(), arg.end()]), | ||||
|                                 path_to_node: Some(memory.path_to_node.clone()), | ||||
|                             }; | ||||
|                             let mem_item = self | ||||
|                                 .arg_into_mem_item(arg, memory, &pipe_info, &metadata, StatementKind::Expression) | ||||
| @ -1587,10 +1624,14 @@ impl ExecutorContext { | ||||
|                     } | ||||
|                 } | ||||
|                 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 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 | ||||
|                             .arg_into_mem_item( | ||||
| @ -1602,7 +1643,10 @@ impl ExecutorContext { | ||||
|                             ) | ||||
|                             .await?; | ||||
|                         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 { | ||||
|                     Value::BinaryExpression(bin_expr) => { | ||||
| @ -1650,6 +1694,7 @@ impl ExecutorContext { | ||||
|                     } | ||||
|                 }, | ||||
|             } | ||||
|             // memory.path_to_node.pop(); | ||||
|         } | ||||
|  | ||||
|         if BodyType::Root == body_type { | ||||
| @ -1660,6 +1705,7 @@ impl ExecutorContext { | ||||
|                     // and chamfers where the engine would otherwise eat the ID of the segments. | ||||
|                     true, | ||||
|                     SourceRange([program.end, program.end]), | ||||
|                     memory.path_to_node.clone(), | ||||
|                 ) | ||||
|                 .await?; | ||||
|         } | ||||
| @ -1753,6 +1799,7 @@ impl ExecutorContext { | ||||
|             .send_modeling_cmd( | ||||
|                 uuid::Uuid::new_v4(), | ||||
|                 crate::executor::SourceRange::default(), | ||||
|                 crate::executor::PathToNode::default(), | ||||
|                 kittycad::types::ModelingCmd::ZoomToFit { | ||||
|                     object_ids: Default::default(), | ||||
|                     padding: 0.1, | ||||
| @ -1766,6 +1813,7 @@ impl ExecutorContext { | ||||
|             .send_modeling_cmd( | ||||
|                 uuid::Uuid::new_v4(), | ||||
|                 crate::executor::SourceRange::default(), | ||||
|                 crate::executor::PathToNode::default(), | ||||
|                 kittycad::types::ModelingCmd::TakeSnapshot { | ||||
|                     format: kittycad::types::ImageFormat::Png, | ||||
|                 }, | ||||
| @ -1861,6 +1909,7 @@ mod tests { | ||||
|             stdlib: Arc::new(crate::std::StdLib::new()), | ||||
|             settings: Default::default(), | ||||
|             is_mock: true, | ||||
|             // path_to_node: Vec::new(), | ||||
|         }; | ||||
|         let memory = ctx.run(&program, None).await?; | ||||
|  | ||||
|  | ||||
| @ -41,7 +41,7 @@ use tower_lsp::{ | ||||
|  | ||||
| use crate::{ | ||||
|     ast::types::{Value, VariableKind}, | ||||
|     executor::SourceRange, | ||||
|     executor::{PathToNode, SourceRange}, | ||||
|     lint::checks, | ||||
|     lsp::{backend::Backend as _, util::IntoDiagnostic}, | ||||
|     parser::PIPE_OPERATOR, | ||||
| @ -589,7 +589,7 @@ impl Backend { | ||||
|         } | ||||
|  | ||||
|         // 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 { | ||||
|             Ok(memory) => memory, | ||||
|  | ||||
| @ -9,7 +9,7 @@ use uuid::Uuid; | ||||
|  | ||||
| use crate::{ | ||||
|     errors::{KclError, KclErrorDetails}, | ||||
|     executor::{ExtrudeGroup, FilletOrChamfer, MemoryItem, TagIdentifier, UserVal}, | ||||
|     executor::{ExtrudeGroup, FilletOrChamfer, MemoryItem, TagIdentifier, UserVal, Metadata}, | ||||
|     std::Args, | ||||
| }; | ||||
|  | ||||
| @ -148,7 +148,7 @@ pub async fn get_opposite_edge(args: Args) -> Result<MemoryItem, KclError> { | ||||
|                 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], | ||||
|             }) | ||||
|         })?, | ||||
|         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], | ||||
|             }) | ||||
|         })?, | ||||
|         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::{ | ||||
|     errors::{KclError, KclErrorDetails}, | ||||
|     executor::{ImportedGeometry, MemoryItem}, | ||||
|     executor::{ImportedGeometry, MemoryItem, Metadata}, | ||||
|     fs::FileSystem, | ||||
|     std::Args, | ||||
| }; | ||||
| @ -272,7 +272,7 @@ async fn inner_import( | ||||
|         return Ok(ImportedGeometry { | ||||
|             id: uuid::Uuid::new_v4(), | ||||
|             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 { | ||||
|         id: imported_files.object_id, | ||||
|         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}, | ||||
|     executor::{ | ||||
|         ExecutorContext, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, MemoryItem, Metadata, ProgramMemory, | ||||
|         SketchGroup, SketchGroupSet, SketchSurface, SourceRange, TagIdentifier, | ||||
|         SketchGroup, SketchGroupSet, SketchSurface, SourceRange, PathToNode, TagIdentifier, | ||||
|     }, | ||||
|     std::{kcl_stdlib::KclStdLibFn, sketch::FaceTag}, | ||||
| }; | ||||
| @ -209,6 +209,7 @@ pub enum FunctionKind { | ||||
| pub struct Args { | ||||
|     pub args: Vec<MemoryItem>, | ||||
|     pub source_range: SourceRange, | ||||
|     pub path_to_node: PathToNode, | ||||
|     pub ctx: ExecutorContext, | ||||
|     pub current_program_memory: ProgramMemory, | ||||
| } | ||||
| @ -217,12 +218,15 @@ impl Args { | ||||
|     pub fn new( | ||||
|         args: Vec<MemoryItem>, | ||||
|         source_range: SourceRange, | ||||
|         // path_to_node: PathToNode, | ||||
|         ctx: ExecutorContext, | ||||
|         current_program_memory: ProgramMemory, | ||||
|     ) -> Self { | ||||
|         Self { | ||||
|             args, | ||||
|             source_range, | ||||
|             path_to_node: current_program_memory.path_to_node.clone(), | ||||
|             // path_to_node, | ||||
|             ctx, | ||||
|             current_program_memory, | ||||
|         } | ||||
| @ -234,7 +238,7 @@ impl Args { | ||||
|         id: uuid::Uuid, | ||||
|         cmd: kittycad::types::ModelingCmd, | ||||
|     ) -> 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. | ||||
| @ -245,7 +249,7 @@ impl Args { | ||||
|         id: uuid::Uuid, | ||||
|         cmd: kittycad::types::ModelingCmd, | ||||
|     ) -> 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. | ||||
| @ -254,7 +258,7 @@ impl Args { | ||||
|         id: uuid::Uuid, | ||||
|         cmd: kittycad::types::ModelingCmd, | ||||
|     ) -> 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. | ||||
| @ -303,7 +307,7 @@ impl Args { | ||||
|  | ||||
|         // Run flush. | ||||
|         // 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(()) | ||||
|     } | ||||
| @ -313,6 +317,8 @@ impl Args { | ||||
|             value: j, | ||||
|             meta: vec![Metadata { | ||||
|                 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}, | ||||
|     executor::{ | ||||
|         ExtrudeGroup, ExtrudeGroupSet, Geometries, Geometry, MemoryItem, Point3d, ProgramReturn, SketchGroup, | ||||
|         SketchGroupSet, SourceRange, UserVal, | ||||
|         SketchGroupSet, SourceRange, UserVal, Metadata, | ||||
|     }, | ||||
|     function_param::FunctionParam, | ||||
|     std::{types::Uint, Args}, | ||||
| @ -85,7 +85,7 @@ pub async fn pattern_transform(args: Args) -> Result<MemoryItem, KclError> { | ||||
|         FunctionParam { | ||||
|             inner: transform.func, | ||||
|             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(), | ||||
|             memory: args.current_program_memory.clone(), | ||||
|         }, | ||||
| @ -204,7 +204,7 @@ async fn make_transform<'a>( | ||||
|     // Call the transform fn for this repetition. | ||||
|     let repetition_num = MemoryItem::UserVal(UserVal { | ||||
|         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_return = transform_function.call(transform_fn_args).await?; | ||||
|  | ||||
| @ -9,7 +9,7 @@ use uuid::Uuid; | ||||
|  | ||||
| use crate::{ | ||||
|     errors::{KclError, KclErrorDetails}, | ||||
|     executor::{ExtrudeGroup, MemoryItem, SketchGroup, TagIdentifier, UserVal}, | ||||
|     executor::{ExtrudeGroup, MemoryItem, SketchGroup, TagIdentifier, UserVal, Metadata}, | ||||
|     std::{ | ||||
|         extrude::do_post_extrude, | ||||
|         fillet::{EdgeReference, DEFAULT_TOLERANCE}, | ||||
| @ -300,7 +300,7 @@ pub async fn get_edge(args: Args) -> Result<MemoryItem, KclError> { | ||||
|                 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}, | ||||
|     executor::{ | ||||
|         BasePath, ExtrudeGroup, Face, GeoMeta, MemoryItem, Path, Plane, PlaneType, Point2d, Point3d, SketchGroup, | ||||
|         SketchGroupSet, SketchSurface, SourceRange, TagIdentifier, UserVal, | ||||
|         SketchGroupSet, SketchSurface, SourceRange, TagIdentifier, UserVal, Metadata | ||||
|     }, | ||||
|     std::{ | ||||
|         utils::{ | ||||
| @ -141,7 +141,7 @@ async fn inner_line_to( | ||||
|             tag, | ||||
|             geo_meta: GeoMeta { | ||||
|                 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, | ||||
|             geo_meta: GeoMeta { | ||||
|                 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, | ||||
|             geo_meta: GeoMeta { | ||||
|                 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(), | ||||
|         z_axis: extrude_group.sketch_group.on.z_axis(), | ||||
|         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(); | ||||
|  | ||||
|     // 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 { | ||||
|         PlaneData::XY => default_planes.xy, | ||||
| @ -1223,7 +1223,7 @@ pub(crate) async fn inner_start_profile_at( | ||||
|         tag: tag.clone(), | ||||
|         geo_meta: GeoMeta { | ||||
|             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(), | ||||
|         value: vec![], | ||||
|         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 { | ||||
|             HashMap::from([(tag.name.to_string(), tag.into())]) | ||||
|         } else { | ||||
| @ -1382,7 +1382,7 @@ pub(crate) async fn inner_close( | ||||
|             tag, | ||||
|             geo_meta: GeoMeta { | ||||
|                 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, | ||||
|             geo_meta: GeoMeta { | ||||
|                 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, | ||||
|             geo_meta: GeoMeta { | ||||
|                 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, | ||||
|             geo_meta: GeoMeta { | ||||
|                 id, | ||||
|                 metadata: args.source_range.into(), | ||||
|                 metadata: Metadata::from((args.source_range, Some(args.path_to_node.clone()))), | ||||
|             }, | ||||
|         }, | ||||
|         center: result.center, | ||||
| @ -1818,7 +1818,7 @@ async fn inner_bezier_curve( | ||||
|             tag, | ||||
|             geo_meta: GeoMeta { | ||||
|                 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 | ||||
|         .map_err(|e| format!("{:?}", e))?; | ||||
|     let default_planes = engine | ||||
|         .new_default_planes(Default::default()) | ||||
|         .new_default_planes(Default::default(), Default::default()) | ||||
|         .await | ||||
|         .map_err(String::from)?; | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	