Fix KCL source ranges to know which source file they point to (#4418)

* Add ts_rs feature to work with indexmap

* Add feature for schemars to work with indexmap

* Add module ID to intern module paths

* Update code to use new source range with three fields

* Update generated files

* Update docs

* Fix wasm

* Fix TS code to use new SourceRange

* Fix TS tests to use new SourceRange and moduleId

* Fix formatting

* Fix to filter errors and source ranges to only show the top-level module

* Fix to reuse module IDs

* Fix to disallow empty path for import

* Revert unneeded Self change

* Rename field to be clearer

* Fix parser tests

* Update snapshots

* Change to not serialize module_id of 0

* Update snapshots after adding default module_id

* Move module_id functions to separate module

* Fix tests for console errors

* Proposal: module ID = 0 gets skipped when serializing tokens too (#4422)

Just like in AST nodes.

Also I think "is_top_level" communicates intention better than is_default

---------

Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>
This commit is contained in:
Jonathan Tran
2024-11-07 11:23:41 -05:00
committed by GitHub
parent 30dfc167d3
commit 97705234c6
80 changed files with 1789 additions and 1246 deletions

View File

@ -2,7 +2,7 @@ use anyhow::Result;
use kcl_lib::{
ast::{
modify::modify_ast_for_sketch,
types::{Node, Program},
types::{ModuleId, Node, Program},
},
executor::{ExecutorContext, IdGenerator, KclValue, PlaneType, Sketch, SourceRange},
};
@ -10,10 +10,9 @@ use kittycad_modeling_cmds::{each_cmd as mcmd, length_unit::LengthUnit, shared::
use pretty_assertions::assert_eq;
/// Setup the engine and parse code for an ast.
async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Node<Program>, uuid::Uuid)> {
let tokens = kcl_lib::token::lexer(code)?;
let parser = kcl_lib::parser::Parser::new(tokens);
let program = parser.ast()?;
async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Node<Program>, ModuleId, uuid::Uuid)> {
let module_id = ModuleId::default();
let program = kcl_lib::parser::parse(code, module_id)?;
let ctx = kcl_lib::executor::ExecutorContext::new_with_default_client(Default::default()).await?;
let exec_state = ctx.run(&program, None, IdGenerator::default(), None).await?;
@ -60,7 +59,7 @@ async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Node<Program>
)
.await?;
Ok((ctx, program, sketch_id))
Ok((ctx, program, module_id, sketch_id))
}
#[tokio::test(flavor = "multi_thread")]
@ -76,9 +75,9 @@ async fn kcl_test_modify_sketch_part001() {
name
);
let (ctx, program, sketch_id) = setup(&code, name).await.unwrap();
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
let mut new_program = program.clone();
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
.await
.unwrap();
@ -101,9 +100,9 @@ async fn kcl_test_modify_sketch_part002() {
name
);
let (ctx, program, sketch_id) = setup(&code, name).await.unwrap();
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
let mut new_program = program.clone();
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
.await
.unwrap();
@ -128,9 +127,9 @@ async fn kcl_test_modify_close_sketch() {
name
);
let (ctx, program, sketch_id) = setup(&code, name).await.unwrap();
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
let mut new_program = program.clone();
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
.await
.unwrap();
@ -154,9 +153,9 @@ async fn kcl_test_modify_line_to_close_sketch() {
name
);
let (ctx, program, sketch_id) = setup(&code, name).await.unwrap();
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
let mut new_program = program.clone();
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
.await
.unwrap();
@ -191,14 +190,14 @@ const {} = startSketchOn("XY")
name
);
let (ctx, program, sketch_id) = setup(&code, name).await.unwrap();
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
let mut new_program = program.clone();
let result = modify_ast_for_sketch(&ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id).await;
let result = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id).await;
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
r#"engine: KclErrorDetails { source_ranges: [SourceRange([188, 193])], message: "Sketch part002 is constrained `partial` and cannot be modified" }"#
r#"engine: KclErrorDetails { source_ranges: [SourceRange([188, 193, 0])], message: "Sketch part002 is constrained `partial` and cannot be modified" }"#
);
}
@ -216,9 +215,9 @@ async fn kcl_test_modify_line_should_close_sketch() {
name
);
let (ctx, program, sketch_id) = setup(&code, name).await.unwrap();
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
let mut new_program = program.clone();
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
.await
.unwrap();