Bump cargo to 1.88; 2024 edition for kcl-lib (#7618)
This is a big one because the edition changes a fair number of things.
This commit is contained in:
18
flake.lock
generated
18
flake.lock
generated
@ -20,11 +20,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1745998881,
|
"lastModified": 1750865895,
|
||||||
"narHash": "sha256-vonyYAKJSlsX4n9GCsS0pHxR6yCrfqBIuGvANlkwG6U=",
|
"narHash": "sha256-p2dWAQcLVzquy9LxYCZPwyUdugw78Qv3ChvnX755qHA=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "423d2df5b04b4ee7688c3d71396e872afa236a89",
|
"rev": "61c0f513911459945e2cb8bf333dc849f1b976ff",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -36,11 +36,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1745998881,
|
"lastModified": 1750865895,
|
||||||
"narHash": "sha256-vonyYAKJSlsX4n9GCsS0pHxR6yCrfqBIuGvANlkwG6U=",
|
"narHash": "sha256-p2dWAQcLVzquy9LxYCZPwyUdugw78Qv3ChvnX755qHA=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "423d2df5b04b4ee7688c3d71396e872afa236a89",
|
"rev": "61c0f513911459945e2cb8bf333dc849f1b976ff",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -78,11 +78,11 @@
|
|||||||
"nixpkgs": "nixpkgs_3"
|
"nixpkgs": "nixpkgs_3"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1745980514,
|
"lastModified": 1750964660,
|
||||||
"narHash": "sha256-CITAeiuXGjDvT5iZBXr6vKVWQwsUQLJUMFO91bfJFC4=",
|
"narHash": "sha256-YQ6EyFetjH1uy5JhdhRdPe6cuNXlYpMAQePFfZj4W7M=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "7fbdae44b0f40ea432e46fd152ad8be0f8f41ad6",
|
"rev": "04f0fcfb1a50c63529805a798b4b5c21610ff390",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -42,7 +42,7 @@ impl Build {
|
|||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
if !stable {
|
if !stable {
|
||||||
version = format!("{}-nightly", version);
|
version = format!("{version}-nightly");
|
||||||
}
|
}
|
||||||
|
|
||||||
let release_tag = if stable {
|
let release_tag = if stable {
|
||||||
@ -59,10 +59,7 @@ impl Build {
|
|||||||
if stable && !release_tag.contains(&version) {
|
if stable && !release_tag.contains(&version) {
|
||||||
// bail early if the tag doesn't match the version
|
// bail early if the tag doesn't match the version
|
||||||
// TODO: error here when we use the tags with kcl
|
// TODO: error here when we use the tags with kcl
|
||||||
println!(
|
println!("Tag {release_tag} doesn't match version {version}. Did you forget to update Cargo.toml?");
|
||||||
"Tag {} doesn't match version {}. Did you forget to update Cargo.toml?",
|
|
||||||
release_tag, version
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
build_server(sh, &version, &target)?;
|
build_server(sh, &version, &target)?;
|
||||||
|
@ -95,10 +95,10 @@ async fn main() -> Result<()> {
|
|||||||
// Format fields using the provided closure.
|
// Format fields using the provided closure.
|
||||||
// We want to make this very concise otherwise the logs are not able to be read by humans.
|
// We want to make this very concise otherwise the logs are not able to be read by humans.
|
||||||
let format = tracing_subscriber::fmt::format::debug_fn(|writer, field, value| {
|
let format = tracing_subscriber::fmt::format::debug_fn(|writer, field, value| {
|
||||||
if format!("{}", field) == "message" {
|
if format!("{field}") == "message" {
|
||||||
write!(writer, "{}: {:?}", field, value)
|
write!(writer, "{field}: {value:?}")
|
||||||
} else {
|
} else {
|
||||||
write!(writer, "{}", field)
|
write!(writer, "{field}")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Separate each field with a comma.
|
// Separate each field with a comma.
|
||||||
|
@ -87,10 +87,10 @@ async fn main() -> Result<()> {
|
|||||||
// Format fields using the provided closure.
|
// Format fields using the provided closure.
|
||||||
// We want to make this very concise otherwise the logs are not able to be read by humans.
|
// We want to make this very concise otherwise the logs are not able to be read by humans.
|
||||||
let format = tracing_subscriber::fmt::format::debug_fn(|writer, field, value| {
|
let format = tracing_subscriber::fmt::format::debug_fn(|writer, field, value| {
|
||||||
if format!("{}", field) == "message" {
|
if format!("{field}") == "message" {
|
||||||
write!(writer, "{}: {:?}", field, value)
|
write!(writer, "{field}: {value:?}")
|
||||||
} else {
|
} else {
|
||||||
write!(writer, "{}", field)
|
write!(writer, "{field}")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Separate each field with a comma.
|
// Separate each field with a comma.
|
||||||
@ -151,7 +151,7 @@ async fn run_cmd(opts: &Opts) -> Result<()> {
|
|||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Some(sig) = signals.forever().next() {
|
if let Some(sig) = signals.forever().next() {
|
||||||
log::info!("received signal: {:?}", sig);
|
log::info!("received signal: {sig:?}");
|
||||||
log::info!("triggering cleanup...");
|
log::info!("triggering cleanup...");
|
||||||
|
|
||||||
// Exit the process.
|
// Exit the process.
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
description = "KittyCAD Language implementation and tools"
|
description = "KittyCAD Language implementation and tools"
|
||||||
version = "0.2.83"
|
version = "0.2.83"
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
rust-version = "1.83"
|
rust-version = "1.88"
|
||||||
authors = ["Jess Frazelle", "Adam Chalmers", "KittyCAD, Inc"]
|
authors = ["Jess Frazelle", "Adam Chalmers", "KittyCAD, Inc"]
|
||||||
keywords = ["kcl", "KittyCAD", "CAD"]
|
keywords = ["kcl", "KittyCAD", "CAD"]
|
||||||
exclude = ["tests/*", "benches/*", "examples/*", "e2e/*", "bindings/*", "fuzz/*"]
|
exclude = ["tests/*", "benches/*", "examples/*", "e2e/*", "bindings/*", "fuzz/*"]
|
||||||
|
@ -4,7 +4,7 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use criterion::{criterion_group, criterion_main, Criterion};
|
use criterion::{Criterion, criterion_group, criterion_main};
|
||||||
|
|
||||||
const IGNORE_DIRS: [&str; 2] = ["step", "screenshots"];
|
const IGNORE_DIRS: [&str; 2] = ["step", "screenshots"];
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ fn run_benchmarks(c: &mut Criterion) {
|
|||||||
|
|
||||||
// Read the file content (panic on failure)
|
// Read the file content (panic on failure)
|
||||||
let input_content = fs::read_to_string(&input_file)
|
let input_content = fs::read_to_string(&input_file)
|
||||||
.unwrap_or_else(|e| panic!("Failed to read main.kcl in directory {}: {}", dir_name, e));
|
.unwrap_or_else(|e| panic!("Failed to read main.kcl in directory {dir_name}: {e}"));
|
||||||
|
|
||||||
// Create a benchmark group for this directory
|
// Create a benchmark group for this directory
|
||||||
let mut group = c.benchmark_group(&dir_name);
|
let mut group = c.benchmark_group(&dir_name);
|
||||||
@ -72,12 +72,12 @@ fn run_benchmarks(c: &mut Criterion) {
|
|||||||
#[cfg(feature = "benchmark-execution")]
|
#[cfg(feature = "benchmark-execution")]
|
||||||
let program = kcl_lib::Program::parse_no_errs(&input_content).unwrap();
|
let program = kcl_lib::Program::parse_no_errs(&input_content).unwrap();
|
||||||
|
|
||||||
group.bench_function(format!("parse_{}", dir_name), |b| {
|
group.bench_function(format!("parse_{dir_name}"), |b| {
|
||||||
b.iter(|| kcl_lib::Program::parse_no_errs(black_box(&input_content)).unwrap())
|
b.iter(|| kcl_lib::Program::parse_no_errs(black_box(&input_content)).unwrap())
|
||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(feature = "benchmark-execution")]
|
#[cfg(feature = "benchmark-execution")]
|
||||||
group.bench_function(format!("execute_{}", dir_name), |b| {
|
group.bench_function(format!("execute_{dir_name}"), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
if let Err(err) = rt.block_on(async {
|
if let Err(err) = rt.block_on(async {
|
||||||
let ctx = kcl_lib::ExecutorContext::new_with_default_client().await?;
|
let ctx = kcl_lib::ExecutorContext::new_with_default_client().await?;
|
||||||
@ -86,7 +86,7 @@ fn run_benchmarks(c: &mut Criterion) {
|
|||||||
ctx.close().await;
|
ctx.close().await;
|
||||||
Ok::<(), anyhow::Error>(())
|
Ok::<(), anyhow::Error>(())
|
||||||
}) {
|
}) {
|
||||||
panic!("Failed to execute program: {}", err);
|
panic!("Failed to execute program: {err}");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::hint::black_box;
|
use std::hint::black_box;
|
||||||
|
|
||||||
use criterion::{criterion_group, criterion_main, Criterion};
|
use criterion::{Criterion, criterion_group, criterion_main};
|
||||||
|
|
||||||
pub fn bench_parse(c: &mut Criterion) {
|
pub fn bench_parse(c: &mut Criterion) {
|
||||||
for (name, file) in [
|
for (name, file) in [
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use criterion::{criterion_group, criterion_main, Criterion};
|
use criterion::{Criterion, criterion_group, criterion_main};
|
||||||
|
|
||||||
pub fn bench_digest(c: &mut Criterion) {
|
pub fn bench_digest(c: &mut Criterion) {
|
||||||
for (name, file) in [
|
for (name, file) in [
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::hint::black_box;
|
use std::hint::black_box;
|
||||||
|
|
||||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
|
||||||
use kcl_lib::kcl_lsp_server;
|
use kcl_lib::kcl_lsp_server;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
use tower_lsp::LanguageServer;
|
use tower_lsp::LanguageServer;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
//! Cache testing framework.
|
//! Cache testing framework.
|
||||||
|
|
||||||
use kcl_lib::{bust_cache, ExecError, ExecOutcome};
|
use kcl_lib::{ExecError, ExecOutcome, bust_cache};
|
||||||
#[cfg(feature = "artifact-graph")]
|
#[cfg(feature = "artifact-graph")]
|
||||||
use kcl_lib::{exec::Operation, NodePathStep};
|
use kcl_lib::{NodePathStep, exec::Operation};
|
||||||
use kcmc::{each_cmd as mcmd, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ async fn cache_test(
|
|||||||
if !variation.other_files.is_empty() {
|
if !variation.other_files.is_empty() {
|
||||||
let tmp_dir = std::env::temp_dir();
|
let tmp_dir = std::env::temp_dir();
|
||||||
let tmp_dir = tmp_dir
|
let tmp_dir = tmp_dir
|
||||||
.join(format!("kcl_test_{}", test_name))
|
.join(format!("kcl_test_{test_name}"))
|
||||||
.join(uuid::Uuid::new_v4().to_string());
|
.join(uuid::Uuid::new_v4().to_string());
|
||||||
|
|
||||||
// Create a temporary file for each of the other files.
|
// Create a temporary file for each of the other files.
|
||||||
@ -56,7 +56,7 @@ async fn cache_test(
|
|||||||
Err(error) => {
|
Err(error) => {
|
||||||
let report = error.clone().into_miette_report_with_outputs(variation.code).unwrap();
|
let report = error.clone().into_miette_report_with_outputs(variation.code).unwrap();
|
||||||
let report = miette::Report::new(report);
|
let report = miette::Report::new(report);
|
||||||
panic!("{:?}", report);
|
panic!("{report:?}");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ async fn cache_test(
|
|||||||
.and_then(|x| x.decode().map_err(|e| ExecError::BadPng(e.to_string())))
|
.and_then(|x| x.decode().map_err(|e| ExecError::BadPng(e.to_string())))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Save the snapshot.
|
// Save the snapshot.
|
||||||
let path = crate::assert_out(&format!("cache_{}_{}", test_name, index), &img);
|
let path = crate::assert_out(&format!("cache_{test_name}_{index}"), &img);
|
||||||
|
|
||||||
img_results.push((path, img, outcome));
|
img_results.push((path, img, outcome));
|
||||||
}
|
}
|
||||||
@ -337,8 +337,7 @@ extrude001 = extrude(profile001, length = 4)
|
|||||||
// 0] as a more lenient check.
|
// 0] as a more lenient check.
|
||||||
.map(|c| !c.range.is_synthetic() && c.node_path.is_empty())
|
.map(|c| !c.range.is_synthetic() && c.node_path.is_empty())
|
||||||
.unwrap_or(false),
|
.unwrap_or(false),
|
||||||
"artifact={:?}",
|
"artifact={artifact:?}"
|
||||||
artifact
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
mod cache;
|
mod cache;
|
||||||
|
|
||||||
use kcl_lib::{
|
use kcl_lib::{
|
||||||
test_server::{execute_and_export_step, execute_and_snapshot, execute_and_snapshot_no_auth},
|
|
||||||
BacktraceItem, ExecError, ModuleId, SourceRange,
|
BacktraceItem, ExecError, ModuleId, SourceRange,
|
||||||
|
test_server::{execute_and_export_step, execute_and_snapshot, execute_and_snapshot_no_auth},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The minimum permissible difference between asserted twenty-twenty images.
|
/// The minimum permissible difference between asserted twenty-twenty images.
|
||||||
@ -869,11 +869,13 @@ async fn kcl_test_revolve_bad_angle_low() {
|
|||||||
let result = execute_and_snapshot(code, None).await;
|
let result = execute_and_snapshot(code, None).await;
|
||||||
|
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert!(result
|
assert!(
|
||||||
|
result
|
||||||
.err()
|
.err()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string()
|
.to_string()
|
||||||
.contains("Expected angle to be between -360 and 360 and not 0, found `-455`"));
|
.contains("Expected angle to be between -360 and 360 and not 0, found `-455`")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
@ -895,11 +897,13 @@ async fn kcl_test_revolve_bad_angle_high() {
|
|||||||
let result = execute_and_snapshot(code, None).await;
|
let result = execute_and_snapshot(code, None).await;
|
||||||
|
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert!(result
|
assert!(
|
||||||
|
result
|
||||||
.err()
|
.err()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string()
|
.to_string()
|
||||||
.contains("Expected angle to be between -360 and 360 and not 0, found `455`"));
|
.contains("Expected angle to be between -360 and 360 and not 0, found `455`")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
@ -2090,7 +2094,10 @@ async fn kcl_test_better_type_names() {
|
|||||||
},
|
},
|
||||||
None => todo!(),
|
None => todo!(),
|
||||||
};
|
};
|
||||||
assert_eq!(err, "This function expected the input argument to be one or more Solids or ImportedGeometry but it's actually of type Sketch. You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`");
|
assert_eq!(
|
||||||
|
err,
|
||||||
|
"This function expected the input argument to be one or more Solids or ImportedGeometry but it's actually of type Sketch. You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
@ -101,7 +101,7 @@ pub trait CoreDump: Clone {
|
|||||||
.meta()
|
.meta()
|
||||||
.create_debug_uploads(vec![kittycad::types::multipart::Attachment {
|
.create_debug_uploads(vec![kittycad::types::multipart::Attachment {
|
||||||
name: "".to_string(),
|
name: "".to_string(),
|
||||||
filepath: Some(format!(r#"modeling-app/coredump-{}.json"#, coredump_id).into()),
|
filepath: Some(format!(r#"modeling-app/coredump-{coredump_id}.json"#).into()),
|
||||||
content_type: Some("application/json".to_string()),
|
content_type: Some("application/json".to_string()),
|
||||||
data,
|
data,
|
||||||
}])
|
}])
|
||||||
|
@ -189,7 +189,7 @@ fn generate_example(index: usize, src: &str, props: &ExampleProperties, file_nam
|
|||||||
index
|
index
|
||||||
);
|
);
|
||||||
let image_data =
|
let image_data =
|
||||||
std::fs::read(&image_path).unwrap_or_else(|_| panic!("Failed to read image file: {}", image_path));
|
std::fs::read(&image_path).unwrap_or_else(|_| panic!("Failed to read image file: {image_path}"));
|
||||||
base64::engine::general_purpose::STANDARD.encode(&image_data)
|
base64::engine::general_purpose::STANDARD.encode(&image_data)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -225,7 +225,7 @@ fn generate_type_from_kcl(ty: &TyData, file_name: String, example_name: String,
|
|||||||
|
|
||||||
let output = hbs.render("kclType", &data)?;
|
let output = hbs.render("kclType", &data)?;
|
||||||
let output = cleanup_types(&output, kcl_std);
|
let output = cleanup_types(&output, kcl_std);
|
||||||
expectorate::assert_contents(format!("../../docs/kcl-std/{}.md", file_name), &output);
|
expectorate::assert_contents(format!("../../docs/kcl-std/{file_name}.md"), &output);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -267,7 +267,7 @@ fn generate_mod_from_kcl(m: &ModData, file_name: String) -> Result<()> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let output = hbs.render("module", &data)?;
|
let output = hbs.render("module", &data)?;
|
||||||
expectorate::assert_contents(format!("../../docs/kcl-std/{}.md", file_name), &output);
|
expectorate::assert_contents(format!("../../docs/kcl-std/{file_name}.md"), &output);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -334,7 +334,7 @@ fn generate_function_from_kcl(
|
|||||||
|
|
||||||
let output = hbs.render("function", &data)?;
|
let output = hbs.render("function", &data)?;
|
||||||
let output = &cleanup_types(&output, kcl_std);
|
let output = &cleanup_types(&output, kcl_std);
|
||||||
expectorate::assert_contents(format!("../../docs/kcl-std/{}.md", file_name), output);
|
expectorate::assert_contents(format!("../../docs/kcl-std/{file_name}.md"), output);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -378,7 +378,7 @@ fn generate_const_from_kcl(cnst: &ConstData, file_name: String, example_name: St
|
|||||||
|
|
||||||
let output = hbs.render("const", &data)?;
|
let output = hbs.render("const", &data)?;
|
||||||
let output = cleanup_types(&output, kcl_std);
|
let output = cleanup_types(&output, kcl_std);
|
||||||
expectorate::assert_contents(format!("../../docs/kcl-std/{}.md", file_name), &output);
|
expectorate::assert_contents(format!("../../docs/kcl-std/{file_name}.md"), &output);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use tower_lsp::lsp_types::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ModuleId,
|
||||||
execution::annotations,
|
execution::annotations,
|
||||||
parsing::{
|
parsing::{
|
||||||
ast::types::{
|
ast::types::{
|
||||||
@ -15,7 +16,6 @@ use crate::{
|
|||||||
},
|
},
|
||||||
token::NumericSuffix,
|
token::NumericSuffix,
|
||||||
},
|
},
|
||||||
ModuleId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn walk_prelude() -> ModData {
|
pub fn walk_prelude() -> ModData {
|
||||||
@ -97,7 +97,7 @@ fn visit_module(name: &str, preferred_prefix: &str, names: WalkForNames) -> Resu
|
|||||||
ImportSelector::None { .. } => {
|
ImportSelector::None { .. } => {
|
||||||
let name = import.module_name().unwrap();
|
let name = import.module_name().unwrap();
|
||||||
if names.contains(&name) {
|
if names.contains(&name) {
|
||||||
Some(visit_module(&path[1], &format!("{}::", name), WalkForNames::All)?)
|
Some(visit_module(&path[1], &format!("{name}::"), WalkForNames::All)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -451,7 +451,7 @@ impl ModData {
|
|||||||
let (name, qual_name, module_name) = if name == "prelude" {
|
let (name, qual_name, module_name) = if name == "prelude" {
|
||||||
("std", "std".to_owned(), String::new())
|
("std", "std".to_owned(), String::new())
|
||||||
} else {
|
} else {
|
||||||
(name, format!("std::{}", name), "std".to_owned())
|
(name, format!("std::{name}"), "std".to_owned())
|
||||||
};
|
};
|
||||||
Self {
|
Self {
|
||||||
preferred_name: format!("{preferred_prefix}{name}"),
|
preferred_name: format!("{preferred_prefix}{name}"),
|
||||||
@ -767,14 +767,12 @@ impl ArgData {
|
|||||||
for s in &arr.elements {
|
for s in &arr.elements {
|
||||||
let Expr::Literal(lit) = s else {
|
let Expr::Literal(lit) = s else {
|
||||||
panic!(
|
panic!(
|
||||||
"Invalid value in `snippetArray`, all items must be string literals but found {:?}",
|
"Invalid value in `snippetArray`, all items must be string literals but found {s:?}"
|
||||||
s
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
let LiteralValue::String(litstr) = &lit.inner.value else {
|
let LiteralValue::String(litstr) = &lit.inner.value else {
|
||||||
panic!(
|
panic!(
|
||||||
"Invalid value in `snippetArray`, all items must be string literals but found {:?}",
|
"Invalid value in `snippetArray`, all items must be string literals but found {s:?}"
|
||||||
s
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
items.push(litstr.to_owned());
|
items.push(litstr.to_owned());
|
||||||
@ -816,7 +814,7 @@ impl ArgData {
|
|||||||
}
|
}
|
||||||
match self.ty.as_deref() {
|
match self.ty.as_deref() {
|
||||||
Some("Sketch") if self.kind == ArgKind::Special => None,
|
Some("Sketch") if self.kind == ArgKind::Special => None,
|
||||||
Some(s) if s.starts_with("number") => Some((index, format!(r#"{label}${{{}:10}}"#, index))),
|
Some(s) if s.starts_with("number") => Some((index, format!(r#"{label}${{{index}:10}}"#))),
|
||||||
Some("Point2d") => Some((index + 1, format!(r#"{label}[${{{}:0}}, ${{{}:0}}]"#, index, index + 1))),
|
Some("Point2d") => Some((index + 1, format!(r#"{label}[${{{}:0}}, ${{{}:0}}]"#, index, index + 1))),
|
||||||
Some("Point3d") => Some((
|
Some("Point3d") => Some((
|
||||||
index + 2,
|
index + 2,
|
||||||
@ -831,7 +829,7 @@ impl ArgData {
|
|||||||
Some("Sketch") | Some("Sketch | Helix") => Some((index, format!(r#"{label}${{{index}:sketch000}}"#))),
|
Some("Sketch") | Some("Sketch | Helix") => Some((index, format!(r#"{label}${{{index}:sketch000}}"#))),
|
||||||
Some("Edge") => Some((index, format!(r#"{label}${{{index}:tag_or_edge_fn}}"#))),
|
Some("Edge") => Some((index, format!(r#"{label}${{{index}:tag_or_edge_fn}}"#))),
|
||||||
Some("[Edge; 1+]") => Some((index, format!(r#"{label}[${{{index}:tag_or_edge_fn}}]"#))),
|
Some("[Edge; 1+]") => Some((index, format!(r#"{label}[${{{index}:tag_or_edge_fn}}]"#))),
|
||||||
Some("Plane") | Some("Solid | Plane") => Some((index, format!(r#"{label}${{{}:XY}}"#, index))),
|
Some("Plane") | Some("Solid | Plane") => Some((index, format!(r#"{label}${{{index}:XY}}"#))),
|
||||||
Some("[TaggedFace; 2]") => Some((
|
Some("[TaggedFace; 2]") => Some((
|
||||||
index + 1,
|
index + 1,
|
||||||
format!(r#"{label}[${{{}:tag}}, ${{{}:tag}}]"#, index, index + 1),
|
format!(r#"{label}[${{{}:tag}}, ${{{}:tag}}]"#, index, index + 1),
|
||||||
@ -841,10 +839,10 @@ impl ArgData {
|
|||||||
if self.name == "color" {
|
if self.name == "color" {
|
||||||
Some((index, format!(r"{label}${{{}:{}}}", index, "\"#ff0000\"")))
|
Some((index, format!(r"{label}${{{}:{}}}", index, "\"#ff0000\"")))
|
||||||
} else {
|
} else {
|
||||||
Some((index, format!(r#"{label}${{{}:"string"}}"#, index)))
|
Some((index, format!(r#"{label}${{{index}:"string"}}"#)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some("bool") => Some((index, format!(r#"{label}${{{}:false}}"#, index))),
|
Some("bool") => Some((index, format!(r#"{label}${{{index}:false}}"#))),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1298,7 +1296,10 @@ mod test {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let name = format!("{}-{i}", f.qual_name.replace("::", "-"));
|
let name = format!("{}-{i}", f.qual_name.replace("::", "-"));
|
||||||
assert!(TEST_NAMES.contains(&&*name), "Missing test for example \"{name}\", maybe need to update kcl-derive-docs/src/example_tests.rs?")
|
assert!(
|
||||||
|
TEST_NAMES.contains(&&*name),
|
||||||
|
"Missing test for example \"{name}\", maybe need to update kcl-derive-docs/src/example_tests.rs?"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1334,7 +1335,9 @@ mod test {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let Some(DocData::Fn(d)) = data.children.get(&format!("I:{qualname}")) else {
|
let Some(DocData::Fn(d)) = data.children.get(&format!("I:{qualname}")) else {
|
||||||
panic!("Could not find data for {NAME} (missing a child entry for {qualname}), maybe need to update kcl-derive-docs/src/example_tests.rs?");
|
panic!(
|
||||||
|
"Could not find data for {NAME} (missing a child entry for {qualname}), maybe need to update kcl-derive-docs/src/example_tests.rs?"
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i, eg) in d.examples.iter().enumerate() {
|
for (i, eg) in d.examples.iter().enumerate() {
|
||||||
@ -1362,6 +1365,8 @@ mod test {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!("Could not find data for {NAME} (no example {number}), maybe need to update kcl-derive-docs/src/example_tests.rs?");
|
panic!(
|
||||||
|
"Could not find data for {NAME} (no example {number}), maybe need to update kcl-derive-docs/src/example_tests.rs?"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
//! tasks.
|
//! tasks.
|
||||||
|
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
atomic::{AtomicUsize, Ordering},
|
|
||||||
Arc,
|
Arc,
|
||||||
|
atomic::{AtomicUsize, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
use tokio::sync::{mpsc, Notify};
|
use tokio::sync::{Notify, mpsc};
|
||||||
|
|
||||||
use crate::errors::KclError;
|
use crate::errors::KclError;
|
||||||
|
|
||||||
|
@ -3,26 +3,26 @@
|
|||||||
|
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{Result, anyhow};
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use kcmc::{
|
use kcmc::{
|
||||||
|
ModelingCmd,
|
||||||
websocket::{
|
websocket::{
|
||||||
BatchResponse, FailureWebSocketResponse, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData,
|
BatchResponse, FailureWebSocketResponse, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData,
|
||||||
SuccessWebSocketResponse, WebSocketRequest, WebSocketResponse,
|
SuccessWebSocketResponse, WebSocketRequest, WebSocketResponse,
|
||||||
},
|
},
|
||||||
ModelingCmd,
|
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds::{self as kcmc};
|
use kittycad_modeling_cmds::{self as kcmc};
|
||||||
use tokio::sync::{mpsc, oneshot, RwLock};
|
use tokio::sync::{RwLock, mpsc, oneshot};
|
||||||
use tokio_tungstenite::tungstenite::Message as WsMsg;
|
use tokio_tungstenite::tungstenite::Message as WsMsg;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
SourceRange,
|
||||||
engine::{AsyncTasks, EngineManager, EngineStats},
|
engine::{AsyncTasks, EngineManager, EngineStats},
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{DefaultPlanes, IdGenerator},
|
execution::{DefaultPlanes, IdGenerator},
|
||||||
SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@ -85,7 +85,7 @@ impl TcpRead {
|
|||||||
let msg = match msg {
|
let msg = match msg {
|
||||||
Ok(msg) => msg,
|
Ok(msg) => msg,
|
||||||
Err(e) if matches!(e, tokio_tungstenite::tungstenite::Error::Protocol(_)) => {
|
Err(e) if matches!(e, tokio_tungstenite::tungstenite::Error::Protocol(_)) => {
|
||||||
return Err(WebSocketReadError::Read(e))
|
return Err(WebSocketReadError::Read(e));
|
||||||
}
|
}
|
||||||
Err(e) => return Err(anyhow::anyhow!("Error reading from engine's WebSocket: {e}").into()),
|
Err(e) => return Err(anyhow::anyhow!("Error reading from engine's WebSocket: {e}").into()),
|
||||||
};
|
};
|
||||||
@ -427,7 +427,7 @@ impl EngineManager for EngineConnection {
|
|||||||
request_sent: tx,
|
request_sent: tx,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.map_err(|e| KclError::new_engine(KclErrorDetails::new(format!("Failed to send debug: {}", e), vec![])))?;
|
.map_err(|e| KclError::new_engine(KclErrorDetails::new(format!("Failed to send debug: {e}"), vec![])))?;
|
||||||
|
|
||||||
let _ = rx.await;
|
let _ = rx.await;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -463,7 +463,7 @@ impl EngineManager for EngineConnection {
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
KclError::new_engine(KclErrorDetails::new(
|
KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("Failed to send modeling command: {}", e),
|
format!("Failed to send modeling command: {e}"),
|
||||||
vec![source_range],
|
vec![source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -533,7 +533,7 @@ impl EngineManager for EngineConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Err(KclError::new_engine(KclErrorDetails::new(
|
Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("Modeling command timed out `{}`", id),
|
format!("Modeling command timed out `{id}`"),
|
||||||
vec![source_range],
|
vec![source_range],
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
@ -12,16 +12,16 @@ use kcmc::{
|
|||||||
WebSocketResponse,
|
WebSocketResponse,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds::{self as kcmc, websocket::ModelingCmdReq, ImportFiles, ModelingCmd};
|
use kittycad_modeling_cmds::{self as kcmc, ImportFiles, ModelingCmd, websocket::ModelingCmdReq};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
SourceRange,
|
||||||
engine::{AsyncTasks, EngineStats},
|
engine::{AsyncTasks, EngineStats},
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
exec::DefaultPlanes,
|
exec::DefaultPlanes,
|
||||||
execution::IdGenerator,
|
execution::IdGenerator,
|
||||||
SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -11,10 +11,10 @@ use uuid::Uuid;
|
|||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
SourceRange,
|
||||||
engine::{AsyncTasks, EngineStats},
|
engine::{AsyncTasks, EngineStats},
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{DefaultPlanes, IdGenerator},
|
execution::{DefaultPlanes, IdGenerator},
|
||||||
SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[wasm_bindgen(module = "/../../src/lang/std/engineConnection.ts")]
|
#[wasm_bindgen(module = "/../../src/lang/std/engineConnection.ts")]
|
||||||
|
@ -12,15 +12,15 @@ pub mod conn_wasm;
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicUsize, Ordering},
|
|
||||||
Arc,
|
Arc,
|
||||||
|
atomic::{AtomicUsize, Ordering},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use async_tasks::AsyncTasks;
|
pub use async_tasks::AsyncTasks;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use kcmc::{
|
use kcmc::{
|
||||||
each_cmd as mcmd,
|
ModelingCmd, each_cmd as mcmd,
|
||||||
length_unit::LengthUnit,
|
length_unit::LengthUnit,
|
||||||
ok_response::OkModelingCmdResponse,
|
ok_response::OkModelingCmdResponse,
|
||||||
shared::Color,
|
shared::Color,
|
||||||
@ -28,7 +28,6 @@ use kcmc::{
|
|||||||
BatchResponse, ModelingBatch, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData, WebSocketRequest,
|
BatchResponse, ModelingBatch, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData, WebSocketRequest,
|
||||||
WebSocketResponse,
|
WebSocketResponse,
|
||||||
},
|
},
|
||||||
ModelingCmd,
|
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
@ -39,9 +38,9 @@ use uuid::Uuid;
|
|||||||
use web_time::Instant;
|
use web_time::Instant;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
|
||||||
execution::{types::UnitLen, DefaultPlanes, IdGenerator, PlaneInfo, Point3d},
|
|
||||||
SourceRange,
|
SourceRange,
|
||||||
|
errors::{KclError, KclErrorDetails},
|
||||||
|
execution::{DefaultPlanes, IdGenerator, PlaneInfo, Point3d, types::UnitLen},
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
@ -291,7 +290,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
// the artifact graph won't care either if its gone since you can't select it
|
// the artifact graph won't care either if its gone since you can't select it
|
||||||
// anymore anyways.
|
// anymore anyways.
|
||||||
if let Err(err) = self.async_tasks().join_all().await {
|
if let Err(err) = self.async_tasks().join_all().await {
|
||||||
crate::log::logln!("Error waiting for async tasks (this is typically fine and just means that an edge became something else): {:?}", err);
|
crate::log::logln!(
|
||||||
|
"Error waiting for async tasks (this is typically fine and just means that an edge became something else): {:?}",
|
||||||
|
err
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush the batch to make sure nothing remains.
|
// Flush the batch to make sure nothing remains.
|
||||||
@ -499,7 +501,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(KclError::new_engine(KclErrorDetails::new(
|
return Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("The request is not a modeling command: {:?}", req),
|
format!("The request is not a modeling command: {req:?}"),
|
||||||
vec![*range],
|
vec![*range],
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -529,7 +531,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
} else {
|
} else {
|
||||||
// We should never get here.
|
// We should never get here.
|
||||||
Err(KclError::new_engine(KclErrorDetails::new(
|
Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("Failed to get batch response: {:?}", response),
|
format!("Failed to get batch response: {response:?}"),
|
||||||
vec![source_range],
|
vec![source_range],
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
@ -544,7 +546,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
// an error.
|
// an error.
|
||||||
let source_range = id_to_source_range.get(cmd_id.as_ref()).cloned().ok_or_else(|| {
|
let source_range = id_to_source_range.get(cmd_id.as_ref()).cloned().ok_or_else(|| {
|
||||||
KclError::new_engine(KclErrorDetails::new(
|
KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("Failed to get source range for command ID: {:?}", cmd_id),
|
format!("Failed to get source range for command ID: {cmd_id:?}"),
|
||||||
vec![],
|
vec![],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -554,7 +556,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
self.parse_websocket_response(ws_resp, source_range)
|
self.parse_websocket_response(ws_resp, source_range)
|
||||||
}
|
}
|
||||||
_ => Err(KclError::new_engine(KclErrorDetails::new(
|
_ => Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("The final request is not a modeling command: {:?}", final_req),
|
format!("The final request is not a modeling command: {final_req:?}"),
|
||||||
vec![source_range],
|
vec![source_range],
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
@ -663,7 +665,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
let info = DEFAULT_PLANE_INFO.get(&name).ok_or_else(|| {
|
let info = DEFAULT_PLANE_INFO.get(&name).ok_or_else(|| {
|
||||||
// We should never get here.
|
// We should never get here.
|
||||||
KclError::new_engine(KclErrorDetails::new(
|
KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("Failed to get default plane info for: {:?}", name),
|
format!("Failed to get default plane info for: {name:?}"),
|
||||||
vec![source_range],
|
vec![source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -739,7 +741,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
// Get the source range for the command.
|
// Get the source range for the command.
|
||||||
let source_range = id_to_source_range.get(cmd_id).cloned().ok_or_else(|| {
|
let source_range = id_to_source_range.get(cmd_id).cloned().ok_or_else(|| {
|
||||||
KclError::new_engine(KclErrorDetails::new(
|
KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("Failed to get source range for command ID: {:?}", cmd_id),
|
format!("Failed to get source range for command ID: {cmd_id:?}"),
|
||||||
vec![],
|
vec![],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -754,7 +756,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
// Return an error that we did not get an error or the response we wanted.
|
// Return an error that we did not get an error or the response we wanted.
|
||||||
// This should never happen but who knows.
|
// This should never happen but who knows.
|
||||||
Err(KclError::new_engine(KclErrorDetails::new(
|
Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("Failed to find response for command ID: {:?}", id),
|
format!("Failed to find response for command ID: {id:?}"),
|
||||||
vec![],
|
vec![],
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,11 @@ use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
|
|||||||
#[cfg(feature = "artifact-graph")]
|
#[cfg(feature = "artifact-graph")]
|
||||||
use crate::execution::{ArtifactCommand, ArtifactGraph, Operation};
|
use crate::execution::{ArtifactCommand, ArtifactGraph, Operation};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ModuleId,
|
||||||
execution::DefaultPlanes,
|
execution::DefaultPlanes,
|
||||||
lsp::IntoDiagnostic,
|
lsp::IntoDiagnostic,
|
||||||
modules::{ModulePath, ModuleSource},
|
modules::{ModulePath, ModuleSource},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
ModuleId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// How did the KCL execution fail
|
/// How did the KCL execution fail
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use kittycad_modeling_cmds::coord::{System, KITTYCAD, OPENGL, VULKAN};
|
use kittycad_modeling_cmds::coord::{KITTYCAD, OPENGL, System, VULKAN};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
KclError, SourceRange,
|
||||||
errors::KclErrorDetails,
|
errors::KclErrorDetails,
|
||||||
execution::types::{UnitAngle, UnitLen},
|
execution::types::{UnitAngle, UnitLen},
|
||||||
parsing::ast::types::{Annotation, Expr, LiteralValue, Node, ObjectProperty},
|
parsing::ast::types::{Annotation, Expr, LiteralValue, Node, ObjectProperty},
|
||||||
KclError, SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Annotations which should cause re-execution if they change.
|
/// Annotations which should cause re-execution if they change.
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use kittycad_modeling_cmds::{
|
use kittycad_modeling_cmds::{
|
||||||
self as kcmc,
|
self as kcmc, EnableSketchMode, ModelingCmd,
|
||||||
ok_response::OkModelingCmdResponse,
|
ok_response::OkModelingCmdResponse,
|
||||||
shared::ExtrusionFaceCapType,
|
shared::ExtrusionFaceCapType,
|
||||||
websocket::{BatchResponse, OkWebSocketResponseData, WebSocketResponse},
|
websocket::{BatchResponse, OkWebSocketResponseData, WebSocketResponse},
|
||||||
EnableSketchMode, ModelingCmd,
|
|
||||||
};
|
};
|
||||||
use serde::{ser::SerializeSeq, Serialize};
|
use serde::{Serialize, ser::SerializeSeq};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
KclError, NodePath, SourceRange,
|
||||||
errors::KclErrorDetails,
|
errors::KclErrorDetails,
|
||||||
execution::ArtifactId,
|
execution::ArtifactId,
|
||||||
parsing::ast::types::{Node, Program},
|
parsing::ast::types::{Node, Program},
|
||||||
KclError, NodePath, SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -893,7 +892,10 @@ fn artifacts_to_update(
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
if original_path_ids.len() != face_edge_infos.len() {
|
if original_path_ids.len() != face_edge_infos.len() {
|
||||||
internal_error!(range, "EntityMirror or EntityMirrorAcrossEdge response has different number face edge info than original mirrored paths: id={id:?}, cmd={cmd:?}, response={response:?}");
|
internal_error!(
|
||||||
|
range,
|
||||||
|
"EntityMirror or EntityMirrorAcrossEdge response has different number face edge info than original mirrored paths: id={id:?}, cmd={cmd:?}, response={response:?}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let mut return_arr = Vec::new();
|
let mut return_arr = Vec::new();
|
||||||
for (face_edge_info, original_path_id) in face_edge_infos.iter().zip(original_path_ids) {
|
for (face_edge_info, original_path_id) in face_edge_infos.iter().zip(original_path_ids) {
|
||||||
@ -909,7 +911,10 @@ fn artifacts_to_update(
|
|||||||
// of its info.
|
// of its info.
|
||||||
let Some(Artifact::Path(original_path)) = artifacts.get(&original_path_id) else {
|
let Some(Artifact::Path(original_path)) = artifacts.get(&original_path_id) else {
|
||||||
// We couldn't find the original path. This is a bug.
|
// We couldn't find the original path. This is a bug.
|
||||||
internal_error!(range, "Couldn't find original path for mirror2d: original_path_id={original_path_id:?}, cmd={cmd:?}");
|
internal_error!(
|
||||||
|
range,
|
||||||
|
"Couldn't find original path for mirror2d: original_path_id={original_path_id:?}, cmd={cmd:?}"
|
||||||
|
);
|
||||||
};
|
};
|
||||||
Path {
|
Path {
|
||||||
id: path_id,
|
id: path_id,
|
||||||
|
@ -268,7 +268,7 @@ impl ArtifactGraph {
|
|||||||
for (group_id, artifact_ids) in groups {
|
for (group_id, artifact_ids) in groups {
|
||||||
let group_id = *stable_id_map.get(&group_id).unwrap();
|
let group_id = *stable_id_map.get(&group_id).unwrap();
|
||||||
writeln!(output, "{prefix}subgraph path{group_id} [Path]")?;
|
writeln!(output, "{prefix}subgraph path{group_id} [Path]")?;
|
||||||
let indented = format!("{} ", prefix);
|
let indented = format!("{prefix} ");
|
||||||
for artifact_id in artifact_ids {
|
for artifact_id in artifact_ids {
|
||||||
let artifact = self.map.get(&artifact_id).unwrap();
|
let artifact = self.map.get(&artifact_id).unwrap();
|
||||||
let id = *stable_id_map.get(&artifact_id).unwrap();
|
let id = *stable_id_map.get(&artifact_id).unwrap();
|
||||||
@ -353,7 +353,7 @@ impl ArtifactGraph {
|
|||||||
node_path_display(output, prefix, None, &segment.code_ref)?;
|
node_path_display(output, prefix, None, &segment.code_ref)?;
|
||||||
}
|
}
|
||||||
Artifact::Solid2d(_solid2d) => {
|
Artifact::Solid2d(_solid2d) => {
|
||||||
writeln!(output, "{prefix}{}[Solid2d]", id)?;
|
writeln!(output, "{prefix}{id}[Solid2d]")?;
|
||||||
}
|
}
|
||||||
Artifact::StartSketchOnFace(StartSketchOnFace { code_ref, .. }) => {
|
Artifact::StartSketchOnFace(StartSketchOnFace { code_ref, .. }) => {
|
||||||
writeln!(
|
writeln!(
|
||||||
@ -494,24 +494,24 @@ impl ArtifactGraph {
|
|||||||
match edge.flow {
|
match edge.flow {
|
||||||
EdgeFlow::SourceToTarget => match edge.direction {
|
EdgeFlow::SourceToTarget => match edge.direction {
|
||||||
EdgeDirection::Forward => {
|
EdgeDirection::Forward => {
|
||||||
writeln!(output, "{prefix}{source_id} x{}--> {}", extra, target_id)?;
|
writeln!(output, "{prefix}{source_id} x{extra}--> {target_id}")?;
|
||||||
}
|
}
|
||||||
EdgeDirection::Backward => {
|
EdgeDirection::Backward => {
|
||||||
writeln!(output, "{prefix}{source_id} <{}--x {}", extra, target_id)?;
|
writeln!(output, "{prefix}{source_id} <{extra}--x {target_id}")?;
|
||||||
}
|
}
|
||||||
EdgeDirection::Bidirectional => {
|
EdgeDirection::Bidirectional => {
|
||||||
writeln!(output, "{prefix}{source_id} {}--- {}", extra, target_id)?;
|
writeln!(output, "{prefix}{source_id} {extra}--- {target_id}")?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
EdgeFlow::TargetToSource => match edge.direction {
|
EdgeFlow::TargetToSource => match edge.direction {
|
||||||
EdgeDirection::Forward => {
|
EdgeDirection::Forward => {
|
||||||
writeln!(output, "{prefix}{target_id} x{}--> {}", extra, source_id)?;
|
writeln!(output, "{prefix}{target_id} x{extra}--> {source_id}")?;
|
||||||
}
|
}
|
||||||
EdgeDirection::Backward => {
|
EdgeDirection::Backward => {
|
||||||
writeln!(output, "{prefix}{target_id} <{}--x {}", extra, source_id)?;
|
writeln!(output, "{prefix}{target_id} <{extra}--x {source_id}")?;
|
||||||
}
|
}
|
||||||
EdgeDirection::Bidirectional => {
|
EdgeDirection::Bidirectional => {
|
||||||
writeln!(output, "{prefix}{target_id} {}--- {}", extra, source_id)?;
|
writeln!(output, "{prefix}{target_id} {extra}--- {source_id}")?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,14 @@ use itertools::{EitherOrBoth, Itertools};
|
|||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ExecOutcome, ExecutorContext,
|
||||||
execution::{
|
execution::{
|
||||||
annotations,
|
EnvironmentRef, ExecutorSettings, annotations,
|
||||||
memory::Stack,
|
memory::Stack,
|
||||||
state::{self as exec_state, ModuleInfoMap},
|
state::{self as exec_state, ModuleInfoMap},
|
||||||
EnvironmentRef, ExecutorSettings,
|
|
||||||
},
|
},
|
||||||
parsing::ast::types::{Annotation, Node, Program},
|
parsing::ast::types::{Annotation, Node, Program},
|
||||||
walk::Node as WalkNode,
|
walk::Node as WalkNode,
|
||||||
ExecOutcome, ExecutorContext,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
@ -337,7 +336,7 @@ mod tests {
|
|||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::execution::{parse_execute, parse_execute_with_project_dir, ExecTestResults};
|
use crate::execution::{ExecTestResults, parse_execute, parse_execute_with_project_dir};
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_changed_program_same_code() {
|
async fn test_get_changed_program_same_code() {
|
||||||
@ -755,7 +754,7 @@ extrude(profile001, length = 100)"#
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let CacheResult::CheckImportsOnly { reapply_settings, .. } = result else {
|
let CacheResult::CheckImportsOnly { reapply_settings, .. } = result else {
|
||||||
panic!("Expected CheckImportsOnly, got {:?}", result);
|
panic!("Expected CheckImportsOnly, got {result:?}");
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(reapply_settings, false);
|
assert_eq!(reapply_settings, false);
|
||||||
@ -839,7 +838,7 @@ extrude(profile001, length = 100)
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let CacheResult::CheckImportsOnly { reapply_settings, .. } = result else {
|
let CacheResult::CheckImportsOnly { reapply_settings, .. } = result else {
|
||||||
panic!("Expected CheckImportsOnly, got {:?}", result);
|
panic!("Expected CheckImportsOnly, got {result:?}");
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(reapply_settings, false);
|
assert_eq!(reapply_settings, false);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use super::{types::NumericType, ArtifactId, KclValue};
|
use super::{ArtifactId, KclValue, types::NumericType};
|
||||||
#[cfg(feature = "artifact-graph")]
|
#[cfg(feature = "artifact-graph")]
|
||||||
use crate::parsing::ast::types::{Node, Program};
|
use crate::parsing::ast::types::{Node, Program};
|
||||||
use crate::{parsing::ast::types::ItemVisibility, ModuleId, NodePath, SourceRange};
|
use crate::{ModuleId, NodePath, SourceRange, parsing::ast::types::ItemVisibility};
|
||||||
|
|
||||||
/// A CAD modeling operation for display in the feature tree, AKA operations
|
/// A CAD modeling operation for display in the feature tree, AKA operations
|
||||||
/// timeline.
|
/// timeline.
|
||||||
@ -57,7 +57,7 @@ impl Operation {
|
|||||||
/// If the variant is `StdLibCall`, set the `is_error` field.
|
/// If the variant is `StdLibCall`, set the `is_error` field.
|
||||||
pub(crate) fn set_std_lib_call_is_error(&mut self, is_err: bool) {
|
pub(crate) fn set_std_lib_call_is_error(&mut self, is_err: bool) {
|
||||||
match self {
|
match self {
|
||||||
Self::StdLibCall { ref mut is_error, .. } => *is_error = is_err,
|
Self::StdLibCall { is_error, .. } => *is_error = is_err,
|
||||||
Self::VariableDeclaration { .. } | Self::GroupBegin { .. } | Self::GroupEnd => {}
|
Self::VariableDeclaration { .. } | Self::GroupBegin { .. } | Self::GroupEnd => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,17 @@ use std::collections::HashMap;
|
|||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
CompilationError, NodePath,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
annotations,
|
BodyType, EnvironmentRef, ExecState, ExecutorContext, KclValue, Metadata, ModelingCmdMeta, ModuleArtifactState,
|
||||||
|
Operation, PlaneType, StatementKind, TagIdentifier, annotations,
|
||||||
cad_op::OpKclValue,
|
cad_op::OpKclValue,
|
||||||
fn_call::Args,
|
fn_call::Args,
|
||||||
kcl_value::{FunctionSource, TypeDef},
|
kcl_value::{FunctionSource, TypeDef},
|
||||||
memory,
|
memory,
|
||||||
state::ModuleState,
|
state::ModuleState,
|
||||||
types::{NumericType, PrimitiveType, RuntimeType},
|
types::{NumericType, PrimitiveType, RuntimeType},
|
||||||
BodyType, EnvironmentRef, ExecState, ExecutorContext, KclValue, Metadata, ModelingCmdMeta, ModuleArtifactState,
|
|
||||||
Operation, PlaneType, StatementKind, TagIdentifier,
|
|
||||||
},
|
},
|
||||||
fmt,
|
fmt,
|
||||||
modules::{ModuleId, ModulePath, ModuleRepr},
|
modules::{ModuleId, ModulePath, ModuleRepr},
|
||||||
@ -28,7 +28,6 @@ use crate::{
|
|||||||
},
|
},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
std::args::TyF64,
|
std::args::TyF64,
|
||||||
CompilationError, NodePath,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'a> StatementKind<'a> {
|
impl<'a> StatementKind<'a> {
|
||||||
@ -198,19 +197,23 @@ impl ExecutorContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ty.is_ok() && !module_exports.contains(&ty_name) {
|
if ty.is_ok() && !module_exports.contains(&ty_name) {
|
||||||
ty = Err(KclError::new_semantic(KclErrorDetails::new(format!(
|
ty = Err(KclError::new_semantic(KclErrorDetails::new(
|
||||||
|
format!(
|
||||||
"Cannot import \"{}\" from module because it is not exported. Add \"export\" before the definition to export it.",
|
"Cannot import \"{}\" from module because it is not exported. Add \"export\" before the definition to export it.",
|
||||||
import_item.name.name
|
import_item.name.name
|
||||||
),
|
),
|
||||||
vec![SourceRange::from(&import_item.name)],)));
|
vec![SourceRange::from(&import_item.name)],
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if mod_value.is_ok() && !module_exports.contains(&mod_name) {
|
if mod_value.is_ok() && !module_exports.contains(&mod_name) {
|
||||||
mod_value = Err(KclError::new_semantic(KclErrorDetails::new(format!(
|
mod_value = Err(KclError::new_semantic(KclErrorDetails::new(
|
||||||
|
format!(
|
||||||
"Cannot import \"{}\" from module because it is not exported. Add \"export\" before the definition to export it.",
|
"Cannot import \"{}\" from module because it is not exported. Add \"export\" before the definition to export it.",
|
||||||
import_item.name.name
|
import_item.name.name
|
||||||
),
|
),
|
||||||
vec![SourceRange::from(&import_item.name)],)));
|
vec![SourceRange::from(&import_item.name)],
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if value.is_err() && ty.is_err() && mod_value.is_err() {
|
if value.is_err() && ty.is_err() && mod_value.is_err() {
|
||||||
@ -270,7 +273,7 @@ impl ExecutorContext {
|
|||||||
.get_from(name, env_ref, source_range, 0)
|
.get_from(name, env_ref, source_range, 0)
|
||||||
.map_err(|_err| {
|
.map_err(|_err| {
|
||||||
KclError::new_internal(KclErrorDetails::new(
|
KclError::new_internal(KclErrorDetails::new(
|
||||||
format!("{} is not defined in module (but was exported?)", name),
|
format!("{name} is not defined in module (but was exported?)"),
|
||||||
vec![source_range],
|
vec![source_range],
|
||||||
))
|
))
|
||||||
})?
|
})?
|
||||||
@ -431,7 +434,7 @@ impl ExecutorContext {
|
|||||||
return Err(KclError::new_semantic(KclErrorDetails::new(
|
return Err(KclError::new_semantic(KclErrorDetails::new(
|
||||||
"User-defined types are not yet supported.".to_owned(),
|
"User-defined types are not yet supported.".to_owned(),
|
||||||
vec![metadata.source_range],
|
vec![metadata.source_range],
|
||||||
)))
|
)));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -792,11 +795,12 @@ fn var_in_own_ref_err(e: KclError, being_declared: &Option<String>) -> KclError
|
|||||||
// TODO after June 26th: replace this with a let-chain,
|
// TODO after June 26th: replace this with a let-chain,
|
||||||
// which will be available in Rust 1.88
|
// which will be available in Rust 1.88
|
||||||
// https://rust-lang.github.io/rfcs/2497-if-let-chains.html
|
// https://rust-lang.github.io/rfcs/2497-if-let-chains.html
|
||||||
match (&being_declared, &name) {
|
if let (Some(name0), Some(name1)) = (&being_declared, &name)
|
||||||
(Some(name0), Some(name1)) if name0 == name1 => {
|
&& name0 == name1
|
||||||
details.message = format!("You can't use `{name0}` because you're currently trying to define it. Use a different variable here instead.");
|
{
|
||||||
}
|
details.message = format!(
|
||||||
_ => {}
|
"You can't use `{name0}` because you're currently trying to define it. Use a different variable here instead."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
KclError::UndefinedValue { details, name }
|
KclError::UndefinedValue { details, name }
|
||||||
}
|
}
|
||||||
@ -1077,7 +1081,7 @@ impl Node<BinaryExpression> {
|
|||||||
(&left_value, &right_value)
|
(&left_value, &right_value)
|
||||||
{
|
{
|
||||||
return Ok(KclValue::String {
|
return Ok(KclValue::String {
|
||||||
value: format!("{}{}", left, right),
|
value: format!("{left}{right}"),
|
||||||
meta,
|
meta,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1237,7 +1241,9 @@ impl Node<BinaryExpression> {
|
|||||||
exec_state.clear_units_warnings(&sr);
|
exec_state.clear_units_warnings(&sr);
|
||||||
let mut err = CompilationError::err(
|
let mut err = CompilationError::err(
|
||||||
sr,
|
sr,
|
||||||
format!("{} numbers which have unknown or incompatible units.\nYou can probably fix this error by specifying the units using type ascription, e.g., `len: number(mm)` or `(a * b): number(deg)`.", verb),
|
format!(
|
||||||
|
"{verb} numbers which have unknown or incompatible units.\nYou can probably fix this error by specifying the units using type ascription, e.g., `len: number(mm)` or `(a * b): number(deg)`."
|
||||||
|
),
|
||||||
);
|
);
|
||||||
err.tag = crate::errors::Tag::UnknownNumericUnits;
|
err.tag = crate::errors::Tag::UnknownNumericUnits;
|
||||||
exec_state.warn(err);
|
exec_state.warn(err);
|
||||||
@ -1417,7 +1423,7 @@ async fn inner_execute_pipe_body(
|
|||||||
for expression in body {
|
for expression in body {
|
||||||
if let Expr::TagDeclarator(_) = expression {
|
if let Expr::TagDeclarator(_) = expression {
|
||||||
return Err(KclError::new_semantic(KclErrorDetails::new(
|
return Err(KclError::new_semantic(KclErrorDetails::new(
|
||||||
format!("This cannot be in a PipeExpression: {:?}", expression),
|
format!("This cannot be in a PipeExpression: {expression:?}"),
|
||||||
vec![expression.into()],
|
vec![expression.into()],
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -1699,9 +1705,15 @@ fn jvalue_to_prop(value: &KclValue, property_sr: Vec<SourceRange>, name: &str) -
|
|||||||
let make_err =
|
let make_err =
|
||||||
|message: String| Err::<Property, _>(KclError::new_semantic(KclErrorDetails::new(message, property_sr)));
|
|message: String| Err::<Property, _>(KclError::new_semantic(KclErrorDetails::new(message, property_sr)));
|
||||||
match value {
|
match value {
|
||||||
n @ KclValue::Number{value: num, ty, .. } => {
|
n @ KclValue::Number { value: num, ty, .. } => {
|
||||||
if !matches!(ty, NumericType::Known(crate::exec::UnitType::Count) | NumericType::Default { .. } | NumericType::Any ) {
|
if !matches!(
|
||||||
return make_err(format!("arrays can only be indexed by non-dimensioned numbers, found {}", n.human_friendly_type()));
|
ty,
|
||||||
|
NumericType::Known(crate::exec::UnitType::Count) | NumericType::Default { .. } | NumericType::Any
|
||||||
|
) {
|
||||||
|
return make_err(format!(
|
||||||
|
"arrays can only be indexed by non-dimensioned numbers, found {}",
|
||||||
|
n.human_friendly_type()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
let num = *num;
|
let num = *num;
|
||||||
if num < 0.0 {
|
if num < 0.0 {
|
||||||
@ -1711,13 +1723,15 @@ fn jvalue_to_prop(value: &KclValue, property_sr: Vec<SourceRange>, name: &str) -
|
|||||||
if let Some(nearest_int) = nearest_int {
|
if let Some(nearest_int) = nearest_int {
|
||||||
Ok(Property::UInt(nearest_int))
|
Ok(Property::UInt(nearest_int))
|
||||||
} else {
|
} else {
|
||||||
make_err(format!("'{num}' is not an integer, so you can't index an array with it"))
|
make_err(format!(
|
||||||
|
"'{num}' is not an integer, so you can't index an array with it"
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KclValue::String{value: x, meta:_} => Ok(Property::String(x.to_owned())),
|
KclValue::String { value: x, meta: _ } => Ok(Property::String(x.to_owned())),
|
||||||
_ => {
|
_ => make_err(format!(
|
||||||
make_err(format!("{name} is not a valid property/index, you can only use a string to get the property of an object, or an int (>= 0) to get an item in an array"))
|
"{name} is not a valid property/index, you can only use a string to get the property of an object, or an int (>= 0) to get an item in an array"
|
||||||
}
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1745,9 +1759,9 @@ mod test {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
exec::UnitType,
|
|
||||||
execution::{parse_execute, ContextType},
|
|
||||||
ExecutorSettings, UnitLen,
|
ExecutorSettings, UnitLen,
|
||||||
|
exec::UnitType,
|
||||||
|
execution::{ContextType, parse_execute},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
@ -1777,7 +1791,7 @@ arr1 = [42]: [number(cm)]
|
|||||||
.get_from("arr1", result.mem_env, SourceRange::default(), 0)
|
.get_from("arr1", result.mem_env, SourceRange::default(), 0)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if let KclValue::HomArray { value, ty } = arr1 {
|
if let KclValue::HomArray { value, ty } = arr1 {
|
||||||
assert_eq!(value.len(), 1, "Expected Vec with specific length: found {:?}", value);
|
assert_eq!(value.len(), 1, "Expected Vec with specific length: found {value:?}");
|
||||||
assert_eq!(*ty, RuntimeType::known_length(UnitLen::Cm));
|
assert_eq!(*ty, RuntimeType::known_length(UnitLen::Cm));
|
||||||
// Compare, ignoring meta.
|
// Compare, ignoring meta.
|
||||||
if let KclValue::Number { value, ty, .. } = &value[0] {
|
if let KclValue::Number { value, ty, .. } = &value[0] {
|
||||||
@ -1946,7 +1960,7 @@ d = b + c
|
|||||||
.await
|
.await
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
KclError::new_internal(KclErrorDetails::new(
|
KclError::new_internal(KclErrorDetails::new(
|
||||||
format!("Failed to create mock engine connection: {}", err),
|
format!("Failed to create mock engine connection: {err}"),
|
||||||
vec![SourceRange::default()],
|
vec![SourceRange::default()],
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
@ -2,19 +2,19 @@ use async_recursion::async_recursion;
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
CompilationError, NodePath,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
|
BodyType, EnvironmentRef, ExecState, ExecutorContext, KclValue, Metadata, StatementKind, TagEngineInfo,
|
||||||
|
TagIdentifier,
|
||||||
cad_op::{Group, OpArg, OpKclValue, Operation},
|
cad_op::{Group, OpArg, OpKclValue, Operation},
|
||||||
kcl_value::FunctionSource,
|
kcl_value::FunctionSource,
|
||||||
memory,
|
memory,
|
||||||
types::RuntimeType,
|
types::RuntimeType,
|
||||||
BodyType, EnvironmentRef, ExecState, ExecutorContext, KclValue, Metadata, StatementKind, TagEngineInfo,
|
|
||||||
TagIdentifier,
|
|
||||||
},
|
},
|
||||||
parsing::ast::types::{CallExpressionKw, DefaultParamVal, FunctionExpression, Node, Program, Type},
|
parsing::ast::types::{CallExpressionKw, DefaultParamVal, FunctionExpression, Node, Program, Type},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
std::StdFn,
|
std::StdFn,
|
||||||
CompilationError, NodePath,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -269,7 +269,7 @@ impl Node<CallExpressionKw> {
|
|||||||
};
|
};
|
||||||
KclError::new_undefined_value(
|
KclError::new_undefined_value(
|
||||||
KclErrorDetails::new(
|
KclErrorDetails::new(
|
||||||
format!("Result of user-defined function {} is undefined", fn_name),
|
format!("Result of user-defined function {fn_name} is undefined"),
|
||||||
source_ranges,
|
source_ranges,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
@ -445,7 +445,7 @@ fn update_memory_for_tags_of_geometry(result: &mut KclValue, exec_state: &mut Ex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KclValue::Solid { ref mut value } => {
|
KclValue::Solid { value } => {
|
||||||
for v in &value.value {
|
for v in &value.value {
|
||||||
if let Some(tag) = v.get_tag() {
|
if let Some(tag) = v.get_tag() {
|
||||||
// Get the past tag and update it.
|
// Get the past tag and update it.
|
||||||
@ -555,9 +555,9 @@ fn type_err_str(expected: &Type, found: &KclValue, source_range: &SourceRange, e
|
|||||||
let found_human = found.human_friendly_type();
|
let found_human = found.human_friendly_type();
|
||||||
let found_ty = found.principal_type_string();
|
let found_ty = found.principal_type_string();
|
||||||
let found_str = if found_human == found_ty || found_human == format!("a {}", strip_backticks(&found_ty)) {
|
let found_str = if found_human == found_ty || found_human == format!("a {}", strip_backticks(&found_ty)) {
|
||||||
format!("a value with type {}", found_ty)
|
format!("a value with type {found_ty}")
|
||||||
} else {
|
} else {
|
||||||
format!("{found_human} (with type {})", found_ty)
|
format!("{found_human} (with type {found_ty})")
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = format!("{expected_str}, but found {found_str}.");
|
let mut result = format!("{expected_str}, but found {found_str}.");
|
||||||
@ -626,7 +626,7 @@ fn type_check_params_kw(
|
|||||||
format!(
|
format!(
|
||||||
"`{label}` is not an argument of {}",
|
"`{label}` is not an argument of {}",
|
||||||
fn_name
|
fn_name
|
||||||
.map(|n| format!("`{}`", n))
|
.map(|n| format!("`{n}`"))
|
||||||
.unwrap_or_else(|| "this function".to_owned()),
|
.unwrap_or_else(|| "this function".to_owned()),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
@ -676,7 +676,7 @@ fn type_check_params_kw(
|
|||||||
format!(
|
format!(
|
||||||
"The input argument of {} requires {}",
|
"The input argument of {} requires {}",
|
||||||
fn_name
|
fn_name
|
||||||
.map(|n| format!("`{}`", n))
|
.map(|n| format!("`{n}`"))
|
||||||
.unwrap_or_else(|| "this function".to_owned()),
|
.unwrap_or_else(|| "this function".to_owned()),
|
||||||
type_err_str(ty, &arg.1.value, &arg.1.source_range, exec_state),
|
type_err_str(ty, &arg.1.value, &arg.1.source_range, exec_state),
|
||||||
),
|
),
|
||||||
@ -691,7 +691,7 @@ fn type_check_params_kw(
|
|||||||
format!(
|
format!(
|
||||||
"{} expects an unlabeled first argument (`@{name}`), but it is labelled in the call",
|
"{} expects an unlabeled first argument (`@{name}`), but it is labelled in the call",
|
||||||
fn_name
|
fn_name
|
||||||
.map(|n| format!("The function `{}`", n))
|
.map(|n| format!("The function `{n}`"))
|
||||||
.unwrap_or_else(|| "This function".to_owned()),
|
.unwrap_or_else(|| "This function".to_owned()),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
@ -721,7 +721,7 @@ fn assign_args_to_params_kw(
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
None => match default {
|
None => match default {
|
||||||
Some(ref default_val) => {
|
Some(default_val) => {
|
||||||
let value = KclValue::from_default_param(default_val.clone(), exec_state);
|
let value = KclValue::from_default_param(default_val.clone(), exec_state);
|
||||||
exec_state
|
exec_state
|
||||||
.mut_stack()
|
.mut_stack()
|
||||||
@ -729,10 +729,7 @@ fn assign_args_to_params_kw(
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
return Err(KclError::new_semantic(KclErrorDetails::new(
|
return Err(KclError::new_semantic(KclErrorDetails::new(
|
||||||
format!(
|
format!("This function requires a parameter {name}, but you haven't passed it one."),
|
||||||
"This function requires a parameter {}, but you haven't passed it one.",
|
|
||||||
name
|
|
||||||
),
|
|
||||||
source_ranges,
|
source_ranges,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -746,7 +743,9 @@ fn assign_args_to_params_kw(
|
|||||||
let Some(unlabeled) = unlabelled else {
|
let Some(unlabeled) = unlabelled else {
|
||||||
return Err(if args.kw_args.labeled.contains_key(param_name) {
|
return Err(if args.kw_args.labeled.contains_key(param_name) {
|
||||||
KclError::new_semantic(KclErrorDetails::new(
|
KclError::new_semantic(KclErrorDetails::new(
|
||||||
format!("The function does declare a parameter named '{param_name}', but this parameter doesn't use a label. Try removing the `{param_name}:`"),
|
format!(
|
||||||
|
"The function does declare a parameter named '{param_name}', but this parameter doesn't use a label. Try removing the `{param_name}:`"
|
||||||
|
),
|
||||||
source_ranges,
|
source_ranges,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
@ -799,7 +798,7 @@ mod test {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
execution::{memory::Stack, parse_execute, types::NumericType, ContextType},
|
execution::{ContextType, memory::Stack, parse_execute, types::NumericType},
|
||||||
parsing::ast::types::{DefaultParamVal, Identifier, Parameter},
|
parsing::ast::types::{DefaultParamVal, Identifier, Parameter},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,16 +3,16 @@ use std::ops::{Add, AddAssign, Mul};
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use kittycad_modeling_cmds::{each_cmd as mcmd, length_unit::LengthUnit, websocket::ModelingCmdReq, ModelingCmd};
|
use kittycad_modeling_cmds::{ModelingCmd, each_cmd as mcmd, length_unit::LengthUnit, websocket::ModelingCmdReq};
|
||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
engine::{PlaneName, DEFAULT_PLANE_INFO},
|
engine::{DEFAULT_PLANE_INFO, PlaneName},
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::NumericType, ArtifactId, ExecState, ExecutorContext, Metadata, TagEngineInfo, TagIdentifier, UnitLen,
|
ArtifactId, ExecState, ExecutorContext, Metadata, TagEngineInfo, TagIdentifier, UnitLen, types::NumericType,
|
||||||
},
|
},
|
||||||
parsing::ast::types::{Node, NodeRef, TagDeclarator, TagNode},
|
parsing::ast::types::{Node, NodeRef, TagDeclarator, TagNode},
|
||||||
std::{args::TyF64, sketch::PlaneData},
|
std::{args::TyF64, sketch::PlaneData},
|
||||||
@ -472,7 +472,7 @@ impl TryFrom<PlaneData> for PlaneInfo {
|
|||||||
PlaneData::Plane(_) => {
|
PlaneData::Plane(_) => {
|
||||||
// We will never get here since we already checked for PlaneData::Plane.
|
// We will never get here since we already checked for PlaneData::Plane.
|
||||||
return Err(KclError::new_internal(KclErrorDetails::new(
|
return Err(KclError::new_internal(KclErrorDetails::new(
|
||||||
format!("PlaneData {:?} not found", value),
|
format!("PlaneData {value:?} not found"),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -480,7 +480,7 @@ impl TryFrom<PlaneData> for PlaneInfo {
|
|||||||
|
|
||||||
let info = DEFAULT_PLANE_INFO.get(&name).ok_or_else(|| {
|
let info = DEFAULT_PLANE_INFO.get(&name).ok_or_else(|| {
|
||||||
KclError::new_internal(KclErrorDetails::new(
|
KclError::new_internal(KclErrorDetails::new(
|
||||||
format!("Plane {} not found", name),
|
format!("Plane {name} not found"),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -815,8 +815,8 @@ impl EdgeCut {
|
|||||||
|
|
||||||
pub fn set_id(&mut self, id: uuid::Uuid) {
|
pub fn set_id(&mut self, id: uuid::Uuid) {
|
||||||
match self {
|
match self {
|
||||||
EdgeCut::Fillet { id: ref mut i, .. } => *i = id,
|
EdgeCut::Fillet { id: i, .. } => *i = id,
|
||||||
EdgeCut::Chamfer { id: ref mut i, .. } => *i = id,
|
EdgeCut::Chamfer { id: i, .. } => *i = id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -829,8 +829,8 @@ impl EdgeCut {
|
|||||||
|
|
||||||
pub fn set_edge_id(&mut self, id: uuid::Uuid) {
|
pub fn set_edge_id(&mut self, id: uuid::Uuid) {
|
||||||
match self {
|
match self {
|
||||||
EdgeCut::Fillet { edge_id: ref mut i, .. } => *i = id,
|
EdgeCut::Fillet { edge_id: i, .. } => *i = id,
|
||||||
EdgeCut::Chamfer { edge_id: ref mut i, .. } => *i = id,
|
EdgeCut::Chamfer { edge_id: i, .. } => *i = id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,12 @@ use std::str::FromStr;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{
|
use kcmc::{
|
||||||
coord::{System, KITTYCAD},
|
ImportFile, ModelingCmd,
|
||||||
|
coord::{KITTYCAD, System},
|
||||||
each_cmd as mcmd,
|
each_cmd as mcmd,
|
||||||
format::InputFormat3d,
|
format::InputFormat3d,
|
||||||
shared::FileImportFormat,
|
shared::FileImportFormat,
|
||||||
units::UnitLength,
|
units::UnitLength,
|
||||||
ImportFile, ModelingCmd,
|
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -16,8 +16,8 @@ use uuid::Uuid;
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
annotations, typed_path::TypedPath, types::UnitLen, ExecState, ExecutorContext, ImportedGeometry,
|
ExecState, ExecutorContext, ImportedGeometry, ModelingCmdMeta, annotations, typed_path::TypedPath,
|
||||||
ModelingCmdMeta,
|
types::UnitLen,
|
||||||
},
|
},
|
||||||
fs::FileSystem,
|
fs::FileSystem,
|
||||||
parsing::ast::types::{Annotation, Node},
|
parsing::ast::types::{Annotation, Node},
|
||||||
@ -184,7 +184,7 @@ pub(super) fn format_from_annotations(
|
|||||||
annotations::IMPORT_LENGTH_UNIT
|
annotations::IMPORT_LENGTH_UNIT
|
||||||
),
|
),
|
||||||
vec![p.as_source_range()],
|
vec![p.as_source_range()],
|
||||||
)))
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,7 +225,7 @@ fn set_coords(fmt: &mut InputFormat3d, coords_str: &str, source_range: SourceRan
|
|||||||
annotations::IMPORT_COORDS
|
annotations::IMPORT_COORDS
|
||||||
),
|
),
|
||||||
vec![source_range],
|
vec![source_range],
|
||||||
)))
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +246,7 @@ fn set_length_unit(fmt: &mut InputFormat3d, units_str: &str, source_range: Sourc
|
|||||||
annotations::IMPORT_LENGTH_UNIT
|
annotations::IMPORT_LENGTH_UNIT
|
||||||
),
|
),
|
||||||
vec![source_range],
|
vec![source_range],
|
||||||
)))
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +291,9 @@ fn get_import_format_from_extension(ext: &str) -> Result<InputFormat3d> {
|
|||||||
} else if ext == "glb" {
|
} else if ext == "glb" {
|
||||||
FileImportFormat::Gltf
|
FileImportFormat::Gltf
|
||||||
} else {
|
} else {
|
||||||
anyhow::bail!("unknown source format for file extension: {ext}. Try setting the `--src-format` flag explicitly or use a valid format.")
|
anyhow::bail!(
|
||||||
|
"unknown source format for file extension: {ext}. Try setting the `--src-format` flag explicitly or use a valid format."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -6,12 +6,12 @@ use std::{
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ExecState, ExecutorContext, KclError, ModuleId, SourceRange,
|
||||||
errors::KclErrorDetails,
|
errors::KclErrorDetails,
|
||||||
execution::typed_path::TypedPath,
|
execution::typed_path::TypedPath,
|
||||||
modules::{ModulePath, ModuleRepr},
|
modules::{ModulePath, ModuleRepr},
|
||||||
parsing::ast::types::{ImportPath, ImportStatement, Node as AstNode},
|
parsing::ast::types::{ImportPath, ImportStatement, Node as AstNode},
|
||||||
walk::{Node, Visitable},
|
walk::{Node, Visitable},
|
||||||
ExecState, ExecutorContext, KclError, ModuleId, SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Specific dependency between two modules. The 0th element of this info
|
/// Specific dependency between two modules. The 0th element of this info
|
||||||
@ -147,7 +147,7 @@ fn import_dependencies(
|
|||||||
ret.lock()
|
ret.lock()
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
KclError::new_internal(KclErrorDetails::new(
|
KclError::new_internal(KclErrorDetails::new(
|
||||||
format!("Failed to lock mutex: {}", err),
|
format!("Failed to lock mutex: {err}"),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
))
|
))
|
||||||
})?
|
})?
|
||||||
@ -157,7 +157,7 @@ fn import_dependencies(
|
|||||||
ret.lock()
|
ret.lock()
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
KclError::new_internal(KclErrorDetails::new(
|
KclError::new_internal(KclErrorDetails::new(
|
||||||
format!("Failed to lock mutex: {}", err),
|
format!("Failed to lock mutex: {err}"),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
))
|
))
|
||||||
})?
|
})?
|
||||||
@ -179,7 +179,7 @@ fn import_dependencies(
|
|||||||
|
|
||||||
let ret = ret.lock().map_err(|err| {
|
let ret = ret.lock().map_err(|err| {
|
||||||
KclError::new_internal(KclErrorDetails::new(
|
KclError::new_internal(KclErrorDetails::new(
|
||||||
format!("Failed to lock mutex: {}", err),
|
format!("Failed to lock mutex: {err}"),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -224,7 +224,7 @@ pub(crate) async fn import_universe(
|
|||||||
let repr = {
|
let repr = {
|
||||||
let Some(module_info) = exec_state.get_module(module_id) else {
|
let Some(module_info) = exec_state.get_module(module_id) else {
|
||||||
return Err(KclError::new_internal(KclErrorDetails::new(
|
return Err(KclError::new_internal(KclErrorDetails::new(
|
||||||
format!("Module {} not found", module_id),
|
format!("Module {module_id} not found"),
|
||||||
vec![import_stmt.into()],
|
vec![import_stmt.into()],
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
@ -244,9 +244,7 @@ mod tests {
|
|||||||
use crate::parsing::ast::types::{ImportSelector, Program};
|
use crate::parsing::ast::types::{ImportSelector, Program};
|
||||||
|
|
||||||
macro_rules! kcl {
|
macro_rules! kcl {
|
||||||
( $kcl:expr ) => {{
|
( $kcl:expr_2021 ) => {{ $crate::parsing::top_level_parse($kcl).unwrap() }};
|
||||||
$crate::parsing::top_level_parse($kcl).unwrap()
|
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_module_info(program: AstNode<Program>) -> DependencyInfo {
|
fn into_module_info(program: AstNode<Program>) -> DependencyInfo {
|
||||||
|
@ -5,18 +5,18 @@ use schemars::JsonSchema;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
CompilationError, KclError, ModuleId, SourceRange,
|
||||||
errors::KclErrorDetails,
|
errors::KclErrorDetails,
|
||||||
execution::{
|
execution::{
|
||||||
annotations::{SETTINGS, SETTINGS_UNIT_LENGTH},
|
|
||||||
types::{NumericType, PrimitiveType, RuntimeType, UnitLen},
|
|
||||||
EnvironmentRef, ExecState, Face, Geometry, GeometryWithImportedGeometry, Helix, ImportedGeometry, MetaSettings,
|
EnvironmentRef, ExecState, Face, Geometry, GeometryWithImportedGeometry, Helix, ImportedGeometry, MetaSettings,
|
||||||
Metadata, Plane, Sketch, Solid, TagIdentifier,
|
Metadata, Plane, Sketch, Solid, TagIdentifier,
|
||||||
|
annotations::{SETTINGS, SETTINGS_UNIT_LENGTH},
|
||||||
|
types::{NumericType, PrimitiveType, RuntimeType, UnitLen},
|
||||||
},
|
},
|
||||||
parsing::ast::types::{
|
parsing::ast::types::{
|
||||||
DefaultParamVal, FunctionExpression, KclNone, Literal, LiteralValue, Node, TagDeclarator, TagNode,
|
DefaultParamVal, FunctionExpression, KclNone, Literal, LiteralValue, Node, TagDeclarator, TagNode,
|
||||||
},
|
},
|
||||||
std::{args::TyF64, StdFnProps},
|
std::{StdFnProps, args::TyF64},
|
||||||
CompilationError, KclError, ModuleId, SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type KclObjectFields = HashMap<String, KclValue>;
|
pub type KclObjectFields = HashMap<String, KclValue>;
|
||||||
@ -136,9 +136,9 @@ impl JsonSchema for FunctionSource {
|
|||||||
"FunctionSource".to_owned()
|
"FunctionSource".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||||
// TODO: Actually generate a reasonable schema.
|
// TODO: Actually generate a reasonable schema.
|
||||||
gen.subschema_for::<()>()
|
r#gen.subschema_for::<()>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,7 +587,7 @@ impl KclValue {
|
|||||||
match self {
|
match self {
|
||||||
KclValue::TagIdentifier(t) => Ok(*t.clone()),
|
KclValue::TagIdentifier(t) => Ok(*t.clone()),
|
||||||
_ => Err(KclError::new_semantic(KclErrorDetails::new(
|
_ => Err(KclError::new_semantic(KclErrorDetails::new(
|
||||||
format!("Not a tag identifier: {:?}", self),
|
format!("Not a tag identifier: {self:?}"),
|
||||||
self.clone().into(),
|
self.clone().into(),
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
@ -598,7 +598,7 @@ impl KclValue {
|
|||||||
match self {
|
match self {
|
||||||
KclValue::TagDeclarator(t) => Ok((**t).clone()),
|
KclValue::TagDeclarator(t) => Ok((**t).clone()),
|
||||||
_ => Err(KclError::new_semantic(KclErrorDetails::new(
|
_ => Err(KclError::new_semantic(KclErrorDetails::new(
|
||||||
format!("Not a tag declarator: {:?}", self),
|
format!("Not a tag declarator: {self:?}"),
|
||||||
self.clone().into(),
|
self.clone().into(),
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
|
@ -207,8 +207,8 @@ use std::{
|
|||||||
fmt,
|
fmt,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
|
||||||
Arc,
|
Arc,
|
||||||
|
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -489,7 +489,7 @@ impl ProgramMemory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Err(KclError::new_undefined_value(
|
Err(KclError::new_undefined_value(
|
||||||
KclErrorDetails::new(format!("`{}` is not defined", var), vec![]),
|
KclErrorDetails::new(format!("`{var}` is not defined"), vec![]),
|
||||||
Some(var.to_owned()),
|
Some(var.to_owned()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -647,7 +647,7 @@ impl Stack {
|
|||||||
let env = self.memory.get_env(self.current_env.index());
|
let env = self.memory.get_env(self.current_env.index());
|
||||||
if env.contains_key(&key) {
|
if env.contains_key(&key) {
|
||||||
return Err(KclError::new_value_already_defined(KclErrorDetails::new(
|
return Err(KclError::new_value_already_defined(KclErrorDetails::new(
|
||||||
format!("Cannot redefine `{}`", key),
|
format!("Cannot redefine `{key}`"),
|
||||||
vec![source_range],
|
vec![source_range],
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -1047,7 +1047,7 @@ mod env {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Take all bindings from the environment.
|
/// Take all bindings from the environment.
|
||||||
pub(super) fn take_bindings(self: Pin<&mut Self>) -> impl Iterator<Item = (String, (usize, KclValue))> {
|
pub(super) fn take_bindings(self: Pin<&mut Self>) -> impl Iterator<Item = (String, (usize, KclValue))> + use<> {
|
||||||
// SAFETY: caller must have unique access since self is mut. We're not moving or invalidating `self`.
|
// SAFETY: caller must have unique access since self is mut. We're not moving or invalidating `self`.
|
||||||
let bindings = std::mem::take(unsafe { self.bindings.get().as_mut().unwrap() });
|
let bindings = std::mem::take(unsafe { self.bindings.get().as_mut().unwrap() });
|
||||||
bindings.into_iter()
|
bindings.into_iter()
|
||||||
|
@ -16,10 +16,9 @@ pub(crate) use import::PreImportedGeometry;
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
pub use kcl_value::{KclObjectFields, KclValue};
|
pub use kcl_value::{KclObjectFields, KclValue};
|
||||||
use kcmc::{
|
use kcmc::{
|
||||||
each_cmd as mcmd,
|
ImageFormat, ModelingCmd, each_cmd as mcmd,
|
||||||
ok_response::{output::TakeSnapshot, OkModelingCmdResponse},
|
ok_response::{OkModelingCmdResponse, output::TakeSnapshot},
|
||||||
websocket::{ModelingSessionData, OkWebSocketResponseData},
|
websocket::{ModelingSessionData, OkWebSocketResponseData},
|
||||||
ImageFormat, ModelingCmd,
|
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds::{self as kcmc, id::ModelingCmdId};
|
use kittycad_modeling_cmds::{self as kcmc, id::ModelingCmdId};
|
||||||
pub use memory::EnvironmentRef;
|
pub use memory::EnvironmentRef;
|
||||||
@ -31,6 +30,7 @@ pub use state::{ExecState, MetaSettings};
|
|||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
CompilationError, ExecError, KclErrorWithOutputs,
|
||||||
engine::{EngineManager, GridScaleBehavior},
|
engine::{EngineManager, GridScaleBehavior},
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
@ -43,7 +43,6 @@ use crate::{
|
|||||||
modules::{ModuleId, ModulePath, ModuleRepr},
|
modules::{ModuleId, ModulePath, ModuleRepr},
|
||||||
parsing::ast::types::{Expr, ImportPath, NodeRef},
|
parsing::ast::types::{Expr, ImportPath, NodeRef},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
CompilationError, ExecError, KclErrorWithOutputs,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) mod annotations;
|
pub(crate) mod annotations;
|
||||||
@ -1329,7 +1328,7 @@ impl ExecutorContext {
|
|||||||
created: if deterministic_time {
|
created: if deterministic_time {
|
||||||
Some("2021-01-01T00:00:00Z".parse().map_err(|e| {
|
Some("2021-01-01T00:00:00Z".parse().map_err(|e| {
|
||||||
KclError::new_internal(crate::errors::KclErrorDetails::new(
|
KclError::new_internal(crate::errors::KclErrorDetails::new(
|
||||||
format!("Failed to parse date: {}", e),
|
format!("Failed to parse date: {e}"),
|
||||||
vec![SourceRange::default()],
|
vec![SourceRange::default()],
|
||||||
))
|
))
|
||||||
})?)
|
})?)
|
||||||
@ -1409,7 +1408,7 @@ pub(crate) async fn parse_execute_with_project_dir(
|
|||||||
engine: Arc::new(Box::new(
|
engine: Arc::new(Box::new(
|
||||||
crate::engine::conn_mock::EngineConnection::new().await.map_err(|err| {
|
crate::engine::conn_mock::EngineConnection::new().await.map_err(|err| {
|
||||||
KclError::new_internal(crate::errors::KclErrorDetails::new(
|
KclError::new_internal(crate::errors::KclErrorDetails::new(
|
||||||
format!("Failed to create mock engine connection: {}", err),
|
format!("Failed to create mock engine connection: {err}"),
|
||||||
vec![SourceRange::default()],
|
vec![SourceRange::default()],
|
||||||
))
|
))
|
||||||
})?,
|
})?,
|
||||||
@ -1446,7 +1445,7 @@ mod tests {
|
|||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{errors::KclErrorDetails, execution::memory::Stack, ModuleId};
|
use crate::{ModuleId, errors::KclErrorDetails, execution::memory::Stack};
|
||||||
|
|
||||||
/// Convenience function to get a JSON value from memory and unwrap.
|
/// Convenience function to get a JSON value from memory and unwrap.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
@ -2045,8 +2044,7 @@ notFunction = !x";
|
|||||||
fn_err
|
fn_err
|
||||||
.message()
|
.message()
|
||||||
.starts_with("Cannot apply unary operator ! to non-boolean value: "),
|
.starts_with("Cannot apply unary operator ! to non-boolean value: "),
|
||||||
"Actual error: {:?}",
|
"Actual error: {fn_err:?}"
|
||||||
fn_err
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let code8 = "
|
let code8 = "
|
||||||
@ -2059,8 +2057,7 @@ notTagDeclarator = !myTagDeclarator";
|
|||||||
tag_declarator_err
|
tag_declarator_err
|
||||||
.message()
|
.message()
|
||||||
.starts_with("Cannot apply unary operator ! to non-boolean value: a tag declarator"),
|
.starts_with("Cannot apply unary operator ! to non-boolean value: a tag declarator"),
|
||||||
"Actual error: {:?}",
|
"Actual error: {tag_declarator_err:?}"
|
||||||
tag_declarator_err
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let code9 = "
|
let code9 = "
|
||||||
@ -2073,8 +2070,7 @@ notTagIdentifier = !myTag";
|
|||||||
tag_identifier_err
|
tag_identifier_err
|
||||||
.message()
|
.message()
|
||||||
.starts_with("Cannot apply unary operator ! to non-boolean value: a tag identifier"),
|
.starts_with("Cannot apply unary operator ! to non-boolean value: a tag identifier"),
|
||||||
"Actual error: {:?}",
|
"Actual error: {tag_identifier_err:?}"
|
||||||
tag_identifier_err
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let code10 = "notPipe = !(1 |> 2)";
|
let code10 = "notPipe = !(1 |> 2)";
|
||||||
@ -2226,7 +2222,7 @@ w = f() + f()
|
|||||||
if let Err(err) = ctx.run_with_caching(old_program).await {
|
if let Err(err) = ctx.run_with_caching(old_program).await {
|
||||||
let report = err.into_miette_report_with_outputs(code).unwrap();
|
let report = err.into_miette_report_with_outputs(code).unwrap();
|
||||||
let report = miette::Report::new(report);
|
let report = miette::Report::new(report);
|
||||||
panic!("Error executing program: {:?}", report);
|
panic!("Error executing program: {report:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the id_generator from the first execution.
|
// Get the id_generator from the first execution.
|
||||||
|
@ -8,10 +8,10 @@ use uuid::Uuid;
|
|||||||
#[cfg(feature = "artifact-graph")]
|
#[cfg(feature = "artifact-graph")]
|
||||||
use crate::exec::ArtifactCommand;
|
use crate::exec::ArtifactCommand;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ExecState, ExecutorContext, KclError, SourceRange,
|
||||||
exec::{IdGenerator, KclValue},
|
exec::{IdGenerator, KclValue},
|
||||||
execution::Solid,
|
execution::Solid,
|
||||||
std::Args,
|
std::Args,
|
||||||
ExecState, ExecutorContext, KclError, SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Context and metadata needed to send a single modeling command.
|
/// Context and metadata needed to send a single modeling command.
|
||||||
|
@ -9,20 +9,19 @@ use uuid::Uuid;
|
|||||||
#[cfg(feature = "artifact-graph")]
|
#[cfg(feature = "artifact-graph")]
|
||||||
use crate::execution::{Artifact, ArtifactCommand, ArtifactGraph, ArtifactId};
|
use crate::execution::{Artifact, ArtifactCommand, ArtifactGraph, ArtifactId};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
CompilationError, EngineManager, ExecutorContext, KclErrorWithOutputs,
|
||||||
errors::{KclError, KclErrorDetails, Severity},
|
errors::{KclError, KclErrorDetails, Severity},
|
||||||
exec::DefaultPlanes,
|
exec::DefaultPlanes,
|
||||||
execution::{
|
execution::{
|
||||||
annotations,
|
EnvironmentRef, ExecOutcome, ExecutorSettings, KclValue, UnitAngle, UnitLen, annotations,
|
||||||
cad_op::Operation,
|
cad_op::Operation,
|
||||||
id_generator::IdGenerator,
|
id_generator::IdGenerator,
|
||||||
memory::{ProgramMemory, Stack},
|
memory::{ProgramMemory, Stack},
|
||||||
types::{self, NumericType},
|
types::{self, NumericType},
|
||||||
EnvironmentRef, ExecOutcome, ExecutorSettings, KclValue, UnitAngle, UnitLen,
|
|
||||||
},
|
},
|
||||||
modules::{ModuleId, ModuleInfo, ModuleLoader, ModulePath, ModuleRepr, ModuleSource},
|
modules::{ModuleId, ModuleInfo, ModuleLoader, ModulePath, ModuleRepr, ModuleSource},
|
||||||
parsing::ast::types::{Annotation, NodeRef},
|
parsing::ast::types::{Annotation, NodeRef},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
CompilationError, EngineManager, ExecutorContext, KclErrorWithOutputs,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// State for executing a program.
|
/// State for executing a program.
|
||||||
@ -555,7 +554,7 @@ impl MetaSettings {
|
|||||||
annotations::SETTINGS_UNIT_ANGLE
|
annotations::SETTINGS_UNIT_ANGLE
|
||||||
),
|
),
|
||||||
vec![annotation.as_source_range()],
|
vec![annotation.as_source_range()],
|
||||||
)))
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,9 +220,9 @@ impl schemars::JsonSchema for TypedPath {
|
|||||||
"TypedPath".to_owned()
|
"TypedPath".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||||
// TODO: Actually generate a reasonable schema.
|
// TODO: Actually generate a reasonable schema.
|
||||||
gen.subschema_for::<std::path::PathBuf>()
|
r#gen.subschema_for::<std::path::PathBuf>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,17 +5,17 @@ use schemars::JsonSchema;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
CompilationError, SourceRange,
|
||||||
execution::{
|
execution::{
|
||||||
|
ExecState, Plane, PlaneInfo, Point3d,
|
||||||
kcl_value::{KclValue, TypeDef},
|
kcl_value::{KclValue, TypeDef},
|
||||||
memory::{self},
|
memory::{self},
|
||||||
ExecState, Plane, PlaneInfo, Point3d,
|
|
||||||
},
|
},
|
||||||
parsing::{
|
parsing::{
|
||||||
ast::types::{PrimitiveType as AstPrimitiveType, Type},
|
ast::types::{PrimitiveType as AstPrimitiveType, Type},
|
||||||
token::NumericSuffix,
|
token::NumericSuffix,
|
||||||
},
|
},
|
||||||
std::args::{FromKclValue, TyF64},
|
std::args::{FromKclValue, TyF64},
|
||||||
CompilationError, SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
@ -210,7 +210,7 @@ impl RuntimeType {
|
|||||||
let ty_val = exec_state
|
let ty_val = exec_state
|
||||||
.stack()
|
.stack()
|
||||||
.get(&format!("{}{}", memory::TYPE_PREFIX, alias), source_range)
|
.get(&format!("{}{}", memory::TYPE_PREFIX, alias), source_range)
|
||||||
.map_err(|_| CompilationError::err(source_range, format!("Unknown type: {}", alias)))?;
|
.map_err(|_| CompilationError::err(source_range, format!("Unknown type: {alias}")))?;
|
||||||
|
|
||||||
Ok(match ty_val {
|
Ok(match ty_val {
|
||||||
KclValue::Type { value, .. } => match value {
|
KclValue::Type { value, .. } => match value {
|
||||||
@ -241,7 +241,7 @@ impl RuntimeType {
|
|||||||
"a tuple with values of types ({})",
|
"a tuple with values of types ({})",
|
||||||
tys.iter().map(Self::human_friendly_type).collect::<Vec<_>>().join(", ")
|
tys.iter().map(Self::human_friendly_type).collect::<Vec<_>>().join(", ")
|
||||||
),
|
),
|
||||||
RuntimeType::Object(_) => format!("an object with fields {}", self),
|
RuntimeType::Object(_) => format!("an object with fields {self}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1529,7 +1529,7 @@ impl KclValue {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::execution::{parse_execute, ExecTestResults};
|
use crate::execution::{ExecTestResults, parse_execute};
|
||||||
|
|
||||||
fn values(exec_state: &mut ExecState) -> Vec<KclValue> {
|
fn values(exec_state: &mut ExecState) -> Vec<KclValue> {
|
||||||
vec![
|
vec![
|
||||||
@ -1975,14 +1975,16 @@ mod test {
|
|||||||
])
|
])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert!(RuntimeType::Union(vec![
|
assert!(
|
||||||
|
RuntimeType::Union(vec![
|
||||||
RuntimeType::Primitive(PrimitiveType::Number(NumericType::Any)),
|
RuntimeType::Primitive(PrimitiveType::Number(NumericType::Any)),
|
||||||
RuntimeType::Primitive(PrimitiveType::Boolean)
|
RuntimeType::Primitive(PrimitiveType::Boolean)
|
||||||
])
|
])
|
||||||
.subtype(&RuntimeType::Union(vec![
|
.subtype(&RuntimeType::Union(vec![
|
||||||
RuntimeType::Primitive(PrimitiveType::Number(NumericType::Any)),
|
RuntimeType::Primitive(PrimitiveType::Number(NumericType::Any)),
|
||||||
RuntimeType::Primitive(PrimitiveType::Boolean)
|
RuntimeType::Primitive(PrimitiveType::Boolean)
|
||||||
])));
|
]))
|
||||||
|
);
|
||||||
|
|
||||||
// Covariance
|
// Covariance
|
||||||
let count = KclValue::Number {
|
let count = KclValue::Number {
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
SourceRange,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::typed_path::TypedPath,
|
execution::typed_path::TypedPath,
|
||||||
fs::FileSystem,
|
fs::FileSystem,
|
||||||
SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::{execution::typed_path::TypedPath, SourceRange};
|
use crate::{SourceRange, execution::typed_path::TypedPath};
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub mod local;
|
pub mod local;
|
||||||
|
@ -4,11 +4,11 @@ use anyhow::Result;
|
|||||||
use wasm_bindgen::prelude::wasm_bindgen;
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
SourceRange,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::typed_path::TypedPath,
|
execution::typed_path::TypedPath,
|
||||||
fs::FileSystem,
|
fs::FileSystem,
|
||||||
wasm::JsFuture,
|
wasm::JsFuture,
|
||||||
SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[wasm_bindgen(module = "/../../src/lang/std/fileSystemManager.ts")]
|
#[wasm_bindgen(module = "/../../src/lang/std/fileSystemManager.ts")]
|
||||||
|
@ -90,10 +90,9 @@ pub use errors::{
|
|||||||
ReportWithOutputs,
|
ReportWithOutputs,
|
||||||
};
|
};
|
||||||
pub use execution::{
|
pub use execution::{
|
||||||
bust_cache, clear_mem_cache,
|
ExecOutcome, ExecState, ExecutorContext, ExecutorSettings, MetaSettings, Point2d, bust_cache, clear_mem_cache,
|
||||||
typed_path::TypedPath,
|
typed_path::TypedPath,
|
||||||
types::{UnitAngle, UnitLen},
|
types::{UnitAngle, UnitLen},
|
||||||
ExecOutcome, ExecState, ExecutorContext, ExecutorSettings, MetaSettings, Point2d,
|
|
||||||
};
|
};
|
||||||
pub use lsp::{
|
pub use lsp::{
|
||||||
copilot::Backend as CopilotLspBackend,
|
copilot::Backend as CopilotLspBackend,
|
||||||
@ -101,7 +100,7 @@ pub use lsp::{
|
|||||||
};
|
};
|
||||||
pub use modules::ModuleId;
|
pub use modules::ModuleId;
|
||||||
pub use parsing::ast::types::{FormatOptions, NodePath, Step as NodePathStep};
|
pub use parsing::ast::types::{FormatOptions, NodePath, Step as NodePathStep};
|
||||||
pub use settings::types::{project::ProjectConfiguration, Configuration, UnitLength};
|
pub use settings::types::{Configuration, UnitLength, project::ProjectConfiguration};
|
||||||
pub use source_range::SourceRange;
|
pub use source_range::SourceRange;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub use unparser::{recast_dir, walk_dir};
|
pub use unparser::{recast_dir, walk_dir};
|
||||||
@ -109,12 +108,12 @@ pub use unparser::{recast_dir, walk_dir};
|
|||||||
// Rather than make executor public and make lots of it pub(crate), just re-export into a new module.
|
// Rather than make executor public and make lots of it pub(crate), just re-export into a new module.
|
||||||
// Ideally we wouldn't export these things at all, they should only be used for testing.
|
// Ideally we wouldn't export these things at all, they should only be used for testing.
|
||||||
pub mod exec {
|
pub mod exec {
|
||||||
pub use crate::execution::{
|
|
||||||
types::{NumericType, UnitAngle, UnitLen, UnitType},
|
|
||||||
DefaultPlanes, IdGenerator, KclValue, PlaneType, Sketch,
|
|
||||||
};
|
|
||||||
#[cfg(feature = "artifact-graph")]
|
#[cfg(feature = "artifact-graph")]
|
||||||
pub use crate::execution::{ArtifactCommand, Operation};
|
pub use crate::execution::{ArtifactCommand, Operation};
|
||||||
|
pub use crate::execution::{
|
||||||
|
DefaultPlanes, IdGenerator, KclValue, PlaneType, Sketch,
|
||||||
|
types::{NumericType, UnitAngle, UnitLen, UnitType},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
@ -136,7 +135,7 @@ pub mod native_engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod std_utils {
|
pub mod std_utils {
|
||||||
pub use crate::std::utils::{get_tangential_arc_to_info, is_points_ccw_wasm, TangentialArcInfoInput};
|
pub use crate::std::utils::{TangentialArcInfoInput, get_tangential_arc_to_info, is_points_ccw_wasm};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod pretty {
|
pub mod pretty {
|
||||||
@ -160,7 +159,7 @@ lazy_static::lazy_static! {
|
|||||||
#[cfg(feature = "cli")]
|
#[cfg(feature = "cli")]
|
||||||
let named_extensions = kittycad::types::FileImportFormat::value_variants()
|
let named_extensions = kittycad::types::FileImportFormat::value_variants()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| format!("{}", x))
|
.map(|x| format!("{x}"))
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
#[cfg(not(feature = "cli"))]
|
#[cfg(not(feature = "cli"))]
|
||||||
let named_extensions = vec![]; // We don't really need this outside of the CLI.
|
let named_extensions = vec![]; // We don't really need this outside of the CLI.
|
||||||
@ -276,41 +275,25 @@ impl Program {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn try_f64_to_usize(f: f64) -> Option<usize> {
|
fn try_f64_to_usize(f: f64) -> Option<usize> {
|
||||||
let i = f as usize;
|
let i = f as usize;
|
||||||
if i as f64 == f {
|
if i as f64 == f { Some(i) } else { None }
|
||||||
Some(i)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_f64_to_u32(f: f64) -> Option<u32> {
|
fn try_f64_to_u32(f: f64) -> Option<u32> {
|
||||||
let i = f as u32;
|
let i = f as u32;
|
||||||
if i as f64 == f {
|
if i as f64 == f { Some(i) } else { None }
|
||||||
Some(i)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_f64_to_u64(f: f64) -> Option<u64> {
|
fn try_f64_to_u64(f: f64) -> Option<u64> {
|
||||||
let i = f as u64;
|
let i = f as u64;
|
||||||
if i as f64 == f {
|
if i as f64 == f { Some(i) } else { None }
|
||||||
Some(i)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_f64_to_i64(f: f64) -> Option<i64> {
|
fn try_f64_to_i64(f: f64) -> Option<i64> {
|
||||||
let i = f as i64;
|
let i = f as i64;
|
||||||
if i as f64 == f {
|
if i as f64 == f { Some(i) } else { None }
|
||||||
Some(i)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the version of the KCL library.
|
/// Get the version of the KCL library.
|
||||||
|
@ -2,11 +2,11 @@ use anyhow::Result;
|
|||||||
use convert_case::Casing;
|
use convert_case::Casing;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
SourceRange,
|
||||||
errors::Suggestion,
|
errors::Suggestion,
|
||||||
lint::rule::{def_finding, Discovered, Finding},
|
lint::rule::{Discovered, Finding, def_finding},
|
||||||
parsing::ast::types::{Node as AstNode, ObjectProperty, Program, VariableDeclarator},
|
parsing::ast::types::{Node as AstNode, ObjectProperty, Program, VariableDeclarator},
|
||||||
walk::Node,
|
walk::Node,
|
||||||
SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
def_finding!(
|
def_finding!(
|
||||||
@ -38,12 +38,12 @@ fn lint_lower_camel_case_var(decl: &VariableDeclarator, prog: &AstNode<Program>)
|
|||||||
let recast = prog.recast(&Default::default(), 0);
|
let recast = prog.recast(&Default::default(), 0);
|
||||||
|
|
||||||
let suggestion = Suggestion {
|
let suggestion = Suggestion {
|
||||||
title: format!("rename '{}' to '{}'", name, new_name),
|
title: format!("rename '{name}' to '{new_name}'"),
|
||||||
insert: recast,
|
insert: recast,
|
||||||
source_range: prog.as_source_range(),
|
source_range: prog.as_source_range(),
|
||||||
};
|
};
|
||||||
findings.push(Z0001.at(
|
findings.push(Z0001.at(
|
||||||
format!("found '{}'", name),
|
format!("found '{name}'"),
|
||||||
SourceRange::new(ident.start, ident.end, ident.module_id),
|
SourceRange::new(ident.start, ident.end, ident.module_id),
|
||||||
Some(suggestion.clone()),
|
Some(suggestion.clone()),
|
||||||
));
|
));
|
||||||
@ -61,7 +61,7 @@ fn lint_lower_camel_case_property(decl: &ObjectProperty, _prog: &AstNode<Program
|
|||||||
if !name.is_case(convert_case::Case::Camel) {
|
if !name.is_case(convert_case::Case::Camel) {
|
||||||
// We can't rename the properties yet.
|
// We can't rename the properties yet.
|
||||||
findings.push(Z0001.at(
|
findings.push(Z0001.at(
|
||||||
format!("found '{}'", name),
|
format!("found '{name}'"),
|
||||||
SourceRange::new(ident.start, ident.end, ident.module_id),
|
SourceRange::new(ident.start, ident.end, ident.module_id),
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
@ -93,7 +93,7 @@ pub fn lint_object_properties(decl: Node, prog: &AstNode<Program>) -> Result<Vec
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{lint_object_properties, lint_variables, Z0001};
|
use super::{Z0001, lint_object_properties, lint_variables};
|
||||||
use crate::lint::rule::{assert_finding, test_finding, test_no_finding};
|
use crate::lint::rule::{assert_finding, test_finding, test_no_finding};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
errors::Suggestion,
|
errors::Suggestion,
|
||||||
lint::{
|
lint::{
|
||||||
checks::offset_plane::start_sketch_on_check_specific_plane,
|
checks::offset_plane::start_sketch_on_check_specific_plane,
|
||||||
rule::{def_finding, Discovered, Finding},
|
rule::{Discovered, Finding, def_finding},
|
||||||
},
|
},
|
||||||
parsing::ast::types::{Node as AstNode, Program},
|
parsing::ast::types::{Node as AstNode, Program},
|
||||||
walk::Node,
|
walk::Node,
|
||||||
@ -33,14 +33,11 @@ pub fn lint_should_be_default_plane(node: Node, _prog: &AstNode<Program>) -> Res
|
|||||||
}
|
}
|
||||||
let suggestion = Suggestion {
|
let suggestion = Suggestion {
|
||||||
title: "use defaultPlane instead".to_owned(),
|
title: "use defaultPlane instead".to_owned(),
|
||||||
insert: format!("{}", plane_name),
|
insert: format!("{plane_name}"),
|
||||||
source_range: call_source_range,
|
source_range: call_source_range,
|
||||||
};
|
};
|
||||||
Ok(vec![Z0002.at(
|
Ok(vec![Z0002.at(
|
||||||
format!(
|
format!("custom plane in startSketchOn; defaultPlane {plane_name} would work here"),
|
||||||
"custom plane in startSketchOn; defaultPlane {} would work here",
|
|
||||||
plane_name
|
|
||||||
),
|
|
||||||
call_source_range,
|
call_source_range,
|
||||||
Some(suggestion),
|
Some(suggestion),
|
||||||
)])
|
)])
|
||||||
@ -48,7 +45,7 @@ pub fn lint_should_be_default_plane(node: Node, _prog: &AstNode<Program>) -> Res
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{lint_should_be_default_plane, Z0002};
|
use super::{Z0002, lint_should_be_default_plane};
|
||||||
use crate::lint::rule::{test_finding, test_no_finding};
|
use crate::lint::rule::{test_finding, test_no_finding};
|
||||||
|
|
||||||
test_finding!(
|
test_finding!(
|
||||||
|
@ -2,6 +2,6 @@ mod camel_case;
|
|||||||
mod default_plane;
|
mod default_plane;
|
||||||
mod offset_plane;
|
mod offset_plane;
|
||||||
|
|
||||||
pub use camel_case::{lint_object_properties, lint_variables, Z0001};
|
pub use camel_case::{Z0001, lint_object_properties, lint_variables};
|
||||||
pub use default_plane::{lint_should_be_default_plane, Z0002};
|
pub use default_plane::{Z0002, lint_should_be_default_plane};
|
||||||
pub use offset_plane::{lint_should_be_offset_plane, Z0003};
|
pub use offset_plane::{Z0003, lint_should_be_offset_plane};
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
engine::{PlaneName, DEFAULT_PLANE_INFO},
|
SourceRange,
|
||||||
|
engine::{DEFAULT_PLANE_INFO, PlaneName},
|
||||||
errors::Suggestion,
|
errors::Suggestion,
|
||||||
execution::{types::UnitLen, PlaneInfo, Point3d},
|
execution::{PlaneInfo, Point3d, types::UnitLen},
|
||||||
lint::rule::{def_finding, Discovered, Finding},
|
lint::rule::{Discovered, Finding, def_finding},
|
||||||
parsing::ast::types::{
|
parsing::ast::types::{
|
||||||
BinaryPart, CallExpressionKw, Expr, LiteralValue, Node as AstNode, ObjectExpression, Program, UnaryOperator,
|
BinaryPart, CallExpressionKw, Expr, LiteralValue, Node as AstNode, ObjectExpression, Program, UnaryOperator,
|
||||||
},
|
},
|
||||||
walk::Node,
|
walk::Node,
|
||||||
SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
def_finding!(
|
def_finding!(
|
||||||
@ -39,14 +39,11 @@ pub fn lint_should_be_offset_plane(node: Node, _prog: &AstNode<Program>) -> Resu
|
|||||||
}
|
}
|
||||||
let suggestion = Suggestion {
|
let suggestion = Suggestion {
|
||||||
title: "use offsetPlane instead".to_owned(),
|
title: "use offsetPlane instead".to_owned(),
|
||||||
insert: format!("offsetPlane({}, offset = {})", plane_name, offset),
|
insert: format!("offsetPlane({plane_name}, offset = {offset})"),
|
||||||
source_range: call_source_range,
|
source_range: call_source_range,
|
||||||
};
|
};
|
||||||
Ok(vec![Z0003.at(
|
Ok(vec![Z0003.at(
|
||||||
format!(
|
format!("custom plane in startSketchOn; offsetPlane from {plane_name} would work here"),
|
||||||
"custom plane in startSketchOn; offsetPlane from {} would work here",
|
|
||||||
plane_name
|
|
||||||
),
|
|
||||||
call_source_range,
|
call_source_range,
|
||||||
Some(suggestion),
|
Some(suggestion),
|
||||||
)])
|
)])
|
||||||
@ -68,16 +65,16 @@ fn get_xyz(point: &ObjectExpression) -> Option<(f64, f64, f64)> {
|
|||||||
|
|
||||||
for property in &point.properties {
|
for property in &point.properties {
|
||||||
let Some(value) = (match &property.value {
|
let Some(value) = (match &property.value {
|
||||||
Expr::UnaryExpression(ref value) => {
|
Expr::UnaryExpression(value) => {
|
||||||
if value.operator != UnaryOperator::Neg {
|
if value.operator != UnaryOperator::Neg {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let BinaryPart::Literal(ref value) = &value.inner.argument else {
|
let BinaryPart::Literal(value) = &value.inner.argument else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
unlitafy(&value.inner.value).map(|v| -v)
|
unlitafy(&value.inner.value).map(|v| -v)
|
||||||
}
|
}
|
||||||
Expr::Literal(ref value) => unlitafy(&value.value),
|
Expr::Literal(value) => unlitafy(&value.value),
|
||||||
_ => {
|
_ => {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -271,7 +268,7 @@ fn normalize_plane_info(plane_info: &PlaneInfo) -> PlaneInfo {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{lint_should_be_offset_plane, Z0003};
|
use super::{Z0003, lint_should_be_offset_plane};
|
||||||
use crate::lint::rule::{test_finding, test_no_finding};
|
use crate::lint::rule::{test_finding, test_no_finding};
|
||||||
|
|
||||||
test_finding!(
|
test_finding!(
|
||||||
|
@ -4,11 +4,11 @@ use serde::Serialize;
|
|||||||
use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
|
use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
SourceRange,
|
||||||
errors::Suggestion,
|
errors::Suggestion,
|
||||||
lsp::IntoDiagnostic,
|
lsp::IntoDiagnostic,
|
||||||
parsing::ast::types::{Node as AstNode, Program},
|
parsing::ast::types::{Node as AstNode, Program},
|
||||||
walk::Node,
|
walk::Node,
|
||||||
SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Check the provided AST for any found rule violations.
|
/// Check the provided AST for any found rule violations.
|
||||||
@ -180,7 +180,7 @@ impl Finding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! def_finding {
|
macro_rules! def_finding {
|
||||||
( $code:ident, $title:expr, $description:expr ) => {
|
( $code:ident, $title:expr_2021, $description:expr_2021 ) => {
|
||||||
/// Generated Finding
|
/// Generated Finding
|
||||||
pub const $code: Finding = $crate::lint::rule::finding!($code, $title, $description);
|
pub const $code: Finding = $crate::lint::rule::finding!($code, $title, $description);
|
||||||
};
|
};
|
||||||
@ -188,7 +188,7 @@ macro_rules! def_finding {
|
|||||||
pub(crate) use def_finding;
|
pub(crate) use def_finding;
|
||||||
|
|
||||||
macro_rules! finding {
|
macro_rules! finding {
|
||||||
( $code:ident, $title:expr, $description:expr ) => {
|
( $code:ident, $title:expr_2021, $description:expr_2021 ) => {
|
||||||
$crate::lint::rule::Finding {
|
$crate::lint::rule::Finding {
|
||||||
code: stringify!($code),
|
code: stringify!($code),
|
||||||
title: $title,
|
title: $title,
|
||||||
@ -205,7 +205,7 @@ pub(crate) use test::{assert_finding, assert_no_finding, test_finding, test_no_f
|
|||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
macro_rules! assert_no_finding {
|
macro_rules! assert_no_finding {
|
||||||
( $check:expr, $finding:expr, $kcl:expr ) => {
|
( $check:expr_2021, $finding:expr_2021, $kcl:expr_2021 ) => {
|
||||||
let prog = $crate::Program::parse_no_errs($kcl).unwrap();
|
let prog = $crate::Program::parse_no_errs($kcl).unwrap();
|
||||||
|
|
||||||
// Ensure the code still works.
|
// Ensure the code still works.
|
||||||
@ -220,7 +220,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! assert_finding {
|
macro_rules! assert_finding {
|
||||||
( $check:expr, $finding:expr, $kcl:expr, $output:expr, $suggestion:expr ) => {
|
( $check:expr_2021, $finding:expr_2021, $kcl:expr_2021, $output:expr_2021, $suggestion:expr_2021 ) => {
|
||||||
let prog = $crate::Program::parse_no_errs($kcl).unwrap();
|
let prog = $crate::Program::parse_no_errs($kcl).unwrap();
|
||||||
|
|
||||||
// Ensure the code still works.
|
// Ensure the code still works.
|
||||||
@ -250,7 +250,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! test_finding {
|
macro_rules! test_finding {
|
||||||
( $name:ident, $check:expr, $finding:expr, $kcl:expr, $output:expr, $suggestion:expr ) => {
|
( $name:ident, $check:expr_2021, $finding:expr_2021, $kcl:expr_2021, $output:expr_2021, $suggestion:expr_2021 ) => {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn $name() {
|
async fn $name() {
|
||||||
$crate::lint::rule::assert_finding!($check, $finding, $kcl, $output, $suggestion);
|
$crate::lint::rule::assert_finding!($check, $finding, $kcl, $output, $suggestion);
|
||||||
@ -259,7 +259,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! test_no_finding {
|
macro_rules! test_no_finding {
|
||||||
( $name:ident, $check:expr, $finding:expr, $kcl:expr ) => {
|
( $name:ident, $check:expr_2021, $finding:expr_2021, $kcl:expr_2021 ) => {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn $name() {
|
async fn $name() {
|
||||||
$crate::lint::rule::assert_no_finding!($check, $finding, $kcl);
|
$crate::lint::rule::assert_no_finding!($check, $finding, $kcl);
|
||||||
|
@ -90,7 +90,7 @@ where
|
|||||||
|
|
||||||
async fn do_initialized(&self, params: InitializedParams) {
|
async fn do_initialized(&self, params: InitializedParams) {
|
||||||
self.client()
|
self.client()
|
||||||
.log_message(MessageType::INFO, format!("initialized: {:?}", params))
|
.log_message(MessageType::INFO, format!("initialized: {params:?}"))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
self.set_is_initialized(true).await;
|
self.set_is_initialized(true).await;
|
||||||
@ -139,7 +139,7 @@ where
|
|||||||
self.client()
|
self.client()
|
||||||
.log_message(
|
.log_message(
|
||||||
MessageType::WARNING,
|
MessageType::WARNING,
|
||||||
format!("updating from disk `{}` failed: {:?}", project_dir, err),
|
format!("updating from disk `{project_dir}` failed: {err:?}"),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -148,19 +148,19 @@ where
|
|||||||
|
|
||||||
async fn do_did_change_configuration(&self, params: DidChangeConfigurationParams) {
|
async fn do_did_change_configuration(&self, params: DidChangeConfigurationParams) {
|
||||||
self.client()
|
self.client()
|
||||||
.log_message(MessageType::INFO, format!("configuration changed: {:?}", params))
|
.log_message(MessageType::INFO, format!("configuration changed: {params:?}"))
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn do_did_change_watched_files(&self, params: DidChangeWatchedFilesParams) {
|
async fn do_did_change_watched_files(&self, params: DidChangeWatchedFilesParams) {
|
||||||
self.client()
|
self.client()
|
||||||
.log_message(MessageType::INFO, format!("watched files changed: {:?}", params))
|
.log_message(MessageType::INFO, format!("watched files changed: {params:?}"))
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn do_did_create_files(&self, params: CreateFilesParams) {
|
async fn do_did_create_files(&self, params: CreateFilesParams) {
|
||||||
self.client()
|
self.client()
|
||||||
.log_message(MessageType::INFO, format!("files created: {:?}", params))
|
.log_message(MessageType::INFO, format!("files created: {params:?}"))
|
||||||
.await;
|
.await;
|
||||||
// Create each file in the code map.
|
// Create each file in the code map.
|
||||||
for file in params.files {
|
for file in params.files {
|
||||||
@ -170,7 +170,7 @@ where
|
|||||||
|
|
||||||
async fn do_did_rename_files(&self, params: RenameFilesParams) {
|
async fn do_did_rename_files(&self, params: RenameFilesParams) {
|
||||||
self.client()
|
self.client()
|
||||||
.log_message(MessageType::INFO, format!("files renamed: {:?}", params))
|
.log_message(MessageType::INFO, format!("files renamed: {params:?}"))
|
||||||
.await;
|
.await;
|
||||||
// Rename each file in the code map.
|
// Rename each file in the code map.
|
||||||
for file in params.files {
|
for file in params.files {
|
||||||
@ -186,7 +186,7 @@ where
|
|||||||
|
|
||||||
async fn do_did_delete_files(&self, params: DeleteFilesParams) {
|
async fn do_did_delete_files(&self, params: DeleteFilesParams) {
|
||||||
self.client()
|
self.client()
|
||||||
.log_message(MessageType::INFO, format!("files deleted: {:?}", params))
|
.log_message(MessageType::INFO, format!("files deleted: {params:?}"))
|
||||||
.await;
|
.await;
|
||||||
// Delete each file in the map.
|
// Delete each file in the map.
|
||||||
for file in params.files {
|
for file in params.files {
|
||||||
@ -228,7 +228,7 @@ where
|
|||||||
|
|
||||||
async fn do_did_close(&self, params: DidCloseTextDocumentParams) {
|
async fn do_did_close(&self, params: DidCloseTextDocumentParams) {
|
||||||
self.client()
|
self.client()
|
||||||
.log_message(MessageType::INFO, format!("document closed: {:?}", params))
|
.log_message(MessageType::INFO, format!("document closed: {params:?}"))
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ use std::{
|
|||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tower_lsp::{
|
use tower_lsp::{
|
||||||
|
LanguageServer,
|
||||||
jsonrpc::{Error, Result},
|
jsonrpc::{Error, Result},
|
||||||
lsp_types::{
|
lsp_types::{
|
||||||
CreateFilesParams, DeleteFilesParams, Diagnostic, DidChangeConfigurationParams, DidChangeTextDocumentParams,
|
CreateFilesParams, DeleteFilesParams, Diagnostic, DidChangeConfigurationParams, DidChangeTextDocumentParams,
|
||||||
@ -22,7 +23,6 @@ use tower_lsp::{
|
|||||||
TextDocumentSyncKind, TextDocumentSyncOptions, WorkspaceFolder, WorkspaceFoldersServerCapabilities,
|
TextDocumentSyncKind, TextDocumentSyncOptions, WorkspaceFolder, WorkspaceFoldersServerCapabilities,
|
||||||
WorkspaceServerCapabilities,
|
WorkspaceServerCapabilities,
|
||||||
},
|
},
|
||||||
LanguageServer,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::lsp::{
|
use crate::lsp::{
|
||||||
@ -198,7 +198,7 @@ impl Backend {
|
|||||||
.map_err(|err| Error {
|
.map_err(|err| Error {
|
||||||
code: tower_lsp::jsonrpc::ErrorCode::from(69),
|
code: tower_lsp::jsonrpc::ErrorCode::from(69),
|
||||||
data: None,
|
data: None,
|
||||||
message: Cow::from(format!("Failed to get completions from zoo api: {}", err)),
|
message: Cow::from(format!("Failed to get completions from zoo api: {err}")),
|
||||||
})?;
|
})?;
|
||||||
Ok(resp.completions)
|
Ok(resp.completions)
|
||||||
}
|
}
|
||||||
@ -209,7 +209,7 @@ impl Backend {
|
|||||||
let mut lock = copy.write().map_err(|err| Error {
|
let mut lock = copy.write().map_err(|err| Error {
|
||||||
code: tower_lsp::jsonrpc::ErrorCode::from(69),
|
code: tower_lsp::jsonrpc::ErrorCode::from(69),
|
||||||
data: None,
|
data: None,
|
||||||
message: Cow::from(format!("Failed lock: {}", err)),
|
message: Cow::from(format!("Failed lock: {err}")),
|
||||||
})?;
|
})?;
|
||||||
*lock = params;
|
*lock = params;
|
||||||
Ok(Success::new(true))
|
Ok(Success::new(true))
|
||||||
@ -254,7 +254,7 @@ impl Backend {
|
|||||||
.map_err(|err| Error {
|
.map_err(|err| Error {
|
||||||
code: tower_lsp::jsonrpc::ErrorCode::from(69),
|
code: tower_lsp::jsonrpc::ErrorCode::from(69),
|
||||||
data: None,
|
data: None,
|
||||||
message: Cow::from(format!("Failed to get completions: {}", err)),
|
message: Cow::from(format!("Failed to get completions: {err}")),
|
||||||
})?;
|
})?;
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
let mut completion_list = vec![];
|
let mut completion_list = vec![];
|
||||||
@ -294,7 +294,7 @@ part001 = cube(pos = [0,0], scale = 20)
|
|||||||
|
|
||||||
pub async fn accept_completion(&self, params: CopilotAcceptCompletionParams) {
|
pub async fn accept_completion(&self, params: CopilotAcceptCompletionParams) {
|
||||||
self.client
|
self.client
|
||||||
.log_message(MessageType::INFO, format!("Accepted completions: {:?}", params))
|
.log_message(MessageType::INFO, format!("Accepted completions: {params:?}"))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Get the original telemetry data.
|
// Get the original telemetry data.
|
||||||
@ -303,7 +303,7 @@ part001 = cube(pos = [0,0], scale = 20)
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.client
|
self.client
|
||||||
.log_message(MessageType::INFO, format!("Original telemetry: {:?}", original))
|
.log_message(MessageType::INFO, format!("Original telemetry: {original:?}"))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// TODO: Send the telemetry data to the zoo api.
|
// TODO: Send the telemetry data to the zoo api.
|
||||||
@ -311,7 +311,7 @@ part001 = cube(pos = [0,0], scale = 20)
|
|||||||
|
|
||||||
pub async fn reject_completions(&self, params: CopilotRejectCompletionParams) {
|
pub async fn reject_completions(&self, params: CopilotRejectCompletionParams) {
|
||||||
self.client
|
self.client
|
||||||
.log_message(MessageType::INFO, format!("Rejected completions: {:?}", params))
|
.log_message(MessageType::INFO, format!("Rejected completions: {params:?}"))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Get the original telemetry data.
|
// Get the original telemetry data.
|
||||||
@ -323,7 +323,7 @@ part001 = cube(pos = [0,0], scale = 20)
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.client
|
self.client
|
||||||
.log_message(MessageType::INFO, format!("Original telemetry: {:?}", originals))
|
.log_message(MessageType::INFO, format!("Original telemetry: {originals:?}"))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// TODO: Send the telemetry data to the zoo api.
|
// TODO: Send the telemetry data to the zoo api.
|
||||||
|
@ -85,7 +85,7 @@ impl CopilotCompletionResponse {
|
|||||||
impl CopilotCyclingCompletion {
|
impl CopilotCyclingCompletion {
|
||||||
pub fn new(text: String, line_before: String, position: CopilotPosition) -> Self {
|
pub fn new(text: String, line_before: String, position: CopilotPosition) -> Self {
|
||||||
let display_text = text.clone();
|
let display_text = text.clone();
|
||||||
let text = format!("{}{}", line_before, text);
|
let text = format!("{line_before}{text}");
|
||||||
let end_char = text.find('\n').unwrap_or(text.len()) as u32;
|
let end_char = text.find('\n').unwrap_or(text.len()) as u32;
|
||||||
Self {
|
Self {
|
||||||
uuid: uuid::Uuid::new_v4(),
|
uuid: uuid::Uuid::new_v4(),
|
||||||
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tower_lsp::lsp_types::Range as LspRange;
|
use tower_lsp::lsp_types::Range as LspRange;
|
||||||
|
|
||||||
use crate::{parsing::ast::types::*, SourceRange};
|
use crate::{SourceRange, parsing::ast::types::*};
|
||||||
|
|
||||||
/// Describes information about a hover.
|
/// Describes information about a hover.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
||||||
|
@ -15,6 +15,7 @@ use dashmap::DashMap;
|
|||||||
use sha2::Digest;
|
use sha2::Digest;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use tower_lsp::{
|
use tower_lsp::{
|
||||||
|
Client, LanguageServer,
|
||||||
jsonrpc::Result as RpcResult,
|
jsonrpc::Result as RpcResult,
|
||||||
lsp_types::{
|
lsp_types::{
|
||||||
CodeAction, CodeActionKind, CodeActionOptions, CodeActionOrCommand, CodeActionParams,
|
CodeAction, CodeActionKind, CodeActionOptions, CodeActionOrCommand, CodeActionParams,
|
||||||
@ -37,10 +38,10 @@ use tower_lsp::{
|
|||||||
TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, TextEdit, WorkDoneProgressOptions,
|
TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, TextEdit, WorkDoneProgressOptions,
|
||||||
WorkspaceEdit, WorkspaceFolder, WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities,
|
WorkspaceEdit, WorkspaceFolder, WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities,
|
||||||
},
|
},
|
||||||
Client, LanguageServer,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ModuleId, Program, SourceRange,
|
||||||
docs::kcl_doc::ModData,
|
docs::kcl_doc::ModData,
|
||||||
errors::LspSuggestion,
|
errors::LspSuggestion,
|
||||||
exec::KclValue,
|
exec::KclValue,
|
||||||
@ -51,11 +52,10 @@ use crate::{
|
|||||||
util::IntoDiagnostic,
|
util::IntoDiagnostic,
|
||||||
},
|
},
|
||||||
parsing::{
|
parsing::{
|
||||||
|
PIPE_OPERATOR,
|
||||||
ast::types::{Expr, VariableKind},
|
ast::types::{Expr, VariableKind},
|
||||||
token::TokenStream,
|
token::TokenStream,
|
||||||
PIPE_OPERATOR,
|
|
||||||
},
|
},
|
||||||
ModuleId, Program, SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod custom_notifications;
|
pub mod custom_notifications;
|
||||||
@ -290,10 +290,9 @@ impl crate::lsp::backend::Backend for Backend {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get the previous tokens.
|
// Get the previous tokens.
|
||||||
let tokens_changed = if let Some(previous_tokens) = self.token_map.get(&filename) {
|
let tokens_changed = match self.token_map.get(&filename) {
|
||||||
*previous_tokens != tokens
|
Some(previous_tokens) => *previous_tokens != tokens,
|
||||||
} else {
|
_ => true,
|
||||||
true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let had_diagnostics = self.has_diagnostics(params.uri.as_ref()).await;
|
let had_diagnostics = self.has_diagnostics(params.uri.as_ref()).await;
|
||||||
@ -424,7 +423,7 @@ impl Backend {
|
|||||||
self.client
|
self.client
|
||||||
.log_message(
|
.log_message(
|
||||||
MessageType::ERROR,
|
MessageType::ERROR,
|
||||||
format!("token type `{:?}` not accounted for", token_type),
|
format!("token type `{token_type:?}` not accounted for"),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
continue;
|
continue;
|
||||||
@ -436,7 +435,8 @@ impl Backend {
|
|||||||
|
|
||||||
// Calculate the token modifiers.
|
// Calculate the token modifiers.
|
||||||
// Get the value at the current position.
|
// Get the value at the current position.
|
||||||
let token_modifiers_bitset = if let Some(ast) = self.ast_map.get(params.uri.as_str()) {
|
let token_modifiers_bitset = match self.ast_map.get(params.uri.as_str()) {
|
||||||
|
Some(ast) => {
|
||||||
let token_index = Arc::new(Mutex::new(token_type_index));
|
let token_index = Arc::new(Mutex::new(token_type_index));
|
||||||
let modifier_index: Arc<Mutex<u32>> = Arc::new(Mutex::new(0));
|
let modifier_index: Arc<Mutex<u32>> = Arc::new(Mutex::new(0));
|
||||||
crate::walk::walk(&ast.ast, |node: crate::walk::Node| {
|
crate::walk::walk(&ast.ast, |node: crate::walk::Node| {
|
||||||
@ -538,17 +538,18 @@ impl Backend {
|
|||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let t = if let Ok(guard) = token_index.lock() { *guard } else { 0 };
|
let t = match token_index.lock() {
|
||||||
|
Ok(guard) => *guard,
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
token_type_index = t;
|
token_type_index = t;
|
||||||
|
|
||||||
let m = if let Ok(guard) = modifier_index.lock() {
|
match modifier_index.lock() {
|
||||||
*guard
|
Ok(guard) => *guard,
|
||||||
} else {
|
_ => 0,
|
||||||
0
|
}
|
||||||
};
|
}
|
||||||
m
|
_ => 0,
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// We need to check if we are on the last token of the line.
|
// We need to check if we are on the last token of the line.
|
||||||
@ -652,11 +653,14 @@ impl Backend {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut items = if let Some(items) = self.diagnostics_map.get(params.uri.as_str()) {
|
let mut items = match self.diagnostics_map.get(params.uri.as_str()) {
|
||||||
|
Some(items) => {
|
||||||
// TODO: Would be awesome to fix the clone here.
|
// TODO: Would be awesome to fix the clone here.
|
||||||
items.clone()
|
items.clone()
|
||||||
} else {
|
}
|
||||||
|
_ => {
|
||||||
vec![]
|
vec![]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for diagnostic in diagnostics {
|
for diagnostic in diagnostics {
|
||||||
@ -768,7 +772,7 @@ impl Backend {
|
|||||||
// Read hash digest and consume hasher
|
// Read hash digest and consume hasher
|
||||||
let result = hasher.finalize();
|
let result = hasher.finalize();
|
||||||
// Get the hash as a string.
|
// Get the hash as a string.
|
||||||
let user_id_hash = format!("{:x}", result);
|
let user_id_hash = format!("{result:x}");
|
||||||
|
|
||||||
// Get the workspace folders.
|
// Get the workspace folders.
|
||||||
// The key of the workspace folder is the project name.
|
// The key of the workspace folder is the project name.
|
||||||
@ -866,7 +870,7 @@ impl Backend {
|
|||||||
impl LanguageServer for Backend {
|
impl LanguageServer for Backend {
|
||||||
async fn initialize(&self, params: InitializeParams) -> RpcResult<InitializeResult> {
|
async fn initialize(&self, params: InitializeParams) -> RpcResult<InitializeResult> {
|
||||||
self.client
|
self.client
|
||||||
.log_message(MessageType::INFO, format!("initialize: {:?}", params))
|
.log_message(MessageType::INFO, format!("initialize: {params:?}"))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Ok(InitializeResult {
|
Ok(InitializeResult {
|
||||||
@ -1006,7 +1010,7 @@ impl LanguageServer for Backend {
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
if let Err(err) = self.send_telemetry().await {
|
if let Err(err) = self.send_telemetry().await {
|
||||||
self.client
|
self.client
|
||||||
.log_message(MessageType::WARNING, format!("failed to send telemetry: {}", err))
|
.log_message(MessageType::WARNING, format!("failed to send telemetry: {err}"))
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1090,7 +1094,7 @@ impl LanguageServer for Backend {
|
|||||||
Ok(Some(LspHover {
|
Ok(Some(LspHover {
|
||||||
contents: HoverContents::Markup(MarkupContent {
|
contents: HoverContents::Markup(MarkupContent {
|
||||||
kind: MarkupKind::Markdown,
|
kind: MarkupKind::Markdown,
|
||||||
value: format!("```\n{}{}\n```\n\n{}", name, sig, docs),
|
value: format!("```\n{name}{sig}\n```\n\n{docs}"),
|
||||||
}),
|
}),
|
||||||
range: Some(range),
|
range: Some(range),
|
||||||
}))
|
}))
|
||||||
@ -1118,7 +1122,7 @@ impl LanguageServer for Backend {
|
|||||||
Ok(Some(LspHover {
|
Ok(Some(LspHover {
|
||||||
contents: HoverContents::Markup(MarkupContent {
|
contents: HoverContents::Markup(MarkupContent {
|
||||||
kind: MarkupKind::Markdown,
|
kind: MarkupKind::Markdown,
|
||||||
value: format!("```\n{}\n```\n\n{}", name, docs),
|
value: format!("```\n{name}\n```\n\n{docs}"),
|
||||||
}),
|
}),
|
||||||
range: Some(range),
|
range: Some(range),
|
||||||
}))
|
}))
|
||||||
@ -1153,17 +1157,17 @@ impl LanguageServer for Backend {
|
|||||||
} => Ok(Some(LspHover {
|
} => Ok(Some(LspHover {
|
||||||
contents: HoverContents::Markup(MarkupContent {
|
contents: HoverContents::Markup(MarkupContent {
|
||||||
kind: MarkupKind::Markdown,
|
kind: MarkupKind::Markdown,
|
||||||
value: format!("```\n{}: {}\n```", name, ty),
|
value: format!("```\n{name}: {ty}\n```"),
|
||||||
}),
|
}),
|
||||||
range: Some(range),
|
range: Some(range),
|
||||||
})),
|
})),
|
||||||
Hover::Variable { name, ty: None, range } => Ok(with_cached_var(&name, |value| {
|
Hover::Variable { name, ty: None, range } => Ok(with_cached_var(&name, |value| {
|
||||||
let mut text: String = format!("```\n{}", name);
|
let mut text: String = format!("```\n{name}");
|
||||||
if let Some(ty) = value.principal_type() {
|
if let Some(ty) = value.principal_type() {
|
||||||
text.push_str(&format!(": {}", ty.human_friendly_type()));
|
text.push_str(&format!(": {}", ty.human_friendly_type()));
|
||||||
}
|
}
|
||||||
if let Some(v) = value.value_str() {
|
if let Some(v) = value.value_str() {
|
||||||
text.push_str(&format!(" = {}", v));
|
text.push_str(&format!(" = {v}"));
|
||||||
}
|
}
|
||||||
text.push_str("\n```");
|
text.push_str("\n```");
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@ use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity, DiagnosticTag};
|
|||||||
pub use util::IntoDiagnostic;
|
pub use util::IntoDiagnostic;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{Severity, Tag},
|
|
||||||
CompilationError,
|
CompilationError,
|
||||||
|
errors::{Severity, Tag},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl IntoDiagnostic for CompilationError {
|
impl IntoDiagnostic for CompilationError {
|
||||||
|
@ -2,18 +2,18 @@ use std::collections::{BTreeMap, HashMap};
|
|||||||
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use tower_lsp::{
|
use tower_lsp::{
|
||||||
|
LanguageServer,
|
||||||
lsp_types::{
|
lsp_types::{
|
||||||
CodeActionKind, CodeActionOrCommand, Diagnostic, PrepareRenameResponse, SemanticTokenModifier,
|
CodeActionKind, CodeActionOrCommand, Diagnostic, PrepareRenameResponse, SemanticTokenModifier,
|
||||||
SemanticTokenType, TextEdit, WorkspaceEdit,
|
SemanticTokenType, TextEdit, WorkspaceEdit,
|
||||||
},
|
},
|
||||||
LanguageServer,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
SourceRange,
|
||||||
errors::{LspSuggestion, Suggestion},
|
errors::{LspSuggestion, Suggestion},
|
||||||
lsp::test_util::{copilot_lsp_server, kcl_lsp_server},
|
lsp::test_util::{copilot_lsp_server, kcl_lsp_server},
|
||||||
parsing::ast::types::{Node, Program},
|
parsing::ast::types::{Node, Program},
|
||||||
SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
@ -276,11 +276,7 @@ async fn test_updating_kcl_lsp_files() {
|
|||||||
assert_eq!(server.code_map.len(), 11);
|
assert_eq!(server.code_map.len(), 11);
|
||||||
// Just make sure that one of the current files read from disk is accurate.
|
// Just make sure that one of the current files read from disk is accurate.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
server
|
server.code_map.get(&format!("{string_path}/util.rs")).unwrap().clone(),
|
||||||
.code_map
|
|
||||||
.get(&format!("{}/util.rs", string_path))
|
|
||||||
.unwrap()
|
|
||||||
.clone(),
|
|
||||||
include_str!("util.rs").as_bytes()
|
include_str!("util.rs").as_bytes()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -633,7 +629,7 @@ async fn test_kcl_lsp_create_zip() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(files.len(), 12);
|
assert_eq!(files.len(), 12);
|
||||||
let util_path = format!("{}/util.rs", string_path).replace("file://", "");
|
let util_path = format!("{string_path}/util.rs").replace("file://", "");
|
||||||
assert!(files.contains_key(&util_path));
|
assert!(files.contains_key(&util_path));
|
||||||
assert_eq!(files.get("/test.kcl"), Some(&4));
|
assert_eq!(files.get("/test.kcl"), Some(&4));
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
exec::KclValue,
|
exec::KclValue,
|
||||||
execution::{typed_path::TypedPath, EnvironmentRef, ModuleArtifactState, PreImportedGeometry},
|
execution::{EnvironmentRef, ModuleArtifactState, PreImportedGeometry, typed_path::TypedPath},
|
||||||
fs::{FileManager, FileSystem},
|
fs::{FileManager, FileSystem},
|
||||||
parsing::ast::types::{ImportPath, Node, Program},
|
parsing::ast::types::{ImportPath, Node, Program},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
@ -73,13 +73,13 @@ impl ModuleLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn enter_module(&mut self, path: &ModulePath) {
|
pub(crate) fn enter_module(&mut self, path: &ModulePath) {
|
||||||
if let ModulePath::Local { value: ref path } = path {
|
if let ModulePath::Local { value: path } = path {
|
||||||
self.import_stack.push(path.clone());
|
self.import_stack.push(path.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn leave_module(&mut self, path: &ModulePath) {
|
pub(crate) fn leave_module(&mut self, path: &ModulePath) {
|
||||||
if let ModulePath::Local { value: ref path } = path {
|
if let ModulePath::Local { value: path } = path {
|
||||||
let popped = self.import_stack.pop().unwrap();
|
let popped = self.import_stack.pop().unwrap();
|
||||||
assert_eq!(path, &popped);
|
assert_eq!(path, &popped);
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ pub(crate) mod digest;
|
|||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
parsing::ast::types::{BinaryPart, BodyItem, Expr, LiteralIdentifier},
|
|
||||||
ModuleId,
|
ModuleId,
|
||||||
|
parsing::ast::types::{BinaryPart, BodyItem, Expr, LiteralIdentifier},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl BodyItem {
|
impl BodyItem {
|
||||||
|
@ -25,15 +25,14 @@ pub use crate::parsing::ast::types::{
|
|||||||
none::KclNone,
|
none::KclNone,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ModuleId, TypedPath,
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
execution::{
|
execution::{
|
||||||
annotations,
|
KclValue, Metadata, TagIdentifier, annotations,
|
||||||
types::{ArrayLen, UnitAngle, UnitLen},
|
types::{ArrayLen, UnitAngle, UnitLen},
|
||||||
KclValue, Metadata, TagIdentifier,
|
|
||||||
},
|
},
|
||||||
parsing::{ast::digest::Digest, token::NumericSuffix, PIPE_OPERATOR},
|
parsing::{PIPE_OPERATOR, ast::digest::Digest, token::NumericSuffix},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
ModuleId, TypedPath,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mod condition;
|
mod condition;
|
||||||
@ -72,18 +71,18 @@ impl<T: JsonSchema> schemars::JsonSchema for Node<T> {
|
|||||||
T::schema_name()
|
T::schema_name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||||
let mut child = T::json_schema(gen).into_object();
|
let mut child = T::json_schema(r#gen).into_object();
|
||||||
// We want to add the start and end fields to the schema.
|
// We want to add the start and end fields to the schema.
|
||||||
// Ideally we would add _any_ extra fields from the Node type automatically
|
// Ideally we would add _any_ extra fields from the Node type automatically
|
||||||
// but this is a bit hard since this isn't a macro.
|
// but this is a bit hard since this isn't a macro.
|
||||||
let Some(ref mut object) = &mut child.object else {
|
let Some(object) = &mut child.object else {
|
||||||
// This should never happen. But it will panic at compile time of docs if it does.
|
// This should never happen. But it will panic at compile time of docs if it does.
|
||||||
// Which is better than runtime.
|
// Which is better than runtime.
|
||||||
panic!("Expected object schema for {}", T::schema_name());
|
panic!("Expected object schema for {}", T::schema_name());
|
||||||
};
|
};
|
||||||
object.properties.insert("start".to_string(), usize::json_schema(gen));
|
object.properties.insert("start".to_string(), usize::json_schema(r#gen));
|
||||||
object.properties.insert("end".to_string(), usize::json_schema(gen));
|
object.properties.insert("end".to_string(), usize::json_schema(r#gen));
|
||||||
|
|
||||||
schemars::schema::Schema::Object(child.clone())
|
schemars::schema::Schema::Object(child.clone())
|
||||||
}
|
}
|
||||||
@ -681,7 +680,7 @@ impl Program {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BodyItem::VariableDeclaration(ref mut variable_declaration) => {
|
BodyItem::VariableDeclaration(variable_declaration) => {
|
||||||
if let Some(var_old_name) = variable_declaration.rename_symbol(new_name, pos) {
|
if let Some(var_old_name) = variable_declaration.rename_symbol(new_name, pos) {
|
||||||
old_name = Some(var_old_name);
|
old_name = Some(var_old_name);
|
||||||
break;
|
break;
|
||||||
@ -705,18 +704,16 @@ impl Program {
|
|||||||
// Recurse over the item.
|
// Recurse over the item.
|
||||||
let mut value = match item {
|
let mut value = match item {
|
||||||
BodyItem::ImportStatement(_) => None, // TODO
|
BodyItem::ImportStatement(_) => None, // TODO
|
||||||
BodyItem::ExpressionStatement(ref mut expression_statement) => {
|
BodyItem::ExpressionStatement(expression_statement) => Some(&mut expression_statement.expression),
|
||||||
Some(&mut expression_statement.expression)
|
BodyItem::VariableDeclaration(variable_declaration) => {
|
||||||
}
|
|
||||||
BodyItem::VariableDeclaration(ref mut variable_declaration) => {
|
|
||||||
variable_declaration.get_mut_expr_for_position(pos)
|
variable_declaration.get_mut_expr_for_position(pos)
|
||||||
}
|
}
|
||||||
BodyItem::TypeDeclaration(_) => None,
|
BodyItem::TypeDeclaration(_) => None,
|
||||||
BodyItem::ReturnStatement(ref mut return_statement) => Some(&mut return_statement.argument),
|
BodyItem::ReturnStatement(return_statement) => Some(&mut return_statement.argument),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if we have a function expression.
|
// Check if we have a function expression.
|
||||||
if let Some(Expr::FunctionExpression(ref mut function_expression)) = &mut value {
|
if let Some(Expr::FunctionExpression(function_expression)) = &mut value {
|
||||||
// Check if the params to the function expression contain the position.
|
// Check if the params to the function expression contain the position.
|
||||||
for param in &mut function_expression.params {
|
for param in &mut function_expression.params {
|
||||||
let param_source_range: SourceRange = (¶m.identifier).into();
|
let param_source_range: SourceRange = (¶m.identifier).into();
|
||||||
@ -764,7 +761,7 @@ impl Program {
|
|||||||
BodyItem::ExpressionStatement(_) => {
|
BodyItem::ExpressionStatement(_) => {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
BodyItem::VariableDeclaration(ref mut variable_declaration) => {
|
BodyItem::VariableDeclaration(variable_declaration) => {
|
||||||
if variable_declaration.declaration.id.name == name {
|
if variable_declaration.declaration.id.name == name {
|
||||||
variable_declaration.declaration = declarator;
|
variable_declaration.declaration = declarator;
|
||||||
return;
|
return;
|
||||||
@ -783,14 +780,14 @@ impl Program {
|
|||||||
for item in &mut self.body {
|
for item in &mut self.body {
|
||||||
match item {
|
match item {
|
||||||
BodyItem::ImportStatement(_) => {} // TODO
|
BodyItem::ImportStatement(_) => {} // TODO
|
||||||
BodyItem::ExpressionStatement(ref mut expression_statement) => expression_statement
|
BodyItem::ExpressionStatement(expression_statement) => expression_statement
|
||||||
.expression
|
.expression
|
||||||
.replace_value(source_range, new_value.clone()),
|
.replace_value(source_range, new_value.clone()),
|
||||||
BodyItem::VariableDeclaration(ref mut variable_declaration) => {
|
BodyItem::VariableDeclaration(variable_declaration) => {
|
||||||
variable_declaration.replace_value(source_range, new_value.clone())
|
variable_declaration.replace_value(source_range, new_value.clone())
|
||||||
}
|
}
|
||||||
BodyItem::TypeDeclaration(_) => {}
|
BodyItem::TypeDeclaration(_) => {}
|
||||||
BodyItem::ReturnStatement(ref mut return_statement) => {
|
BodyItem::ReturnStatement(return_statement) => {
|
||||||
return_statement.argument.replace_value(source_range, new_value.clone())
|
return_statement.argument.replace_value(source_range, new_value.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1040,18 +1037,18 @@ impl Expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Expr::BinaryExpression(ref mut bin_exp) => bin_exp.replace_value(source_range, new_value),
|
Expr::BinaryExpression(bin_exp) => bin_exp.replace_value(source_range, new_value),
|
||||||
Expr::ArrayExpression(ref mut array_exp) => array_exp.replace_value(source_range, new_value),
|
Expr::ArrayExpression(array_exp) => array_exp.replace_value(source_range, new_value),
|
||||||
Expr::ArrayRangeExpression(ref mut array_range) => array_range.replace_value(source_range, new_value),
|
Expr::ArrayRangeExpression(array_range) => array_range.replace_value(source_range, new_value),
|
||||||
Expr::ObjectExpression(ref mut obj_exp) => obj_exp.replace_value(source_range, new_value),
|
Expr::ObjectExpression(obj_exp) => obj_exp.replace_value(source_range, new_value),
|
||||||
Expr::MemberExpression(_) => {}
|
Expr::MemberExpression(_) => {}
|
||||||
Expr::Literal(_) => {}
|
Expr::Literal(_) => {}
|
||||||
Expr::FunctionExpression(ref mut func_exp) => func_exp.replace_value(source_range, new_value),
|
Expr::FunctionExpression(func_exp) => func_exp.replace_value(source_range, new_value),
|
||||||
Expr::CallExpressionKw(ref mut call_exp) => call_exp.replace_value(source_range, new_value),
|
Expr::CallExpressionKw(call_exp) => call_exp.replace_value(source_range, new_value),
|
||||||
Expr::Name(_) => {}
|
Expr::Name(_) => {}
|
||||||
Expr::TagDeclarator(_) => {}
|
Expr::TagDeclarator(_) => {}
|
||||||
Expr::PipeExpression(ref mut pipe_exp) => pipe_exp.replace_value(source_range, new_value),
|
Expr::PipeExpression(pipe_exp) => pipe_exp.replace_value(source_range, new_value),
|
||||||
Expr::UnaryExpression(ref mut unary_exp) => unary_exp.replace_value(source_range, new_value),
|
Expr::UnaryExpression(unary_exp) => unary_exp.replace_value(source_range, new_value),
|
||||||
Expr::IfExpression(_) => {}
|
Expr::IfExpression(_) => {}
|
||||||
Expr::PipeSubstitution(_) => {}
|
Expr::PipeSubstitution(_) => {}
|
||||||
Expr::LabelledExpression(expr) => expr.expr.replace_value(source_range, new_value),
|
Expr::LabelledExpression(expr) => expr.expr.replace_value(source_range, new_value),
|
||||||
@ -1113,25 +1110,19 @@ impl Expr {
|
|||||||
fn rename_identifiers(&mut self, old_name: &str, new_name: &str) {
|
fn rename_identifiers(&mut self, old_name: &str, new_name: &str) {
|
||||||
match self {
|
match self {
|
||||||
Expr::Literal(_literal) => {}
|
Expr::Literal(_literal) => {}
|
||||||
Expr::Name(ref mut identifier) => identifier.rename(old_name, new_name),
|
Expr::Name(identifier) => identifier.rename(old_name, new_name),
|
||||||
Expr::TagDeclarator(ref mut tag) => tag.rename(old_name, new_name),
|
Expr::TagDeclarator(tag) => tag.rename(old_name, new_name),
|
||||||
Expr::BinaryExpression(ref mut binary_expression) => {
|
Expr::BinaryExpression(binary_expression) => binary_expression.rename_identifiers(old_name, new_name),
|
||||||
binary_expression.rename_identifiers(old_name, new_name)
|
|
||||||
}
|
|
||||||
Expr::FunctionExpression(_function_identifier) => {}
|
Expr::FunctionExpression(_function_identifier) => {}
|
||||||
Expr::CallExpressionKw(ref mut call_expression) => call_expression.rename_identifiers(old_name, new_name),
|
Expr::CallExpressionKw(call_expression) => call_expression.rename_identifiers(old_name, new_name),
|
||||||
Expr::PipeExpression(ref mut pipe_expression) => pipe_expression.rename_identifiers(old_name, new_name),
|
Expr::PipeExpression(pipe_expression) => pipe_expression.rename_identifiers(old_name, new_name),
|
||||||
Expr::PipeSubstitution(_) => {}
|
Expr::PipeSubstitution(_) => {}
|
||||||
Expr::ArrayExpression(ref mut array_expression) => array_expression.rename_identifiers(old_name, new_name),
|
Expr::ArrayExpression(array_expression) => array_expression.rename_identifiers(old_name, new_name),
|
||||||
Expr::ArrayRangeExpression(ref mut array_range) => array_range.rename_identifiers(old_name, new_name),
|
Expr::ArrayRangeExpression(array_range) => array_range.rename_identifiers(old_name, new_name),
|
||||||
Expr::ObjectExpression(ref mut object_expression) => {
|
Expr::ObjectExpression(object_expression) => object_expression.rename_identifiers(old_name, new_name),
|
||||||
object_expression.rename_identifiers(old_name, new_name)
|
Expr::MemberExpression(member_expression) => member_expression.rename_identifiers(old_name, new_name),
|
||||||
}
|
Expr::UnaryExpression(unary_expression) => unary_expression.rename_identifiers(old_name, new_name),
|
||||||
Expr::MemberExpression(ref mut member_expression) => {
|
Expr::IfExpression(expr) => expr.rename_identifiers(old_name, new_name),
|
||||||
member_expression.rename_identifiers(old_name, new_name)
|
|
||||||
}
|
|
||||||
Expr::UnaryExpression(ref mut unary_expression) => unary_expression.rename_identifiers(old_name, new_name),
|
|
||||||
Expr::IfExpression(ref mut expr) => expr.rename_identifiers(old_name, new_name),
|
|
||||||
Expr::LabelledExpression(expr) => expr.expr.rename_identifiers(old_name, new_name),
|
Expr::LabelledExpression(expr) => expr.expr.rename_identifiers(old_name, new_name),
|
||||||
Expr::AscribedExpression(expr) => expr.expr.rename_identifiers(old_name, new_name),
|
Expr::AscribedExpression(expr) => expr.expr.rename_identifiers(old_name, new_name),
|
||||||
Expr::None(_) => {}
|
Expr::None(_) => {}
|
||||||
@ -1325,15 +1316,9 @@ impl BinaryPart {
|
|||||||
match self {
|
match self {
|
||||||
BinaryPart::Literal(_) => {}
|
BinaryPart::Literal(_) => {}
|
||||||
BinaryPart::Name(_) => {}
|
BinaryPart::Name(_) => {}
|
||||||
BinaryPart::BinaryExpression(ref mut binary_expression) => {
|
BinaryPart::BinaryExpression(binary_expression) => binary_expression.replace_value(source_range, new_value),
|
||||||
binary_expression.replace_value(source_range, new_value)
|
BinaryPart::CallExpressionKw(call_expression) => call_expression.replace_value(source_range, new_value),
|
||||||
}
|
BinaryPart::UnaryExpression(unary_expression) => unary_expression.replace_value(source_range, new_value),
|
||||||
BinaryPart::CallExpressionKw(ref mut call_expression) => {
|
|
||||||
call_expression.replace_value(source_range, new_value)
|
|
||||||
}
|
|
||||||
BinaryPart::UnaryExpression(ref mut unary_expression) => {
|
|
||||||
unary_expression.replace_value(source_range, new_value)
|
|
||||||
}
|
|
||||||
BinaryPart::MemberExpression(_) => {}
|
BinaryPart::MemberExpression(_) => {}
|
||||||
BinaryPart::IfExpression(e) => e.replace_value(source_range, new_value),
|
BinaryPart::IfExpression(e) => e.replace_value(source_range, new_value),
|
||||||
BinaryPart::AscribedExpression(e) => e.expr.replace_value(source_range, new_value),
|
BinaryPart::AscribedExpression(e) => e.expr.replace_value(source_range, new_value),
|
||||||
@ -1370,21 +1355,13 @@ impl BinaryPart {
|
|||||||
fn rename_identifiers(&mut self, old_name: &str, new_name: &str) {
|
fn rename_identifiers(&mut self, old_name: &str, new_name: &str) {
|
||||||
match self {
|
match self {
|
||||||
BinaryPart::Literal(_literal) => {}
|
BinaryPart::Literal(_literal) => {}
|
||||||
BinaryPart::Name(ref mut identifier) => identifier.rename(old_name, new_name),
|
BinaryPart::Name(identifier) => identifier.rename(old_name, new_name),
|
||||||
BinaryPart::BinaryExpression(ref mut binary_expression) => {
|
BinaryPart::BinaryExpression(binary_expression) => binary_expression.rename_identifiers(old_name, new_name),
|
||||||
binary_expression.rename_identifiers(old_name, new_name)
|
BinaryPart::CallExpressionKw(call_expression) => call_expression.rename_identifiers(old_name, new_name),
|
||||||
}
|
BinaryPart::UnaryExpression(unary_expression) => unary_expression.rename_identifiers(old_name, new_name),
|
||||||
BinaryPart::CallExpressionKw(ref mut call_expression) => {
|
BinaryPart::MemberExpression(member_expression) => member_expression.rename_identifiers(old_name, new_name),
|
||||||
call_expression.rename_identifiers(old_name, new_name)
|
BinaryPart::IfExpression(if_expression) => if_expression.rename_identifiers(old_name, new_name),
|
||||||
}
|
BinaryPart::AscribedExpression(e) => e.expr.rename_identifiers(old_name, new_name),
|
||||||
BinaryPart::UnaryExpression(ref mut unary_expression) => {
|
|
||||||
unary_expression.rename_identifiers(old_name, new_name)
|
|
||||||
}
|
|
||||||
BinaryPart::MemberExpression(ref mut member_expression) => {
|
|
||||||
member_expression.rename_identifiers(old_name, new_name)
|
|
||||||
}
|
|
||||||
BinaryPart::IfExpression(ref mut if_expression) => if_expression.rename_identifiers(old_name, new_name),
|
|
||||||
BinaryPart::AscribedExpression(ref mut e) => e.expr.rename_identifiers(old_name, new_name),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2824,7 +2801,7 @@ impl MemberExpression {
|
|||||||
self.object.rename_identifiers(old_name, new_name);
|
self.object.rename_identifiers(old_name, new_name);
|
||||||
|
|
||||||
match &mut self.property {
|
match &mut self.property {
|
||||||
LiteralIdentifier::Identifier(ref mut identifier) => identifier.rename(old_name, new_name),
|
LiteralIdentifier::Identifier(identifier) => identifier.rename(old_name, new_name),
|
||||||
LiteralIdentifier::Literal(_) => {}
|
LiteralIdentifier::Literal(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3312,7 +3289,7 @@ impl Type {
|
|||||||
.map(|t| t.human_friendly_type())
|
.map(|t| t.human_friendly_type())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(" or "),
|
.join(" or "),
|
||||||
Type::Object { .. } => format!("an object with fields `{}`", self),
|
Type::Object { .. } => format!("an object with fields `{self}`"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3469,7 +3446,11 @@ pub struct RequiredParamAfterOptionalParam(pub Box<Parameter>);
|
|||||||
|
|
||||||
impl std::fmt::Display for RequiredParamAfterOptionalParam {
|
impl std::fmt::Display for RequiredParamAfterOptionalParam {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "KCL functions must declare any optional parameters after all the required parameters. But your required parameter {} is _after_ an optional parameter. You must move it to before the optional parameters instead.", self.0.identifier.name)
|
write!(
|
||||||
|
f,
|
||||||
|
"KCL functions must declare any optional parameters after all the required parameters. But your required parameter {} is _after_ an optional parameter. You must move it to before the optional parameters instead.",
|
||||||
|
self.0.identifier.name
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
use super::CompilationError;
|
use super::CompilationError;
|
||||||
use crate::{
|
use crate::{
|
||||||
parsing::ast::types::{BinaryExpression, BinaryOperator, BinaryPart, Node},
|
|
||||||
SourceRange,
|
SourceRange,
|
||||||
|
parsing::ast::types::{BinaryExpression, BinaryOperator, BinaryPart, Node},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parses a list of tokens (in infix order, i.e. as the user typed them)
|
/// Parses a list of tokens (in infix order, i.e. as the user typed them)
|
||||||
@ -127,11 +127,11 @@ impl From<BinaryOperator> for BinaryExpressionToken {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ModuleId,
|
||||||
parsing::{
|
parsing::{
|
||||||
ast::types::{Literal, LiteralValue},
|
ast::types::{Literal, LiteralValue},
|
||||||
token::NumericSuffix,
|
token::NumericSuffix,
|
||||||
},
|
},
|
||||||
ModuleId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
ModuleId,
|
||||||
errors::{CompilationError, KclError, KclErrorDetails},
|
errors::{CompilationError, KclError, KclErrorDetails},
|
||||||
parsing::{
|
parsing::{
|
||||||
ast::types::{Node, Program},
|
ast::types::{Node, Program},
|
||||||
token::TokenStream,
|
token::TokenStream,
|
||||||
},
|
},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
ModuleId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) mod ast;
|
pub(crate) mod ast;
|
||||||
@ -18,7 +18,7 @@ pub const PIPE_OPERATOR: &str = "|>";
|
|||||||
|
|
||||||
// `?` like behavior for `Result`s to return a ParseResult if there is an error.
|
// `?` like behavior for `Result`s to return a ParseResult if there is an error.
|
||||||
macro_rules! pr_try {
|
macro_rules! pr_try {
|
||||||
($e: expr) => {
|
($e: expr_2021) => {
|
||||||
match $e {
|
match $e {
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(e) => return e.into(),
|
Err(e) => return e.into(),
|
||||||
@ -187,7 +187,7 @@ pub fn deprecation(s: &str, kind: DeprecationKind) -> Option<&'static str> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
macro_rules! parse_and_lex {
|
macro_rules! parse_and_lex {
|
||||||
($func_name:ident, $test_kcl_program:expr) => {
|
($func_name:ident, $test_kcl_program:expr_2021) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $func_name() {
|
fn $func_name() {
|
||||||
let _ = crate::parsing::top_level_parse($test_kcl_program);
|
let _ = crate::parsing::top_level_parse($test_kcl_program);
|
||||||
|
@ -14,14 +14,16 @@ use winnow::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
DeprecationKind,
|
||||||
ast::types::{AscribedExpression, ImportPath, LabelledExpression},
|
ast::types::{AscribedExpression, ImportPath, LabelledExpression},
|
||||||
token::{NumericSuffix, RESERVED_WORDS},
|
token::{NumericSuffix, RESERVED_WORDS},
|
||||||
DeprecationKind,
|
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
IMPORT_FILE_EXTENSIONS, SourceRange, TypedPath,
|
||||||
errors::{CompilationError, Severity, Tag},
|
errors::{CompilationError, Severity, Tag},
|
||||||
execution::types::ArrayLen,
|
execution::types::ArrayLen,
|
||||||
parsing::{
|
parsing::{
|
||||||
|
PIPE_OPERATOR, PIPE_SUBSTITUTION_OPERATOR,
|
||||||
ast::types::{
|
ast::types::{
|
||||||
Annotation, ArrayExpression, ArrayRangeExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem,
|
Annotation, ArrayExpression, ArrayRangeExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem,
|
||||||
BoxNode, CallExpressionKw, CommentStyle, DefaultParamVal, ElseIf, Expr, ExpressionStatement,
|
BoxNode, CallExpressionKw, CommentStyle, DefaultParamVal, ElseIf, Expr, ExpressionStatement,
|
||||||
@ -33,9 +35,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
math::BinaryExpressionToken,
|
math::BinaryExpressionToken,
|
||||||
token::{Token, TokenSlice, TokenType},
|
token::{Token, TokenSlice, TokenType},
|
||||||
PIPE_OPERATOR, PIPE_SUBSTITUTION_OPERATOR,
|
|
||||||
},
|
},
|
||||||
SourceRange, TypedPath, IMPORT_FILE_EXTENSIONS,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
@ -602,7 +602,7 @@ fn binary_operator(i: &mut TokenSlice) -> ModalResult<BinaryOperator> {
|
|||||||
return Err(CompilationError::fatal(
|
return Err(CompilationError::fatal(
|
||||||
token.as_source_range(),
|
token.as_source_range(),
|
||||||
format!("{} is not a binary operator", token.value.as_str()),
|
format!("{} is not a binary operator", token.value.as_str()),
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(op)
|
Ok(op)
|
||||||
@ -726,7 +726,7 @@ fn shebang(i: &mut TokenSlice) -> ModalResult<Node<Shebang>> {
|
|||||||
opt(whitespace).parse_next(i)?;
|
opt(whitespace).parse_next(i)?;
|
||||||
|
|
||||||
Ok(Node::new(
|
Ok(Node::new(
|
||||||
Shebang::new(format!("#!{}", value)),
|
Shebang::new(format!("#!{value}")),
|
||||||
0,
|
0,
|
||||||
tokens.last().unwrap().end,
|
tokens.last().unwrap().end,
|
||||||
tokens.first().unwrap().module_id,
|
tokens.first().unwrap().module_id,
|
||||||
@ -1926,7 +1926,7 @@ fn validate_path_string(path_string: String, var_name: bool, path_range: SourceR
|
|||||||
return Err(ErrMode::Cut(
|
return Err(ErrMode::Cut(
|
||||||
CompilationError::fatal(
|
CompilationError::fatal(
|
||||||
path_range,
|
path_range,
|
||||||
format!("Invalid import path for import from std: {}.", path_string),
|
format!("Invalid import path for import from std: {path_string}."),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
));
|
));
|
||||||
@ -1938,7 +1938,10 @@ fn validate_path_string(path_string: String, var_name: bool, path_range: SourceR
|
|||||||
if !IMPORT_FILE_EXTENSIONS.contains(&extn.to_string_lossy().to_string()) {
|
if !IMPORT_FILE_EXTENSIONS.contains(&extn.to_string_lossy().to_string()) {
|
||||||
ParseContext::warn(CompilationError::err(
|
ParseContext::warn(CompilationError::err(
|
||||||
path_range,
|
path_range,
|
||||||
format!("unsupported import path format. KCL files can be imported from the current project, CAD files with the following formats are supported: {}", IMPORT_FILE_EXTENSIONS.join(", ")),
|
format!(
|
||||||
|
"unsupported import path format. KCL files can be imported from the current project, CAD files with the following formats are supported: {}",
|
||||||
|
IMPORT_FILE_EXTENSIONS.join(", ")
|
||||||
|
),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
ImportPath::Foreign {
|
ImportPath::Foreign {
|
||||||
@ -2210,7 +2213,7 @@ fn declaration(i: &mut TokenSlice) -> ModalResult<BoxNode<VariableDeclaration>>
|
|||||||
if matches!(val, Expr::FunctionExpression(_)) {
|
if matches!(val, Expr::FunctionExpression(_)) {
|
||||||
return Err(CompilationError::fatal(
|
return Err(CompilationError::fatal(
|
||||||
SourceRange::new(start, dec_end, id.module_id),
|
SourceRange::new(start, dec_end, id.module_id),
|
||||||
format!("Expected a `fn` variable kind, found: `{}`", kind),
|
format!("Expected a `fn` variable kind, found: `{kind}`"),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(val)
|
Ok(val)
|
||||||
@ -3312,10 +3315,10 @@ fn fn_call_kw(i: &mut TokenSlice) -> ModalResult<Node<CallExpressionKw>> {
|
|||||||
ParseContext::warn(
|
ParseContext::warn(
|
||||||
CompilationError::err(
|
CompilationError::err(
|
||||||
result.as_source_range(),
|
result.as_source_range(),
|
||||||
format!("Calling `{}` is deprecated, prefer using `{}`.", callee_str, suggestion),
|
format!("Calling `{callee_str}` is deprecated, prefer using `{suggestion}`."),
|
||||||
)
|
)
|
||||||
.with_suggestion(
|
.with_suggestion(
|
||||||
format!("Replace `{}` with `{}`", callee_str, suggestion),
|
format!("Replace `{callee_str}` with `{suggestion}`"),
|
||||||
suggestion,
|
suggestion,
|
||||||
None,
|
None,
|
||||||
Tag::Deprecated,
|
Tag::Deprecated,
|
||||||
@ -3333,13 +3336,13 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
parsing::ast::types::{BodyItem, Expr, VariableKind},
|
|
||||||
ModuleId,
|
ModuleId,
|
||||||
|
parsing::ast::types::{BodyItem, Expr, VariableKind},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn assert_reserved(word: &str) {
|
fn assert_reserved(word: &str) {
|
||||||
// Try to use it as a variable name.
|
// Try to use it as a variable name.
|
||||||
let code = format!(r#"{} = 0"#, word);
|
let code = format!(r#"{word} = 0"#);
|
||||||
let result = crate::parsing::top_level_parse(code.as_str());
|
let result = crate::parsing::top_level_parse(code.as_str());
|
||||||
let err = &result.unwrap_errs().next().unwrap();
|
let err = &result.unwrap_errs().next().unwrap();
|
||||||
// Which token causes the error may change. In "return = 0", for
|
// Which token causes the error may change. In "return = 0", for
|
||||||
@ -5263,7 +5266,7 @@ mod snapshot_math_tests {
|
|||||||
// The macro takes a KCL program, ensures it tokenizes and parses, then compares
|
// The macro takes a KCL program, ensures it tokenizes and parses, then compares
|
||||||
// its parsed AST to a snapshot (kept in this repo in a file under snapshots/ dir)
|
// its parsed AST to a snapshot (kept in this repo in a file under snapshots/ dir)
|
||||||
macro_rules! snapshot_test {
|
macro_rules! snapshot_test {
|
||||||
($func_name:ident, $test_kcl_program:expr) => {
|
($func_name:ident, $test_kcl_program:expr_2021) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $func_name() {
|
fn $func_name() {
|
||||||
let module_id = crate::ModuleId::default();
|
let module_id = crate::ModuleId::default();
|
||||||
@ -5301,7 +5304,7 @@ mod snapshot_tests {
|
|||||||
// The macro takes a KCL program, ensures it tokenizes and parses, then compares
|
// The macro takes a KCL program, ensures it tokenizes and parses, then compares
|
||||||
// its parsed AST to a snapshot (kept in this repo in a file under snapshots/ dir)
|
// its parsed AST to a snapshot (kept in this repo in a file under snapshots/ dir)
|
||||||
macro_rules! snapshot_test {
|
macro_rules! snapshot_test {
|
||||||
($func_name:ident, $test_kcl_program:expr) => {
|
($func_name:ident, $test_kcl_program:expr_2021) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $func_name() {
|
fn $func_name() {
|
||||||
let module_id = crate::ModuleId::default();
|
let module_id = crate::ModuleId::default();
|
||||||
|
@ -16,10 +16,10 @@ use winnow::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
CompilationError, ModuleId,
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
parsing::ast::types::{ItemVisibility, VariableKind},
|
parsing::ast::types::{ItemVisibility, VariableKind},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
CompilationError, ModuleId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mod tokeniser;
|
mod tokeniser;
|
||||||
@ -609,7 +609,7 @@ impl From<ParseError<Input<'_>, winnow::error::ContextError>> for KclError {
|
|||||||
// TODO: Add the Winnow parser context to the error.
|
// TODO: Add the Winnow parser context to the error.
|
||||||
// See https://github.com/KittyCAD/modeling-app/issues/784
|
// See https://github.com/KittyCAD/modeling-app/issues/784
|
||||||
KclError::new_lexical(crate::errors::KclErrorDetails::new(
|
KclError::new_lexical(crate::errors::KclErrorDetails::new(
|
||||||
format!("found unknown token '{}'", bad_token),
|
format!("found unknown token '{bad_token}'"),
|
||||||
vec![SourceRange::new(offset, offset + 1, module_id)],
|
vec![SourceRange::new(offset, offset + 1, module_id)],
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use winnow::{
|
use winnow::{
|
||||||
|
LocatingSlice, Stateful,
|
||||||
ascii::{digit1, multispace1},
|
ascii::{digit1, multispace1},
|
||||||
combinator::{alt, opt, peek, preceded, repeat},
|
combinator::{alt, opt, peek, preceded, repeat},
|
||||||
error::{ContextError, ParseError},
|
error::{ContextError, ParseError},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
stream::{Location, Stream},
|
stream::{Location, Stream},
|
||||||
token::{any, none_of, take_till, take_until, take_while},
|
token::{any, none_of, take_till, take_until, take_while},
|
||||||
LocatingSlice, Stateful,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::TokenStream;
|
use super::TokenStream;
|
||||||
use crate::{
|
use crate::{
|
||||||
parsing::token::{Token, TokenType},
|
|
||||||
ModuleId,
|
ModuleId,
|
||||||
|
parsing::token::{Token, TokenType},
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use schemars::{gen::SchemaGenerator, JsonSchema};
|
use schemars::{JsonSchema, r#gen::SchemaGenerator};
|
||||||
use serde_json::{json, Value};
|
use serde_json::{Value, json};
|
||||||
|
|
||||||
use crate::settings::types::{project::ProjectConfiguration, Configuration};
|
use crate::settings::types::{Configuration, project::ProjectConfiguration};
|
||||||
|
|
||||||
// Project settings example in TOML format
|
// Project settings example in TOML format
|
||||||
const PROJECT_SETTINGS_EXAMPLE: &str = r#"[settings.app]
|
const PROJECT_SETTINGS_EXAMPLE: &str = r#"[settings.app]
|
||||||
@ -60,7 +60,7 @@ fn init_handlebars() -> handlebars::Handlebars<'static> {
|
|||||||
let pretty_options = array
|
let pretty_options = array
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|v| v.as_str())
|
.filter_map(|v| v.as_str())
|
||||||
.map(|s| format!("`{}`", s))
|
.map(|s| format!("`{s}`"))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
out.write(&pretty_options)?;
|
out.write(&pretty_options)?;
|
||||||
@ -89,17 +89,17 @@ fn init_handlebars() -> handlebars::Handlebars<'static> {
|
|||||||
Value::Null => out.write("None")?,
|
Value::Null => out.write("None")?,
|
||||||
Value::Bool(b) => out.write(&b.to_string())?,
|
Value::Bool(b) => out.write(&b.to_string())?,
|
||||||
Value::Number(n) => out.write(&n.to_string())?,
|
Value::Number(n) => out.write(&n.to_string())?,
|
||||||
Value::String(s) => out.write(&format!("`{}`", s))?,
|
Value::String(s) => out.write(&format!("`{s}`"))?,
|
||||||
Value::Array(arr) => {
|
Value::Array(arr) => {
|
||||||
let formatted = arr
|
let formatted = arr
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| match v {
|
.map(|v| match v {
|
||||||
Value::String(s) => format!("`{}`", s),
|
Value::String(s) => format!("`{s}`"),
|
||||||
_ => format!("{}", v),
|
_ => format!("{v}"),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
out.write(&format!("[{}]", formatted))?;
|
out.write(&format!("[{formatted}]"))?;
|
||||||
}
|
}
|
||||||
Value::Object(_) => out.write("(complex default)")?,
|
Value::Object(_) => out.write("(complex default)")?,
|
||||||
}
|
}
|
||||||
@ -122,7 +122,7 @@ pub fn generate_settings_docs() {
|
|||||||
let hbs = init_handlebars();
|
let hbs = init_handlebars();
|
||||||
|
|
||||||
// Generate project settings documentation
|
// Generate project settings documentation
|
||||||
let mut settings = schemars::gen::SchemaSettings::default();
|
let mut settings = schemars::r#gen::SchemaSettings::default();
|
||||||
settings.inline_subschemas = true;
|
settings.inline_subschemas = true;
|
||||||
settings.meta_schema = None; // We don't need the meta schema for docs
|
settings.meta_schema = None; // We don't need the meta schema for docs
|
||||||
settings.option_nullable = false; // Important - makes Option fields show properly
|
settings.option_nullable = false; // Important - makes Option fields show properly
|
||||||
|
@ -716,13 +716,15 @@ enable_ssao = false
|
|||||||
|
|
||||||
let result = color.validate();
|
let result = color.validate();
|
||||||
if let Ok(r) = result {
|
if let Ok(r) = result {
|
||||||
panic!("Expected an error, but got success: {:?}", r);
|
panic!("Expected an error, but got success: {r:?}");
|
||||||
}
|
}
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert!(result
|
assert!(
|
||||||
|
result
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.to_string()
|
.to_string()
|
||||||
.contains("color: Validation error: color"));
|
.contains("color: Validation error: color")
|
||||||
|
);
|
||||||
|
|
||||||
let appearance = AppearanceSettings {
|
let appearance = AppearanceSettings {
|
||||||
theme: AppTheme::System,
|
theme: AppTheme::System,
|
||||||
@ -730,13 +732,15 @@ enable_ssao = false
|
|||||||
};
|
};
|
||||||
let result = appearance.validate();
|
let result = appearance.validate();
|
||||||
if let Ok(r) = result {
|
if let Ok(r) = result {
|
||||||
panic!("Expected an error, but got success: {:?}", r);
|
panic!("Expected an error, but got success: {r:?}");
|
||||||
}
|
}
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert!(result
|
assert!(
|
||||||
|
result
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.to_string()
|
.to_string()
|
||||||
.contains("color: Validation error: color"));
|
.contains("color: Validation error: color")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -746,13 +750,15 @@ color = 1567.4"#;
|
|||||||
|
|
||||||
let result = Configuration::parse_and_validate(settings_file);
|
let result = Configuration::parse_and_validate(settings_file);
|
||||||
if let Ok(r) = result {
|
if let Ok(r) = result {
|
||||||
panic!("Expected an error, but got success: {:?}", r);
|
panic!("Expected an error, but got success: {r:?}");
|
||||||
}
|
}
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
|
||||||
assert!(result
|
assert!(
|
||||||
|
result
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.to_string()
|
.to_string()
|
||||||
.contains("color: Validation error: color"));
|
.contains("color: Validation error: color")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
use crate::settings::types::{
|
use crate::settings::types::{
|
||||||
is_default, AppColor, CommandBarSettings, DefaultTrue, OnboardingStatus, TextEditorSettings, UnitLength,
|
AppColor, CommandBarSettings, DefaultTrue, OnboardingStatus, TextEditorSettings, UnitLength, is_default,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Project specific settings for the app.
|
/// Project specific settings for the app.
|
||||||
@ -203,14 +203,16 @@ color = 1567.4"#;
|
|||||||
|
|
||||||
let result = ProjectConfiguration::parse_and_validate(settings_file);
|
let result = ProjectConfiguration::parse_and_validate(settings_file);
|
||||||
if let Ok(r) = result {
|
if let Ok(r) = result {
|
||||||
panic!("Expected an error, but got success: {:?}", r);
|
panic!("Expected an error, but got success: {r:?}");
|
||||||
}
|
}
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
|
||||||
assert!(result
|
assert!(
|
||||||
|
result
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.to_string()
|
.to_string()
|
||||||
.contains("color: Validation error: color"));
|
.contains("color: Validation error: color")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
use std::{
|
use std::{
|
||||||
panic::{catch_unwind, AssertUnwindSafe},
|
panic::{AssertUnwindSafe, catch_unwind},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ExecOutcome, ExecState, ExecutorContext, ModuleId,
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
execution::{EnvironmentRef, ModuleArtifactState},
|
execution::{EnvironmentRef, ModuleArtifactState},
|
||||||
ExecOutcome, ExecState, ExecutorContext, ModuleId,
|
|
||||||
};
|
};
|
||||||
#[cfg(feature = "artifact-graph")]
|
#[cfg(feature = "artifact-graph")]
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -241,7 +241,10 @@ async fn execute_test(test: &Test, render_to_png: bool, export_step: bool) {
|
|||||||
Ok((exec_state, ctx, env_ref, png, step)) => {
|
Ok((exec_state, ctx, env_ref, png, step)) => {
|
||||||
let fail_path = test.output_dir.join("execution_error.snap");
|
let fail_path = test.output_dir.join("execution_error.snap");
|
||||||
if std::fs::exists(&fail_path).unwrap() {
|
if std::fs::exists(&fail_path).unwrap() {
|
||||||
panic!("This test case is expected to fail, but it passed. If this is intended, and the test should actually be passing now, please delete kcl-lib/{}", fail_path.to_string_lossy())
|
panic!(
|
||||||
|
"This test case is expected to fail, but it passed. If this is intended, and the test should actually be passing now, please delete kcl-lib/{}",
|
||||||
|
fail_path.to_string_lossy()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if render_to_png {
|
if render_to_png {
|
||||||
twenty_twenty::assert_image(test.output_dir.join(RENDERED_MODEL_NAME), &png, 0.99);
|
twenty_twenty::assert_image(test.output_dir.join(RENDERED_MODEL_NAME), &png, 0.99);
|
||||||
@ -287,10 +290,13 @@ async fn execute_test(test: &Test, render_to_png: bool, export_step: bool) {
|
|||||||
let report = error.clone().into_miette_report_with_outputs(&input).unwrap();
|
let report = error.clone().into_miette_report_with_outputs(&input).unwrap();
|
||||||
let report = miette::Report::new(report);
|
let report = miette::Report::new(report);
|
||||||
if previously_passed {
|
if previously_passed {
|
||||||
eprintln!("This test case failed, but it previously passed. If this is intended, and the test should actually be failing now, please delete kcl-lib/{} and other associated passing artifacts", ok_path.to_string_lossy());
|
eprintln!(
|
||||||
|
"This test case failed, but it previously passed. If this is intended, and the test should actually be failing now, please delete kcl-lib/{} and other associated passing artifacts",
|
||||||
|
ok_path.to_string_lossy()
|
||||||
|
);
|
||||||
panic!("{report:?}");
|
panic!("{report:?}");
|
||||||
}
|
}
|
||||||
let report = format!("{:?}", report);
|
let report = format!("{report:?}");
|
||||||
|
|
||||||
let err_result = catch_unwind(AssertUnwindSafe(|| {
|
let err_result = catch_unwind(AssertUnwindSafe(|| {
|
||||||
assert_snapshot(test, "Error from executing", || {
|
assert_snapshot(test, "Error from executing", || {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Run all the KCL samples in the `kcl_samples` directory.
|
//! Run all the KCL samples in the `kcl_samples` directory.
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
panic::{catch_unwind, AssertUnwindSafe},
|
panic::{AssertUnwindSafe, catch_unwind},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -86,7 +86,11 @@ fn test_after_engine_ensure_kcl_samples_manifest_etc() {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|name| !input_names.contains(name))
|
.filter(|name| !input_names.contains(name))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
assert!(missing.is_empty(), "Expected input kcl-samples for the following. If these are no longer tests, delete the expected output directories for them in {}: {missing:?}", OUTPUTS_DIR.to_string_lossy());
|
assert!(
|
||||||
|
missing.is_empty(),
|
||||||
|
"Expected input kcl-samples for the following. If these are no longer tests, delete the expected output directories for them in {}: {missing:?}",
|
||||||
|
OUTPUTS_DIR.to_string_lossy()
|
||||||
|
);
|
||||||
|
|
||||||
// We want to move the screenshot for the inputs to the public/kcl-samples
|
// We want to move the screenshot for the inputs to the public/kcl-samples
|
||||||
// directory so that they can be used as inputs for the next run.
|
// directory so that they can be used as inputs for the next run.
|
||||||
@ -189,7 +193,7 @@ fn kcl_samples_inputs() -> Vec<Test> {
|
|||||||
let entry_point = if main_kcl_path.exists() {
|
let entry_point = if main_kcl_path.exists() {
|
||||||
main_kcl_path
|
main_kcl_path
|
||||||
} else {
|
} else {
|
||||||
panic!("No main.kcl found in {:?}", sub_dir);
|
panic!("No main.kcl found in {sub_dir:?}");
|
||||||
};
|
};
|
||||||
tests.push(test(&dir_name_str, entry_point));
|
tests.push(test(&dir_name_str, entry_point));
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Standard library appearance.
|
//! Standard library appearance.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{each_cmd as mcmd, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd};
|
||||||
use kittycad_modeling_cmds::{self as kcmc, shared::Color};
|
use kittycad_modeling_cmds::{self as kcmc, shared::Color};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rgba_simple::Hex;
|
use rgba_simple::Hex;
|
||||||
@ -10,8 +10,8 @@ use super::args::TyF64;
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{ArrayLen, RuntimeType},
|
|
||||||
ExecState, KclValue, SolidOrImportedGeometry,
|
ExecState, KclValue, SolidOrImportedGeometry,
|
||||||
|
types::{ArrayLen, RuntimeType},
|
||||||
},
|
},
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
@ -63,7 +63,7 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
|||||||
// Make sure the color if set is valid.
|
// Make sure the color if set is valid.
|
||||||
if !HEX_REGEX.is_match(&color) {
|
if !HEX_REGEX.is_match(&color) {
|
||||||
return Err(KclError::new_semantic(KclErrorDetails::new(
|
return Err(KclError::new_semantic(KclErrorDetails::new(
|
||||||
format!("Invalid hex color (`{}`), try something like `#fff000`", color),
|
format!("Invalid hex color (`{color}`), try something like `#fff000`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,13 @@ use serde::Serialize;
|
|||||||
use super::fillet::EdgeReference;
|
use super::fillet::EdgeReference;
|
||||||
pub use crate::execution::fn_call::Args;
|
pub use crate::execution::fn_call::Args;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ModuleId,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
kcl_value::FunctionSource,
|
|
||||||
types::{NumericType, PrimitiveType, RuntimeType, UnitAngle, UnitLen, UnitType},
|
|
||||||
ExecState, ExtrudeSurface, Helix, KclObjectFields, KclValue, Metadata, PlaneInfo, Sketch, SketchSurface, Solid,
|
ExecState, ExtrudeSurface, Helix, KclObjectFields, KclValue, Metadata, PlaneInfo, Sketch, SketchSurface, Solid,
|
||||||
TagIdentifier,
|
TagIdentifier,
|
||||||
|
kcl_value::FunctionSource,
|
||||||
|
types::{NumericType, PrimitiveType, RuntimeType, UnitAngle, UnitLen, UnitType},
|
||||||
},
|
},
|
||||||
parsing::ast::types::TagNode,
|
parsing::ast::types::TagNode,
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
@ -21,7 +22,6 @@ use crate::{
|
|||||||
sketch::FaceTag,
|
sketch::FaceTag,
|
||||||
sweep::SweepPath,
|
sweep::SweepPath,
|
||||||
},
|
},
|
||||||
ModuleId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ERROR_STRING_SKETCH_TO_SOLID_HELPER: &str =
|
const ERROR_STRING_SKETCH_TO_SOLID_HELPER: &str =
|
||||||
@ -97,8 +97,8 @@ impl JsonSchema for TyF64 {
|
|||||||
"TyF64".to_string()
|
"TyF64".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||||
gen.subschema_for::<f64>()
|
r#gen.subschema_for::<f64>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ExecutorContext,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
|
ExecState,
|
||||||
fn_call::{Arg, Args, KwArgs},
|
fn_call::{Arg, Args, KwArgs},
|
||||||
kcl_value::{FunctionSource, KclValue},
|
kcl_value::{FunctionSource, KclValue},
|
||||||
types::RuntimeType,
|
types::RuntimeType,
|
||||||
ExecState,
|
|
||||||
},
|
},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
ExecutorContext,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Apply a function to each element of an array.
|
/// Apply a function to each element of an array.
|
||||||
|
@ -5,14 +5,14 @@ use anyhow::Result;
|
|||||||
use super::args::TyF64;
|
use super::args::TyF64;
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{types::RuntimeType, ExecState, KclValue},
|
execution::{ExecState, KclValue, types::RuntimeType},
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
|
|
||||||
async fn _assert(value: bool, message: &str, args: &Args) -> Result<(), KclError> {
|
async fn _assert(value: bool, message: &str, args: &Args) -> Result<(), KclError> {
|
||||||
if !value {
|
if !value {
|
||||||
return Err(KclError::new_type(KclErrorDetails::new(
|
return Err(KclError::new_type(KclErrorDetails::new(
|
||||||
format!("assert failed: {}", message),
|
format!("assert failed: {message}"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
//! Standard library chamfers.
|
//! Standard library chamfers.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::CutType, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd, length_unit::LengthUnit, shared::CutType};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
|
|
||||||
use super::args::TyF64;
|
use super::args::TyF64;
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::RuntimeType, ChamferSurface, EdgeCut, ExecState, ExtrudeSurface, GeoMeta, KclValue, ModelingCmdMeta,
|
ChamferSurface, EdgeCut, ExecState, ExtrudeSurface, GeoMeta, KclValue, ModelingCmdMeta, Solid,
|
||||||
Solid,
|
types::RuntimeType,
|
||||||
},
|
},
|
||||||
parsing::ast::types::TagNode,
|
parsing::ast::types::TagNode,
|
||||||
std::{fillet::EdgeReference, Args},
|
std::{Args, fillet::EdgeReference},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) const DEFAULT_TOLERANCE: f64 = 0.0000001;
|
pub(crate) const DEFAULT_TOLERANCE: f64 = 0.0000001;
|
||||||
|
@ -4,10 +4,9 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{
|
use kcmc::{
|
||||||
each_cmd as mcmd,
|
ModelingCmd, each_cmd as mcmd,
|
||||||
ok_response::{output::EntityGetAllChildUuids, OkModelingCmdResponse},
|
ok_response::{OkModelingCmdResponse, output::EntityGetAllChildUuids},
|
||||||
websocket::OkWebSocketResponseData,
|
websocket::OkWebSocketResponseData,
|
||||||
ModelingCmd,
|
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds::{self as kcmc};
|
use kittycad_modeling_cmds::{self as kcmc};
|
||||||
|
|
||||||
@ -15,11 +14,11 @@ use super::extrude::do_post_extrude;
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{NumericType, PrimitiveType, RuntimeType},
|
|
||||||
ExecState, GeometryWithImportedGeometry, KclValue, ModelingCmdMeta, Sketch, Solid,
|
ExecState, GeometryWithImportedGeometry, KclValue, ModelingCmdMeta, Sketch, Solid,
|
||||||
|
types::{NumericType, PrimitiveType, RuntimeType},
|
||||||
},
|
},
|
||||||
parsing::ast::types::TagNode,
|
parsing::ast::types::TagNode,
|
||||||
std::{extrude::NamedCapTags, Args},
|
std::{Args, extrude::NamedCapTags},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Clone a sketch or solid.
|
/// Clone a sketch or solid.
|
||||||
@ -91,7 +90,7 @@ async fn inner_clone(
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
KclError::new_internal(KclErrorDetails::new(
|
KclError::new_internal(KclErrorDetails::new(
|
||||||
format!("failed to fix tags and references: {:?}", e),
|
format!("failed to fix tags and references: {e:?}"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -320,10 +319,10 @@ clonedCube = clone(cube)
|
|||||||
assert_ne!(cube, cloned_cube);
|
assert_ne!(cube, cloned_cube);
|
||||||
|
|
||||||
let KclValue::Sketch { value: cube } = cube else {
|
let KclValue::Sketch { value: cube } = cube else {
|
||||||
panic!("Expected a sketch, got: {:?}", cube);
|
panic!("Expected a sketch, got: {cube:?}");
|
||||||
};
|
};
|
||||||
let KclValue::Sketch { value: cloned_cube } = cloned_cube else {
|
let KclValue::Sketch { value: cloned_cube } = cloned_cube else {
|
||||||
panic!("Expected a sketch, got: {:?}", cloned_cube);
|
panic!("Expected a sketch, got: {cloned_cube:?}");
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ne!(cube.id, cloned_cube.id);
|
assert_ne!(cube.id, cloned_cube.id);
|
||||||
@ -369,10 +368,10 @@ clonedCube = clone(cube)
|
|||||||
assert_ne!(cube, cloned_cube);
|
assert_ne!(cube, cloned_cube);
|
||||||
|
|
||||||
let KclValue::Solid { value: cube } = cube else {
|
let KclValue::Solid { value: cube } = cube else {
|
||||||
panic!("Expected a solid, got: {:?}", cube);
|
panic!("Expected a solid, got: {cube:?}");
|
||||||
};
|
};
|
||||||
let KclValue::Solid { value: cloned_cube } = cloned_cube else {
|
let KclValue::Solid { value: cloned_cube } = cloned_cube else {
|
||||||
panic!("Expected a solid, got: {:?}", cloned_cube);
|
panic!("Expected a solid, got: {cloned_cube:?}");
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ne!(cube.id, cloned_cube.id);
|
assert_ne!(cube.id, cloned_cube.id);
|
||||||
@ -427,10 +426,10 @@ clonedCube = clone(cube)
|
|||||||
assert_ne!(cube, cloned_cube);
|
assert_ne!(cube, cloned_cube);
|
||||||
|
|
||||||
let KclValue::Sketch { value: cube } = cube else {
|
let KclValue::Sketch { value: cube } = cube else {
|
||||||
panic!("Expected a sketch, got: {:?}", cube);
|
panic!("Expected a sketch, got: {cube:?}");
|
||||||
};
|
};
|
||||||
let KclValue::Sketch { value: cloned_cube } = cloned_cube else {
|
let KclValue::Sketch { value: cloned_cube } = cloned_cube else {
|
||||||
panic!("Expected a sketch, got: {:?}", cloned_cube);
|
panic!("Expected a sketch, got: {cloned_cube:?}");
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ne!(cube.id, cloned_cube.id);
|
assert_ne!(cube.id, cloned_cube.id);
|
||||||
@ -483,10 +482,10 @@ clonedCube = clone(cube)
|
|||||||
assert_ne!(cube, cloned_cube);
|
assert_ne!(cube, cloned_cube);
|
||||||
|
|
||||||
let KclValue::Solid { value: cube } = cube else {
|
let KclValue::Solid { value: cube } = cube else {
|
||||||
panic!("Expected a solid, got: {:?}", cube);
|
panic!("Expected a solid, got: {cube:?}");
|
||||||
};
|
};
|
||||||
let KclValue::Solid { value: cloned_cube } = cloned_cube else {
|
let KclValue::Solid { value: cloned_cube } = cloned_cube else {
|
||||||
panic!("Expected a solid, got: {:?}", cloned_cube);
|
panic!("Expected a solid, got: {cloned_cube:?}");
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ne!(cube.id, cloned_cube.id);
|
assert_ne!(cube.id, cloned_cube.id);
|
||||||
@ -555,10 +554,10 @@ clonedCube = clone(cube)
|
|||||||
assert_ne!(cube, cloned_cube);
|
assert_ne!(cube, cloned_cube);
|
||||||
|
|
||||||
let KclValue::Solid { value: cube } = cube else {
|
let KclValue::Solid { value: cube } = cube else {
|
||||||
panic!("Expected a solid, got: {:?}", cube);
|
panic!("Expected a solid, got: {cube:?}");
|
||||||
};
|
};
|
||||||
let KclValue::Solid { value: cloned_cube } = cloned_cube else {
|
let KclValue::Solid { value: cloned_cube } = cloned_cube else {
|
||||||
panic!("Expected a solid, got: {:?}", cloned_cube);
|
panic!("Expected a solid, got: {cloned_cube:?}");
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ne!(cube.id, cloned_cube.id);
|
assert_ne!(cube.id, cloned_cube.id);
|
||||||
@ -655,10 +654,10 @@ clonedCube = clone(cube)
|
|||||||
assert_ne!(cube, cloned_cube);
|
assert_ne!(cube, cloned_cube);
|
||||||
|
|
||||||
let KclValue::Solid { value: cube } = cube else {
|
let KclValue::Solid { value: cube } = cube else {
|
||||||
panic!("Expected a solid, got: {:?}", cube);
|
panic!("Expected a solid, got: {cube:?}");
|
||||||
};
|
};
|
||||||
let KclValue::Solid { value: cloned_cube } = cloned_cube else {
|
let KclValue::Solid { value: cloned_cube } = cloned_cube else {
|
||||||
panic!("Expected a solid, got: {:?}", cloned_cube);
|
panic!("Expected a solid, got: {cloned_cube:?}");
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ne!(cube.id, cloned_cube.id);
|
assert_ne!(cube.id, cloned_cube.id);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Constructive Solid Geometry (CSG) operations.
|
//! Constructive Solid Geometry (CSG) operations.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd, length_unit::LengthUnit};
|
||||||
use kittycad_modeling_cmds::{
|
use kittycad_modeling_cmds::{
|
||||||
self as kcmc,
|
self as kcmc,
|
||||||
ok_response::OkModelingCmdResponse,
|
ok_response::OkModelingCmdResponse,
|
||||||
@ -9,11 +9,11 @@ use kittycad_modeling_cmds::{
|
|||||||
websocket::OkWebSocketResponseData,
|
websocket::OkWebSocketResponseData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{args::TyF64, DEFAULT_TOLERANCE_MM};
|
use super::{DEFAULT_TOLERANCE_MM, args::TyF64};
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{types::RuntimeType, ExecState, KclValue, ModelingCmdMeta, Solid},
|
execution::{ExecState, KclValue, ModelingCmdMeta, Solid, types::RuntimeType},
|
||||||
std::{patterns::GeometryTrait, Args},
|
std::{Args, patterns::GeometryTrait},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Union two or more solids into a single solid.
|
/// Union two or more solids into a single solid.
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
//! Edge helper functions.
|
//! Edge helper functions.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{each_cmd as mcmd, ok_response::OkModelingCmdResponse, websocket::OkWebSocketResponseData, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd, ok_response::OkModelingCmdResponse, websocket::OkWebSocketResponseData};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
SourceRange,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{ArrayLen, RuntimeType},
|
|
||||||
ExecState, ExtrudeSurface, KclValue, ModelingCmdMeta, TagIdentifier,
|
ExecState, ExtrudeSurface, KclValue, ModelingCmdMeta, TagIdentifier,
|
||||||
|
types::{ArrayLen, RuntimeType},
|
||||||
},
|
},
|
||||||
std::{sketch::FaceTag, Args},
|
std::{Args, sketch::FaceTag},
|
||||||
SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Get the opposite edge to the edge given.
|
/// Get the opposite edge to the edge given.
|
||||||
@ -55,7 +55,7 @@ async fn inner_get_opposite_edge(
|
|||||||
} = &resp
|
} = &resp
|
||||||
else {
|
else {
|
||||||
return Err(KclError::new_engine(KclErrorDetails::new(
|
return Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("mcmd::Solid3dGetOppositeEdge response was not as expected: {:?}", resp),
|
format!("mcmd::Solid3dGetOppositeEdge response was not as expected: {resp:?}"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
@ -104,10 +104,7 @@ async fn inner_get_next_adjacent_edge(
|
|||||||
} = &resp
|
} = &resp
|
||||||
else {
|
else {
|
||||||
return Err(KclError::new_engine(KclErrorDetails::new(
|
return Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!(
|
format!("mcmd::Solid3dGetNextAdjacentEdge response was not as expected: {resp:?}"),
|
||||||
"mcmd::Solid3dGetNextAdjacentEdge response was not as expected: {:?}",
|
|
||||||
resp
|
|
||||||
),
|
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
@ -160,10 +157,7 @@ async fn inner_get_previous_adjacent_edge(
|
|||||||
} = &resp
|
} = &resp
|
||||||
else {
|
else {
|
||||||
return Err(KclError::new_engine(KclErrorDetails::new(
|
return Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!(
|
format!("mcmd::Solid3dGetPrevAdjacentEdge response was not as expected: {resp:?}"),
|
||||||
"mcmd::Solid3dGetPrevAdjacentEdge response was not as expected: {:?}",
|
|
||||||
resp
|
|
||||||
),
|
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
@ -259,7 +253,7 @@ async fn inner_get_common_edge(
|
|||||||
} = &resp
|
} = &resp
|
||||||
else {
|
else {
|
||||||
return Err(KclError::new_engine(KclErrorDetails::new(
|
return Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("mcmd::Solid3dGetCommonEdge response was not as expected: {:?}", resp),
|
format!("mcmd::Solid3dGetCommonEdge response was not as expected: {resp:?}"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
@ -4,13 +4,12 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{
|
use kcmc::{
|
||||||
each_cmd as mcmd,
|
ModelingCmd, each_cmd as mcmd,
|
||||||
length_unit::LengthUnit,
|
length_unit::LengthUnit,
|
||||||
ok_response::OkModelingCmdResponse,
|
ok_response::OkModelingCmdResponse,
|
||||||
output::ExtrusionFaceInfo,
|
output::ExtrusionFaceInfo,
|
||||||
shared::{ExtrusionFaceCapType, Opposite},
|
shared::{ExtrusionFaceCapType, Opposite},
|
||||||
websocket::{ModelingCmdReq, OkWebSocketResponseData},
|
websocket::{ModelingCmdReq, OkWebSocketResponseData},
|
||||||
ModelingCmd,
|
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds::{
|
use kittycad_modeling_cmds::{
|
||||||
self as kcmc,
|
self as kcmc,
|
||||||
@ -18,12 +17,12 @@ use kittycad_modeling_cmds::{
|
|||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{args::TyF64, utils::point_to_mm, DEFAULT_TOLERANCE_MM};
|
use super::{DEFAULT_TOLERANCE_MM, args::TyF64, utils::point_to_mm};
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::RuntimeType, ArtifactId, ExecState, ExtrudeSurface, GeoMeta, KclValue, ModelingCmdMeta, Path, Sketch,
|
ArtifactId, ExecState, ExtrudeSurface, GeoMeta, KclValue, ModelingCmdMeta, Path, Sketch, SketchSurface, Solid,
|
||||||
SketchSurface, Solid,
|
types::RuntimeType,
|
||||||
},
|
},
|
||||||
parsing::ast::types::TagNode,
|
parsing::ast::types::TagNode,
|
||||||
std::Args,
|
std::Args,
|
||||||
|
@ -2,20 +2,20 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::CutType, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd, length_unit::LengthUnit, shared::CutType};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{args::TyF64, DEFAULT_TOLERANCE_MM};
|
use super::{DEFAULT_TOLERANCE_MM, args::TyF64};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
SourceRange,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::RuntimeType, EdgeCut, ExecState, ExtrudeSurface, FilletSurface, GeoMeta, KclValue, ModelingCmdMeta,
|
EdgeCut, ExecState, ExtrudeSurface, FilletSurface, GeoMeta, KclValue, ModelingCmdMeta, Solid, TagIdentifier,
|
||||||
Solid, TagIdentifier,
|
types::RuntimeType,
|
||||||
},
|
},
|
||||||
parsing::ast::types::TagNode,
|
parsing::ast::types::TagNode,
|
||||||
std::Args,
|
std::Args,
|
||||||
SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A tag or a uuid of an edge.
|
/// A tag or a uuid of an edge.
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
//! Standard library helices.
|
//! Standard library helices.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd, length_unit::LengthUnit, shared::Angle};
|
||||||
use kittycad_modeling_cmds::{self as kcmc, shared::Point3d};
|
use kittycad_modeling_cmds::{self as kcmc, shared::Point3d};
|
||||||
|
|
||||||
use super::args::TyF64;
|
use super::args::TyF64;
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{PrimitiveType, RuntimeType},
|
|
||||||
ExecState, Helix as HelixValue, KclValue, ModelingCmdMeta, Solid,
|
ExecState, Helix as HelixValue, KclValue, ModelingCmdMeta, Solid,
|
||||||
|
types::{PrimitiveType, RuntimeType},
|
||||||
},
|
},
|
||||||
std::{axis_or_reference::Axis3dOrEdgeReference, Args},
|
std::{Args, axis_or_reference::Axis3dOrEdgeReference},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Create a helix.
|
/// Create a helix.
|
||||||
|
@ -3,18 +3,18 @@
|
|||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd, length_unit::LengthUnit};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
|
|
||||||
use super::{args::TyF64, DEFAULT_TOLERANCE_MM};
|
use super::{DEFAULT_TOLERANCE_MM, args::TyF64};
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{NumericType, RuntimeType},
|
|
||||||
ExecState, KclValue, ModelingCmdMeta, Sketch, Solid,
|
ExecState, KclValue, ModelingCmdMeta, Sketch, Solid,
|
||||||
|
types::{NumericType, RuntimeType},
|
||||||
},
|
},
|
||||||
parsing::ast::types::TagNode,
|
parsing::ast::types::TagNode,
|
||||||
std::{extrude::do_post_extrude, Args},
|
std::{Args, extrude::do_post_extrude},
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_V_DEGREE: u32 = 2;
|
const DEFAULT_V_DEGREE: u32 = 2;
|
||||||
|
@ -3,13 +3,13 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
CompilationError,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{ArrayLen, NumericType, RuntimeType},
|
|
||||||
ExecState, KclValue,
|
ExecState, KclValue,
|
||||||
|
types::{ArrayLen, NumericType, RuntimeType},
|
||||||
},
|
},
|
||||||
std::args::{Args, TyF64},
|
std::args::{Args, TyF64},
|
||||||
CompilationError,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Compute the remainder after dividing `num` by `div`.
|
/// Compute the remainder after dividing `num` by `div`.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Standard library mirror.
|
//! Standard library mirror.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{each_cmd as mcmd, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd};
|
||||||
use kittycad_modeling_cmds::{
|
use kittycad_modeling_cmds::{
|
||||||
self as kcmc, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, shared::Point3d,
|
self as kcmc, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, shared::Point3d,
|
||||||
websocket::OkWebSocketResponseData,
|
websocket::OkWebSocketResponseData,
|
||||||
@ -10,10 +10,10 @@ use kittycad_modeling_cmds::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{PrimitiveType, RuntimeType},
|
|
||||||
ExecState, KclValue, Sketch,
|
ExecState, KclValue, Sketch,
|
||||||
|
types::{PrimitiveType, RuntimeType},
|
||||||
},
|
},
|
||||||
std::{axis_or_reference::Axis2dOrEdgeReference, Args},
|
std::{Args, axis_or_reference::Axis2dOrEdgeReference},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Mirror a sketch.
|
/// Mirror a sketch.
|
||||||
@ -84,14 +84,14 @@ async fn inner_mirror_2d(
|
|||||||
return Err(KclError::new_engine(KclErrorDetails::new(
|
return Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
"No edges found in mirror info".to_string(),
|
"No edges found in mirror info".to_string(),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)))
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::new_engine(KclErrorDetails::new(
|
return Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("EntityMirror response was not as expected: {:?}", resp),
|
format!("EntityMirror response was not as expected: {resp:?}"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
@ -127,14 +127,14 @@ async fn inner_mirror_2d(
|
|||||||
return Err(KclError::new_engine(KclErrorDetails::new(
|
return Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
"No edges found in mirror info".to_string(),
|
"No edges found in mirror info".to_string(),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)))
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::new_engine(KclErrorDetails::new(
|
return Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("EntityMirrorAcrossEdge response was not as expected: {:?}", resp),
|
format!("EntityMirrorAcrossEdge response was not as expected: {resp:?}"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
@ -31,7 +31,7 @@ pub use args::Args;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
execution::{types::PrimitiveType, ExecState, KclValue},
|
execution::{ExecState, KclValue, types::PrimitiveType},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type StdFn = fn(
|
pub type StdFn = fn(
|
||||||
|
@ -4,8 +4,8 @@ use std::cmp::Ordering;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{
|
use kcmc::{
|
||||||
each_cmd as mcmd, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, shared::Transform,
|
ModelingCmd, each_cmd as mcmd, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, shared::Transform,
|
||||||
websocket::OkWebSocketResponseData, ModelingCmd,
|
websocket::OkWebSocketResponseData,
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds::{
|
use kittycad_modeling_cmds::{
|
||||||
self as kcmc,
|
self as kcmc,
|
||||||
@ -16,19 +16,19 @@ use uuid::Uuid;
|
|||||||
|
|
||||||
use super::axis_or_reference::Axis3dOrPoint3d;
|
use super::axis_or_reference::Axis3dOrPoint3d;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ExecutorContext, SourceRange,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
|
ExecState, Geometries, Geometry, KclObjectFields, KclValue, Sketch, Solid,
|
||||||
fn_call::{Arg, Args, KwArgs},
|
fn_call::{Arg, Args, KwArgs},
|
||||||
kcl_value::FunctionSource,
|
kcl_value::FunctionSource,
|
||||||
types::{NumericType, PrimitiveType, RuntimeType},
|
types::{NumericType, PrimitiveType, RuntimeType},
|
||||||
ExecState, Geometries, Geometry, KclObjectFields, KclValue, Sketch, Solid,
|
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
args::TyF64,
|
args::TyF64,
|
||||||
axis_or_reference::Axis2dOrPoint2d,
|
axis_or_reference::Axis2dOrPoint2d,
|
||||||
utils::{point_3d_to_mm, point_to_mm},
|
utils::{point_3d_to_mm, point_to_mm},
|
||||||
},
|
},
|
||||||
ExecutorContext, SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const MUST_HAVE_ONE_INSTANCE: &str = "There must be at least 1 instance of your geometry";
|
const MUST_HAVE_ONE_INSTANCE: &str = "There must be at least 1 instance of your geometry";
|
||||||
@ -176,7 +176,7 @@ async fn send_pattern_transform<T: GeometryTrait>(
|
|||||||
&mock_ids
|
&mock_ids
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::new_engine(KclErrorDetails::new(
|
return Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("EntityLinearPattern response was not as expected: {:?}", resp),
|
format!("EntityLinearPattern response was not as expected: {resp:?}"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
@ -244,7 +244,7 @@ async fn make_transform<T: GeometryTrait>(
|
|||||||
return Err(KclError::new_semantic(KclErrorDetails::new(
|
return Err(KclError::new_semantic(KclErrorDetails::new(
|
||||||
"Transform function must return a transform object".to_string(),
|
"Transform function must return a transform object".to_string(),
|
||||||
source_ranges.clone(),
|
source_ranges.clone(),
|
||||||
)))
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -970,7 +970,7 @@ async fn pattern_circular(
|
|||||||
&mock_ids
|
&mock_ids
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::new_engine(KclErrorDetails::new(
|
return Err(KclError::new_engine(KclErrorDetails::new(
|
||||||
format!("EntityCircularPattern response was not as expected: {:?}", resp),
|
format!("EntityCircularPattern response was not as expected: {resp:?}"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
//! Standard library plane helpers.
|
//! Standard library plane helpers.
|
||||||
|
|
||||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Color, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd, length_unit::LengthUnit, shared::Color};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
|
|
||||||
use super::{args::TyF64, sketch::PlaneData};
|
use super::{args::TyF64, sketch::PlaneData};
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
execution::{types::RuntimeType, ExecState, KclValue, ModelingCmdMeta, Plane, PlaneType},
|
execution::{ExecState, KclValue, ModelingCmdMeta, Plane, PlaneType, types::RuntimeType},
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,22 +2,21 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{
|
use kcmc::{
|
||||||
each_cmd as mcmd,
|
ModelingCmd, each_cmd as mcmd,
|
||||||
length_unit::LengthUnit,
|
length_unit::LengthUnit,
|
||||||
shared::{Angle, Opposite},
|
shared::{Angle, Opposite},
|
||||||
ModelingCmd,
|
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds::{self as kcmc, shared::Point3d};
|
use kittycad_modeling_cmds::{self as kcmc, shared::Point3d};
|
||||||
|
|
||||||
use super::{args::TyF64, DEFAULT_TOLERANCE_MM};
|
use super::{DEFAULT_TOLERANCE_MM, args::TyF64};
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{NumericType, PrimitiveType, RuntimeType},
|
|
||||||
ExecState, KclValue, ModelingCmdMeta, Sketch, Solid,
|
ExecState, KclValue, ModelingCmdMeta, Sketch, Solid,
|
||||||
|
types::{NumericType, PrimitiveType, RuntimeType},
|
||||||
},
|
},
|
||||||
parsing::ast::types::TagNode,
|
parsing::ast::types::TagNode,
|
||||||
std::{axis_or_reference::Axis2dOrEdgeReference, extrude::do_post_extrude, Args},
|
std::{Args, axis_or_reference::Axis2dOrEdgeReference, extrude::do_post_extrude},
|
||||||
};
|
};
|
||||||
|
|
||||||
extern crate nalgebra_glm as glm;
|
extern crate nalgebra_glm as glm;
|
||||||
@ -76,7 +75,7 @@ async fn inner_revolve(
|
|||||||
// nice and we use the other data in the docs, so we still need use the derive above for the json schema.
|
// nice and we use the other data in the docs, so we still need use the derive above for the json schema.
|
||||||
if !(-360.0..=360.0).contains(&angle) || angle == 0.0 {
|
if !(-360.0..=360.0).contains(&angle) || angle == 0.0 {
|
||||||
return Err(KclError::new_semantic(KclErrorDetails::new(
|
return Err(KclError::new_semantic(KclErrorDetails::new(
|
||||||
format!("Expected angle to be between -360 and 360 and not 0, found `{}`", angle),
|
format!("Expected angle to be between -360 and 360 and not 0, found `{angle}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -89,8 +88,7 @@ async fn inner_revolve(
|
|||||||
if !(-360.0..=360.0).contains(&bidirectional_angle) || bidirectional_angle == 0.0 {
|
if !(-360.0..=360.0).contains(&bidirectional_angle) || bidirectional_angle == 0.0 {
|
||||||
return Err(KclError::new_semantic(KclErrorDetails::new(
|
return Err(KclError::new_semantic(KclErrorDetails::new(
|
||||||
format!(
|
format!(
|
||||||
"Expected bidirectional angle to be between -360 and 360 and not 0, found `{}`",
|
"Expected bidirectional angle to be between -360 and 360 and not 0, found `{bidirectional_angle}`"
|
||||||
bidirectional_angle
|
|
||||||
),
|
),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
@ -100,10 +98,7 @@ async fn inner_revolve(
|
|||||||
let ang = angle.signum() * bidirectional_angle + angle;
|
let ang = angle.signum() * bidirectional_angle + angle;
|
||||||
if !(-360.0..=360.0).contains(&ang) {
|
if !(-360.0..=360.0).contains(&ang) {
|
||||||
return Err(KclError::new_semantic(KclErrorDetails::new(
|
return Err(KclError::new_semantic(KclErrorDetails::new(
|
||||||
format!(
|
format!("Combined angle and bidirectional must be between -360 and 360, found '{ang}'"),
|
||||||
"Combined angle and bidirectional must be between -360 and 360, found '{}'",
|
|
||||||
ang
|
|
||||||
),
|
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@ use super::utils::untype_point;
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{NumericType, PrimitiveType, RuntimeType},
|
|
||||||
ExecState, KclValue, Sketch, TagIdentifier,
|
ExecState, KclValue, Sketch, TagIdentifier,
|
||||||
|
types::{NumericType, PrimitiveType, RuntimeType},
|
||||||
},
|
},
|
||||||
std::{args::TyF64, utils::between, Args},
|
std::{Args, args::TyF64, utils::between},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Returns the point at the end of the given segment.
|
/// Returns the point at the end of the given segment.
|
||||||
@ -25,7 +25,7 @@ fn inner_segment_end(tag: &TagIdentifier, exec_state: &mut ExecState, args: Args
|
|||||||
let line = args.get_tag_engine_info(exec_state, tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
format!("Expected a line segment with a path, found `{:?}`", line),
|
format!("Expected a line segment with a path, found `{line:?}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -48,7 +48,7 @@ fn inner_segment_end_x(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
|
|||||||
let line = args.get_tag_engine_info(exec_state, tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
format!("Expected a line segment with a path, found `{:?}`", line),
|
format!("Expected a line segment with a path, found `{line:?}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -68,7 +68,7 @@ fn inner_segment_end_y(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
|
|||||||
let line = args.get_tag_engine_info(exec_state, tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
format!("Expected a line segment with a path, found `{:?}`", line),
|
format!("Expected a line segment with a path, found `{line:?}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -88,7 +88,7 @@ fn inner_segment_start(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
|
|||||||
let line = args.get_tag_engine_info(exec_state, tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
format!("Expected a line segment with a path, found `{:?}`", line),
|
format!("Expected a line segment with a path, found `{line:?}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -111,7 +111,7 @@ fn inner_segment_start_x(tag: &TagIdentifier, exec_state: &mut ExecState, args:
|
|||||||
let line = args.get_tag_engine_info(exec_state, tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
format!("Expected a line segment with a path, found `{:?}`", line),
|
format!("Expected a line segment with a path, found `{line:?}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -131,7 +131,7 @@ fn inner_segment_start_y(tag: &TagIdentifier, exec_state: &mut ExecState, args:
|
|||||||
let line = args.get_tag_engine_info(exec_state, tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
format!("Expected a line segment with a path, found `{:?}`", line),
|
format!("Expected a line segment with a path, found `{line:?}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -152,7 +152,7 @@ fn inner_last_segment_x(sketch: Sketch, args: Args) -> Result<TyF64, KclError> {
|
|||||||
.last()
|
.last()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
format!("Expected a Sketch with at least one segment, found `{:?}`", sketch),
|
format!("Expected a Sketch with at least one segment, found `{sketch:?}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?
|
})?
|
||||||
@ -175,7 +175,7 @@ fn inner_last_segment_y(sketch: Sketch, args: Args) -> Result<TyF64, KclError> {
|
|||||||
.last()
|
.last()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
format!("Expected a Sketch with at least one segment, found `{:?}`", sketch),
|
format!("Expected a Sketch with at least one segment, found `{sketch:?}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?
|
})?
|
||||||
@ -195,7 +195,7 @@ fn inner_segment_length(tag: &TagIdentifier, exec_state: &mut ExecState, args: A
|
|||||||
let line = args.get_tag_engine_info(exec_state, tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
format!("Expected a line segment with a path, found `{:?}`", line),
|
format!("Expected a line segment with a path, found `{line:?}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -215,7 +215,7 @@ fn inner_segment_angle(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
|
|||||||
let line = args.get_tag_engine_info(exec_state, tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
format!("Expected a line segment with a path, found `{:?}`", line),
|
format!("Expected a line segment with a path, found `{line:?}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -237,7 +237,7 @@ async fn inner_tangent_to_end(tag: &TagIdentifier, exec_state: &mut ExecState, a
|
|||||||
let line = args.get_tag_engine_info(exec_state, tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
format!("Expected a line segment with a path, found `{:?}`", line),
|
format!("Expected a line segment with a path, found `{line:?}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{
|
use kcmc::{
|
||||||
each_cmd as mcmd,
|
ModelingCmd, each_cmd as mcmd,
|
||||||
length_unit::LengthUnit,
|
length_unit::LengthUnit,
|
||||||
shared::{Angle, Point2d as KPoint2d},
|
shared::{Angle, Point2d as KPoint2d},
|
||||||
ModelingCmd,
|
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use kittycad_modeling_cmds::shared::PathSegment;
|
use kittycad_modeling_cmds::shared::PathSegment;
|
||||||
@ -17,17 +16,17 @@ use super::{
|
|||||||
utils::{point_to_len_unit, point_to_mm, point_to_typed, untype_point, untyped_point_to_mm},
|
utils::{point_to_len_unit, point_to_mm, point_to_typed, untype_point, untyped_point_to_mm},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
SourceRange,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{RuntimeType, UnitLen},
|
|
||||||
BasePath, ExecState, GeoMeta, KclValue, ModelingCmdMeta, Path, Sketch, SketchSurface,
|
BasePath, ExecState, GeoMeta, KclValue, ModelingCmdMeta, Path, Sketch, SketchSurface,
|
||||||
|
types::{RuntimeType, UnitLen},
|
||||||
},
|
},
|
||||||
parsing::ast::types::TagNode,
|
parsing::ast::types::TagNode,
|
||||||
std::{
|
std::{
|
||||||
utils::{calculate_circle_center, distance},
|
|
||||||
Args,
|
Args,
|
||||||
|
utils::{calculate_circle_center, distance},
|
||||||
},
|
},
|
||||||
SourceRange,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A sketch surface or a sketch.
|
/// A sketch surface or a sketch.
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
//! Standard library shells.
|
//! Standard library shells.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd, length_unit::LengthUnit};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
|
|
||||||
use super::args::TyF64;
|
use super::args::TyF64;
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{ArrayLen, RuntimeType},
|
|
||||||
ExecState, KclValue, Solid,
|
ExecState, KclValue, Solid,
|
||||||
|
types::{ArrayLen, RuntimeType},
|
||||||
},
|
},
|
||||||
std::{sketch::FaceTag, Args},
|
std::{Args, sketch::FaceTag},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Create a shell.
|
/// Create a shell.
|
||||||
|
@ -4,7 +4,7 @@ use anyhow::Result;
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use kcmc::shared::Point2d as KPoint2d; // Point2d is already defined in this pkg, to impl ts_rs traits.
|
use kcmc::shared::Point2d as KPoint2d; // Point2d is already defined in this pkg, to impl ts_rs traits.
|
||||||
use kcmc::shared::Point3d as KPoint3d; // Point3d is already defined in this pkg, to impl ts_rs traits.
|
use kcmc::shared::Point3d as KPoint3d; // Point3d is already defined in this pkg, to impl ts_rs traits.
|
||||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, websocket::ModelingCmdReq, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, websocket::ModelingCmdReq};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use kittycad_modeling_cmds::shared::PathSegment;
|
use kittycad_modeling_cmds::shared::PathSegment;
|
||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
@ -17,17 +17,16 @@ use crate::execution::{Artifact, ArtifactId, CodeRef, StartSketchOnFace, StartSk
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{ArrayLen, NumericType, PrimitiveType, RuntimeType, UnitLen},
|
|
||||||
BasePath, ExecState, Face, GeoMeta, KclValue, ModelingCmdMeta, Path, Plane, PlaneInfo, Point2d, Sketch,
|
BasePath, ExecState, Face, GeoMeta, KclValue, ModelingCmdMeta, Path, Plane, PlaneInfo, Point2d, Sketch,
|
||||||
SketchSurface, Solid, TagEngineInfo, TagIdentifier,
|
SketchSurface, Solid, TagEngineInfo, TagIdentifier,
|
||||||
|
types::{ArrayLen, NumericType, PrimitiveType, RuntimeType, UnitLen},
|
||||||
},
|
},
|
||||||
parsing::ast::types::TagNode,
|
parsing::ast::types::TagNode,
|
||||||
std::{
|
std::{
|
||||||
args::{Args, TyF64},
|
args::{Args, TyF64},
|
||||||
utils::{
|
utils::{
|
||||||
arc_center_and_end, get_tangential_arc_to_info, get_x_component, get_y_component,
|
TangentialArcInfoInput, arc_center_and_end, get_tangential_arc_to_info, get_x_component, get_y_component,
|
||||||
intersection_with_parallel_line, point_to_len_unit, point_to_mm, untyped_point_to_mm,
|
intersection_with_parallel_line, point_to_len_unit, point_to_mm, untyped_point_to_mm,
|
||||||
TangentialArcInfoInput,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -45,7 +44,7 @@ pub enum FaceTag {
|
|||||||
impl std::fmt::Display for FaceTag {
|
impl std::fmt::Display for FaceTag {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
FaceTag::Tag(t) => write!(f, "{}", t),
|
FaceTag::Tag(t) => write!(f, "{t}"),
|
||||||
FaceTag::StartOrEnd(StartOrEnd::Start) => write!(f, "start"),
|
FaceTag::StartOrEnd(StartOrEnd::Start) => write!(f, "start"),
|
||||||
FaceTag::StartOrEnd(StartOrEnd::End) => write!(f, "end"),
|
FaceTag::StartOrEnd(StartOrEnd::End) => write!(f, "end"),
|
||||||
}
|
}
|
||||||
@ -62,7 +61,7 @@ impl FaceTag {
|
|||||||
must_be_planar: bool,
|
must_be_planar: bool,
|
||||||
) -> Result<uuid::Uuid, KclError> {
|
) -> Result<uuid::Uuid, KclError> {
|
||||||
match self {
|
match self {
|
||||||
FaceTag::Tag(ref t) => args.get_adjacent_face_to_tag(exec_state, t, must_be_planar).await,
|
FaceTag::Tag(t) => args.get_adjacent_face_to_tag(exec_state, t, must_be_planar).await,
|
||||||
FaceTag::StartOrEnd(StartOrEnd::Start) => solid.start_cap_id.ok_or_else(|| {
|
FaceTag::StartOrEnd(StartOrEnd::Start) => solid.start_cap_id.ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
"Expected a start face".to_string(),
|
"Expected a start face".to_string(),
|
||||||
@ -737,7 +736,7 @@ pub async fn inner_angled_line_that_intersects(
|
|||||||
let intersect_path = args.get_tag_engine_info(exec_state, &intersect_tag)?;
|
let intersect_path = args.get_tag_engine_info(exec_state, &intersect_tag)?;
|
||||||
let path = intersect_path.path.clone().ok_or_else(|| {
|
let path = intersect_path.path.clone().ok_or_else(|| {
|
||||||
KclError::new_type(KclErrorDetails::new(
|
KclError::new_type(KclErrorDetails::new(
|
||||||
format!("Expected an intersect path with a path, found `{:?}`", intersect_path),
|
format!("Expected an intersect path with a path, found `{intersect_path:?}`"),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
//! Standard library sweep.
|
//! Standard library sweep.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
|
use kcmc::{ModelingCmd, each_cmd as mcmd, length_unit::LengthUnit};
|
||||||
use kittycad_modeling_cmds::{self as kcmc, shared::RelativeTo};
|
use kittycad_modeling_cmds::{self as kcmc, shared::RelativeTo};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use super::{args::TyF64, DEFAULT_TOLERANCE_MM};
|
use super::{DEFAULT_TOLERANCE_MM, args::TyF64};
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
execution::{
|
execution::{
|
||||||
types::{NumericType, RuntimeType},
|
|
||||||
ExecState, Helix, KclValue, ModelingCmdMeta, Sketch, Solid,
|
ExecState, Helix, KclValue, ModelingCmdMeta, Sketch, Solid,
|
||||||
|
types::{NumericType, RuntimeType},
|
||||||
},
|
},
|
||||||
parsing::ast::types::TagNode,
|
parsing::ast::types::TagNode,
|
||||||
std::{extrude::do_post_extrude, Args},
|
std::{Args, extrude::do_post_extrude},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A path to sweep along.
|
/// A path to sweep along.
|
||||||
@ -79,7 +79,7 @@ async fn inner_sweep(
|
|||||||
return Err(KclError::new_syntax(crate::errors::KclErrorDetails::new(
|
return Err(KclError::new_syntax(crate::errors::KclErrorDetails::new(
|
||||||
"If you provide relativeTo, it must either be 'sketchPlane' or 'trajectoryCurve'".to_owned(),
|
"If you provide relativeTo, it must either be 'sketchPlane' or 'trajectoryCurve'".to_owned(),
|
||||||
vec![args.source_range],
|
vec![args.source_range],
|
||||||
)))
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,21 +2,20 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{
|
use kcmc::{
|
||||||
each_cmd as mcmd,
|
ModelingCmd, each_cmd as mcmd,
|
||||||
length_unit::LengthUnit,
|
length_unit::LengthUnit,
|
||||||
shared,
|
shared,
|
||||||
shared::{Point3d, Point4d},
|
shared::{Point3d, Point4d},
|
||||||
ModelingCmd,
|
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{PrimitiveType, RuntimeType},
|
|
||||||
ExecState, KclValue, SolidOrSketchOrImportedGeometry,
|
ExecState, KclValue, SolidOrSketchOrImportedGeometry,
|
||||||
|
types::{PrimitiveType, RuntimeType},
|
||||||
},
|
},
|
||||||
std::{args::TyF64, axis_or_reference::Axis3dOrPoint3d, Args},
|
std::{Args, args::TyF64, axis_or_reference::Axis3dOrPoint3d},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Scale a solid or a sketch.
|
/// Scale a solid or a sketch.
|
||||||
|
@ -88,11 +88,7 @@ pub(crate) fn delta(from_angle: Angle, to_angle: Angle) -> Angle {
|
|||||||
|
|
||||||
pub(crate) fn normalize_rad(angle: f64) -> f64 {
|
pub(crate) fn normalize_rad(angle: f64) -> f64 {
|
||||||
let draft = angle % (2.0 * PI);
|
let draft = angle % (2.0 * PI);
|
||||||
if draft < 0.0 {
|
if draft < 0.0 { draft + 2.0 * PI } else { draft }
|
||||||
draft + 2.0 * PI
|
|
||||||
} else {
|
|
||||||
draft
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_intersection_of_two_lines(line1: &[Coords2d; 2], line2_angle: f64, line2_point: Coords2d) -> Coords2d {
|
fn calculate_intersection_of_two_lines(line1: &[Coords2d; 2], line2_angle: f64, line2_point: Coords2d) -> Coords2d {
|
||||||
@ -174,8 +170,8 @@ pub(crate) fn arc_center_and_end(
|
|||||||
let end_angle = end_angle.to_radians();
|
let end_angle = end_angle.to_radians();
|
||||||
|
|
||||||
let center = [
|
let center = [
|
||||||
-1.0 * (radius * libm::cos(start_angle) - from[0]),
|
-(radius * libm::cos(start_angle) - from[0]),
|
||||||
-1.0 * (radius * libm::sin(start_angle) - from[1]),
|
-(radius * libm::sin(start_angle) - from[1]),
|
||||||
];
|
];
|
||||||
|
|
||||||
let end = [
|
let end = [
|
||||||
@ -240,7 +236,7 @@ mod tests {
|
|||||||
use approx::assert_relative_eq;
|
use approx::assert_relative_eq;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use super::{calculate_circle_center, get_x_component, get_y_component, Angle};
|
use super::{Angle, calculate_circle_center, get_x_component, get_y_component};
|
||||||
|
|
||||||
static EACH_QUAD: [(i32, [i32; 2]); 12] = [
|
static EACH_QUAD: [(i32, [i32; 2]); 12] = [
|
||||||
(-315, [1, 1]),
|
(-315, [1, 1]),
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ConnectionError, ExecError, KclError, KclErrorWithOutputs, Program,
|
||||||
engine::new_zoo_client,
|
engine::new_zoo_client,
|
||||||
errors::ExecErrorWithState,
|
errors::ExecErrorWithState,
|
||||||
execution::{EnvironmentRef, ExecState, ExecutorContext, ExecutorSettings},
|
execution::{EnvironmentRef, ExecState, ExecutorContext, ExecutorSettings},
|
||||||
ConnectionError, ExecError, KclError, KclErrorWithOutputs, Program,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
@ -64,7 +64,7 @@ pub async fn execute_and_snapshot_ast(
|
|||||||
// Close the context to avoid any resource leaks.
|
// Close the context to avoid any resource leaks.
|
||||||
ctx.close().await;
|
ctx.close().await;
|
||||||
return Err(ExecErrorWithState::new(
|
return Err(ExecErrorWithState::new(
|
||||||
ExecError::BadExport(format!("Export failed: {:?}", err)),
|
ExecError::BadExport(format!("Export failed: {err:?}")),
|
||||||
exec_state.clone(),
|
exec_state.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ pub async fn execute_and_export_step(
|
|||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Err(ExecErrorWithState::new(
|
return Err(ExecErrorWithState::new(
|
||||||
ExecError::BadExport(format!("Export failed: {:?}", err)),
|
ExecError::BadExport(format!("Export failed: {err:?}")),
|
||||||
exec_state.clone(),
|
exec_state.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
KclError, ModuleId,
|
||||||
parsing::{
|
parsing::{
|
||||||
|
DeprecationKind, PIPE_OPERATOR,
|
||||||
ast::types::{
|
ast::types::{
|
||||||
Annotation, ArrayExpression, ArrayRangeExpression, AscribedExpression, Associativity, BinaryExpression,
|
Annotation, ArrayExpression, ArrayRangeExpression, AscribedExpression, Associativity, BinaryExpression,
|
||||||
BinaryOperator, BinaryPart, BodyItem, CallExpressionKw, CommentStyle, DefaultParamVal, Expr, FormatOptions,
|
BinaryOperator, BinaryPart, BodyItem, CallExpressionKw, CommentStyle, DefaultParamVal, Expr, FormatOptions,
|
||||||
@ -10,9 +12,8 @@ use crate::{
|
|||||||
Parameter, PipeExpression, Program, TagDeclarator, TypeDeclaration, UnaryExpression, VariableDeclaration,
|
Parameter, PipeExpression, Program, TagDeclarator, TypeDeclaration, UnaryExpression, VariableDeclaration,
|
||||||
VariableKind,
|
VariableKind,
|
||||||
},
|
},
|
||||||
deprecation, DeprecationKind, PIPE_OPERATOR,
|
deprecation,
|
||||||
},
|
},
|
||||||
KclError, ModuleId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -110,7 +111,7 @@ impl Program {
|
|||||||
let formatted = custom_white_space_or_comment.recast(options, indentation_level);
|
let formatted = custom_white_space_or_comment.recast(options, indentation_level);
|
||||||
if i == 0 && !formatted.trim().is_empty() {
|
if i == 0 && !formatted.trim().is_empty() {
|
||||||
if let NonCodeValue::BlockComment { .. } = custom_white_space_or_comment.value {
|
if let NonCodeValue::BlockComment { .. } = custom_white_space_or_comment.value {
|
||||||
format!("\n{}", formatted)
|
format!("\n{formatted}")
|
||||||
} else {
|
} else {
|
||||||
formatted
|
formatted
|
||||||
}
|
}
|
||||||
@ -127,7 +128,7 @@ impl Program {
|
|||||||
custom_white_space_or_comment
|
custom_white_space_or_comment
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = write!(output, "{}{}{}", start_string, recast_str, end_string);
|
let _ = write!(output, "{start_string}{recast_str}{end_string}");
|
||||||
output
|
output
|
||||||
})
|
})
|
||||||
.trim()
|
.trim()
|
||||||
@ -135,7 +136,7 @@ impl Program {
|
|||||||
|
|
||||||
// Insert a final new line if the user wants it.
|
// Insert a final new line if the user wants it.
|
||||||
if options.insert_final_newline && !result.is_empty() {
|
if options.insert_final_newline && !result.is_empty() {
|
||||||
format!("{}\n", result)
|
format!("{result}\n")
|
||||||
} else {
|
} else {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
@ -158,16 +159,16 @@ impl Node<NonCodeNode> {
|
|||||||
NonCodeValue::InlineComment {
|
NonCodeValue::InlineComment {
|
||||||
value,
|
value,
|
||||||
style: CommentStyle::Line,
|
style: CommentStyle::Line,
|
||||||
} => format!(" // {}\n", value),
|
} => format!(" // {value}\n"),
|
||||||
NonCodeValue::InlineComment {
|
NonCodeValue::InlineComment {
|
||||||
value,
|
value,
|
||||||
style: CommentStyle::Block,
|
style: CommentStyle::Block,
|
||||||
} => format!(" /* {} */", value),
|
} => format!(" /* {value} */"),
|
||||||
NonCodeValue::BlockComment { value, style } => match style {
|
NonCodeValue::BlockComment { value, style } => match style {
|
||||||
CommentStyle::Block => format!("{}/* {} */", indentation, value),
|
CommentStyle::Block => format!("{indentation}/* {value} */"),
|
||||||
CommentStyle::Line => {
|
CommentStyle::Line => {
|
||||||
if value.trim().is_empty() {
|
if value.trim().is_empty() {
|
||||||
format!("{}//\n", indentation)
|
format!("{indentation}//\n")
|
||||||
} else {
|
} else {
|
||||||
format!("{}// {}\n", indentation, value.trim())
|
format!("{}// {}\n", indentation, value.trim())
|
||||||
}
|
}
|
||||||
@ -176,10 +177,10 @@ impl Node<NonCodeNode> {
|
|||||||
NonCodeValue::NewLineBlockComment { value, style } => {
|
NonCodeValue::NewLineBlockComment { value, style } => {
|
||||||
let add_start_new_line = if self.start == 0 { "" } else { "\n\n" };
|
let add_start_new_line = if self.start == 0 { "" } else { "\n\n" };
|
||||||
match style {
|
match style {
|
||||||
CommentStyle::Block => format!("{}{}/* {} */\n", add_start_new_line, indentation, value),
|
CommentStyle::Block => format!("{add_start_new_line}{indentation}/* {value} */\n"),
|
||||||
CommentStyle::Line => {
|
CommentStyle::Line => {
|
||||||
if value.trim().is_empty() {
|
if value.trim().is_empty() {
|
||||||
format!("{}{}//\n", add_start_new_line, indentation)
|
format!("{add_start_new_line}{indentation}//\n")
|
||||||
} else {
|
} else {
|
||||||
format!("{}{}// {}\n", add_start_new_line, indentation, value.trim())
|
format!("{}{}// {}\n", add_start_new_line, indentation, value.trim())
|
||||||
}
|
}
|
||||||
@ -241,7 +242,7 @@ impl ImportStatement {
|
|||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
let mut string = format!("{}{}import ", vis, indentation);
|
let mut string = format!("{vis}{indentation}import ");
|
||||||
match &self.selector {
|
match &self.selector {
|
||||||
ImportSelector::List { items } => {
|
ImportSelector::List { items } => {
|
||||||
for (i, item) in items.iter().enumerate() {
|
for (i, item) in items.iter().enumerate() {
|
||||||
@ -291,7 +292,7 @@ impl Expr {
|
|||||||
Expr::BinaryExpression(bin_exp) => bin_exp.recast(options, indentation_level, ctxt),
|
Expr::BinaryExpression(bin_exp) => bin_exp.recast(options, indentation_level, ctxt),
|
||||||
Expr::ArrayExpression(array_exp) => array_exp.recast(options, indentation_level, ctxt),
|
Expr::ArrayExpression(array_exp) => array_exp.recast(options, indentation_level, ctxt),
|
||||||
Expr::ArrayRangeExpression(range_exp) => range_exp.recast(options, indentation_level, ctxt),
|
Expr::ArrayRangeExpression(range_exp) => range_exp.recast(options, indentation_level, ctxt),
|
||||||
Expr::ObjectExpression(ref obj_exp) => obj_exp.recast(options, indentation_level, ctxt),
|
Expr::ObjectExpression(obj_exp) => obj_exp.recast(options, indentation_level, ctxt),
|
||||||
Expr::MemberExpression(mem_exp) => mem_exp.recast(options, indentation_level, ctxt),
|
Expr::MemberExpression(mem_exp) => mem_exp.recast(options, indentation_level, ctxt),
|
||||||
Expr::Literal(literal) => literal.recast(),
|
Expr::Literal(literal) => literal.recast(),
|
||||||
Expr::FunctionExpression(func_exp) => {
|
Expr::FunctionExpression(func_exp) => {
|
||||||
@ -702,13 +703,7 @@ impl MemberExpression {
|
|||||||
|
|
||||||
impl BinaryExpression {
|
impl BinaryExpression {
|
||||||
fn recast(&self, options: &FormatOptions, _indentation_level: usize, ctxt: ExprContext) -> String {
|
fn recast(&self, options: &FormatOptions, _indentation_level: usize, ctxt: ExprContext) -> String {
|
||||||
let maybe_wrap_it = |a: String, doit: bool| -> String {
|
let maybe_wrap_it = |a: String, doit: bool| -> String { if doit { format!("({a})") } else { a } };
|
||||||
if doit {
|
|
||||||
format!("({})", a)
|
|
||||||
} else {
|
|
||||||
a
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// It would be better to always preserve the user's parentheses but since we've dropped that
|
// It would be better to always preserve the user's parentheses but since we've dropped that
|
||||||
// info from the AST, we bracket expressions as necessary.
|
// info from the AST, we bracket expressions as necessary.
|
||||||
@ -977,7 +972,7 @@ mod tests {
|
|||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{parsing::ast::types::FormatOptions, ModuleId};
|
use crate::{ModuleId, parsing::ast::types::FormatOptions};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_recast_annotations_without_body_items() {
|
fn test_recast_annotations_without_body_items() {
|
||||||
|
@ -289,9 +289,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
macro_rules! kcl {
|
macro_rules! kcl {
|
||||||
( $kcl:expr ) => {{
|
( $kcl:expr_2021 ) => {{ $crate::parsing::top_level_parse($kcl).unwrap() }};
|
||||||
$crate::parsing::top_level_parse($kcl).unwrap()
|
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -153,9 +153,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
macro_rules! kcl {
|
macro_rules! kcl {
|
||||||
( $kcl:expr ) => {{
|
( $kcl:expr_2021 ) => {{ $crate::parsing::top_level_parse($kcl).unwrap() }};
|
||||||
$crate::parsing::top_level_parse($kcl).unwrap()
|
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -57,9 +57,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
macro_rules! kcl {
|
macro_rules! kcl {
|
||||||
( $kcl:expr ) => {{
|
( $kcl:expr_2021 ) => {{ $crate::parsing::top_level_parse($kcl).unwrap() }};
|
||||||
$crate::parsing::top_level_parse($kcl).unwrap()
|
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -19,7 +19,7 @@ fn tokio() -> &'static tokio::runtime::Runtime {
|
|||||||
fn into_miette(error: kcl_lib::KclErrorWithOutputs, code: &str) -> PyErr {
|
fn into_miette(error: kcl_lib::KclErrorWithOutputs, code: &str) -> PyErr {
|
||||||
let report = error.clone().into_miette_report_with_outputs(code).unwrap();
|
let report = error.clone().into_miette_report_with_outputs(code).unwrap();
|
||||||
let report = miette::Report::new(report);
|
let report = miette::Report::new(report);
|
||||||
pyo3::exceptions::PyException::new_err(format!("{:?}", report))
|
pyo3::exceptions::PyException::new_err(format!("{report:?}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_miette_for_parse(filename: &str, input: &str, error: kcl_lib::KclError) -> PyErr {
|
fn into_miette_for_parse(filename: &str, input: &str, error: kcl_lib::KclError) -> PyErr {
|
||||||
@ -29,7 +29,7 @@ fn into_miette_for_parse(filename: &str, input: &str, error: kcl_lib::KclError)
|
|||||||
filename: filename.to_string(),
|
filename: filename.to_string(),
|
||||||
};
|
};
|
||||||
let report = miette::Report::new(report);
|
let report = miette::Report::new(report);
|
||||||
pyo3::exceptions::PyException::new_err(format!("{:?}", report))
|
pyo3::exceptions::PyException::new_err(format!("{report:?}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The variety of image formats snapshots may be exported to.
|
/// The variety of image formats snapshots may be exported to.
|
||||||
@ -402,8 +402,7 @@ async fn execute_and_snapshot(path: String, image_format: ImageFormat) -> PyResu
|
|||||||
} = resp
|
} = resp
|
||||||
else {
|
else {
|
||||||
return Err(pyo3::exceptions::PyException::new_err(format!(
|
return Err(pyo3::exceptions::PyException::new_err(format!(
|
||||||
"Unexpected response from engine: {:?}",
|
"Unexpected response from engine: {resp:?}"
|
||||||
resp
|
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -459,8 +458,7 @@ async fn execute_code_and_snapshot(code: String, image_format: ImageFormat) -> P
|
|||||||
} = resp
|
} = resp
|
||||||
else {
|
else {
|
||||||
return Err(pyo3::exceptions::PyException::new_err(format!(
|
return Err(pyo3::exceptions::PyException::new_err(format!(
|
||||||
"Unexpected response from engine: {:?}",
|
"Unexpected response from engine: {resp:?}"
|
||||||
resp
|
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -510,8 +508,7 @@ async fn execute_and_export(path: String, export_format: FileExportFormat) -> Py
|
|||||||
|
|
||||||
let kittycad_modeling_cmds::websocket::OkWebSocketResponseData::Export { files } = resp else {
|
let kittycad_modeling_cmds::websocket::OkWebSocketResponseData::Export { files } = resp else {
|
||||||
return Err(pyo3::exceptions::PyException::new_err(format!(
|
return Err(pyo3::exceptions::PyException::new_err(format!(
|
||||||
"Unexpected response from engine: {:?}",
|
"Unexpected response from engine: {resp:?}"
|
||||||
resp
|
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -558,8 +555,7 @@ async fn execute_code_and_export(code: String, export_format: FileExportFormat)
|
|||||||
|
|
||||||
let kittycad_modeling_cmds::websocket::OkWebSocketResponseData::Export { files } = resp else {
|
let kittycad_modeling_cmds::websocket::OkWebSocketResponseData::Export { files } = resp else {
|
||||||
return Err(pyo3::exceptions::PyException::new_err(format!(
|
return Err(pyo3::exceptions::PyException::new_err(format!(
|
||||||
"Unexpected response from engine: {:?}",
|
"Unexpected response from engine: {resp:?}"
|
||||||
resp
|
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ impl EngineConnection {
|
|||||||
|
|
||||||
fn handle_command(&self, cmd_id: &ModelingCmdId, cmd: &kcmc::ModelingCmd) -> (String, OkModelingCmdResponse) {
|
fn handle_command(&self, cmd_id: &ModelingCmdId, cmd: &kcmc::ModelingCmd) -> (String, OkModelingCmdResponse) {
|
||||||
let cpp_id = id_to_cpp(cmd_id);
|
let cpp_id = id_to_cpp(cmd_id);
|
||||||
let cmd_id = format!("{}", cmd_id);
|
let cmd_id = format!("{cmd_id}");
|
||||||
let mut this_response = OkModelingCmdResponse::Empty {};
|
let mut this_response = OkModelingCmdResponse::Empty {};
|
||||||
|
|
||||||
let new_code = match cmd {
|
let new_code = match cmd {
|
||||||
@ -86,7 +86,7 @@ impl EngineConnection {
|
|||||||
size,
|
size,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let plane_id = format!("plane_{}", cpp_id);
|
let plane_id = format!("plane_{cpp_id}");
|
||||||
format!(
|
format!(
|
||||||
r#"
|
r#"
|
||||||
auto {plane_id} = make_shared<Object>("plane", glm::dvec3 {{ 0, 0, 0 }});
|
auto {plane_id} = make_shared<Object>("plane", glm::dvec3 {{ 0, 0, 0 }});
|
||||||
@ -108,8 +108,8 @@ impl EngineConnection {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
kcmc::ModelingCmd::StartPath(kcmc::StartPath { .. }) => {
|
kcmc::ModelingCmd::StartPath(kcmc::StartPath { .. }) => {
|
||||||
let sketch_id = format!("sketch_{}", cpp_id);
|
let sketch_id = format!("sketch_{cpp_id}");
|
||||||
let path_id = format!("path_{}", cpp_id);
|
let path_id = format!("path_{cpp_id}");
|
||||||
format!(
|
format!(
|
||||||
r#"
|
r#"
|
||||||
auto {sketch_id} = make_shared<Object>("sketch", glm::dvec3 {{ 0, 0, 0 }});
|
auto {sketch_id} = make_shared<Object>("sketch", glm::dvec3 {{ 0, 0, 0 }});
|
||||||
@ -178,7 +178,7 @@ impl EngineConnection {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
format!("//{:?}", cmd)
|
format!("//{cmd:?}")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kcmc::ModelingCmd::ClosePath(kcmc::ClosePath { path_id }) => {
|
kcmc::ModelingCmd::ClosePath(kcmc::ClosePath { path_id }) => {
|
||||||
@ -240,9 +240,8 @@ impl EngineConnection {
|
|||||||
}) => {
|
}) => {
|
||||||
format!(
|
format!(
|
||||||
r#"
|
r#"
|
||||||
//face info get {} {}
|
//face info get {object_id} {edge_id}
|
||||||
"#,
|
"#
|
||||||
object_id, edge_id
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
kcmc::ModelingCmd::EntityCircularPattern(kcmc::EntityCircularPattern {
|
kcmc::ModelingCmd::EntityCircularPattern(kcmc::EntityCircularPattern {
|
||||||
@ -313,11 +312,11 @@ impl EngineConnection {
|
|||||||
// base_code.push_str(&repl_uuid_fix_code);
|
// base_code.push_str(&repl_uuid_fix_code);
|
||||||
|
|
||||||
// base_code
|
// base_code
|
||||||
format!("//{:?}", cmd)
|
format!("//{cmd:?}")
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
//helps us follow along with the currently unhandled engine commands
|
//helps us follow along with the currently unhandled engine commands
|
||||||
format!("//{:?}", cmd)
|
format!("//{cmd:?}")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -330,7 +329,7 @@ fn id_to_cpp(id: &ModelingCmdId) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn uuid_to_cpp(id: &uuid::Uuid) -> String {
|
fn uuid_to_cpp(id: &uuid::Uuid) -> String {
|
||||||
let str = format!("{}", id);
|
let str = format!("{id}");
|
||||||
str::replace(&str, "-", "_")
|
str::replace(&str, "-", "_")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,5 +16,5 @@ async fn main() {
|
|||||||
|
|
||||||
let result = kcl_to_engine_core(&kcl).await.expect("kcl conversion");
|
let result = kcl_to_engine_core(&kcl).await.expect("kcl conversion");
|
||||||
|
|
||||||
println!("{}", result);
|
println!("{result}");
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "1.87"
|
channel = "1.88"
|
||||||
components = ["clippy", "rustfmt"]
|
components = ["clippy", "rustfmt"]
|
||||||
|
Reference in New Issue
Block a user