Merge branch 'main' into lf94/tauri-to-electron

This commit is contained in:
Kurt Hutten
2024-08-14 15:37:14 +10:00
committed by GitHub
15 changed files with 129 additions and 25 deletions

View File

@ -25,5 +25,5 @@ once fixed in engine will just start working here with no language changes.
Sketching on the chamfered face does not currently work. Sketching on the chamfered face does not currently work.
- **Shell**: Shell is only working for `end` faces, not for `side` or `start` - **Shell**: Shell sometimes does not work when arcs or fillets are involved.
faces. We are tracking the engine side bug on this. We are tracking the engine side bug on this.

File diff suppressed because one or more lines are too long

View File

@ -197582,7 +197582,9 @@
"unpublished": false, "unpublished": false,
"deprecated": false, "deprecated": false,
"examples": [ "examples": [
"const firstSketch = startSketchOn('XY')\n |> startProfileAt([-12, 12], %)\n |> line([24, 0], %)\n |> line([0, -24], %)\n |> line([-24, 0], %)\n |> close(%)\n |> extrude(6, %)\n\n// Remove the end face for the extrusion.\nshell({ faces: ['end'], thickness: 0.25 }, firstSketch)" "const firstSketch = startSketchOn('XY')\n |> startProfileAt([-12, 12], %)\n |> line([24, 0], %)\n |> line([0, -24], %)\n |> line([-24, 0], %)\n |> close(%)\n |> extrude(6, %)\n\n// Remove the end face for the extrusion.\nshell({ faces: ['end'], thickness: 0.25 }, firstSketch)",
"const firstSketch = startSketchOn('-XZ')\n |> startProfileAt([-12, 12], %)\n |> line([24, 0], %)\n |> line([0, -24], %)\n |> line([-24, 0], %)\n |> close(%)\n |> extrude(6, %)\n\n// Remove the start face for the extrusion.\nshell({ faces: ['start'], thickness: 0.25 }, firstSketch)",
"const firstSketch = startSketchOn('XY')\n |> startProfileAt([-12, 12], %)\n |> line([24, 0], %)\n |> line([0, -24], %)\n |> line([-24, 0], %, $myTag)\n |> close(%)\n |> extrude(6, %)\n\n// Remove a tagged face for the extrusion.\nshell({ faces: [myTag], thickness: 0.25 }, firstSketch)"
] ]
}, },
{ {

View File

@ -1480,9 +1480,9 @@ dependencies = [
[[package]] [[package]]
name = "kittycad" name = "kittycad"
version = "0.3.13" version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda4573582df5e220e6c3104dba6dc01acff529b36e289f41ca9cb5f91c117ae" checksum = "ce5e9c51976882cdf6777557fd8c3ee68b00bb53e9307fc1721acb397f2ece9a"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",

View File

@ -70,7 +70,7 @@ members = [
] ]
[workspace.dependencies] [workspace.dependencies]
kittycad = { version = "0.3.13", default-features = false, features = ["js", "requests"] } kittycad = { version = "0.3.14", default-features = false, features = ["js", "requests"] }
kittycad-modeling-session = "0.1.4" kittycad-modeling-session = "0.1.4"
[[test]] [[test]]

View File

@ -2977,7 +2977,7 @@ impl MemberExpression {
source_ranges: vec![self.clone().into()], source_ranges: vec![self.clone().into()],
})), })),
(being_indexed, _) => { (being_indexed, _) => {
let t = human_friendly_type(being_indexed); let t = human_friendly_type(&being_indexed);
Err(KclError::Semantic(KclErrorDetails { Err(KclError::Semantic(KclErrorDetails {
message: format!("Only arrays and objects can be indexed, but you're trying to index a {t}"), message: format!("Only arrays and objects can be indexed, but you're trying to index a {t}"),
source_ranges: vec![self.clone().into()], source_ranges: vec![self.clone().into()],
@ -4071,7 +4071,7 @@ impl ConstraintLevels {
} }
} }
fn human_friendly_type(j: JValue) -> &'static str { pub(crate) fn human_friendly_type(j: &JValue) -> &'static str {
match j { match j {
JValue::Null => "null", JValue::Null => "null",
JValue::Bool(_) => "boolean (true/false value)", JValue::Bool(_) => "boolean (true/false value)",

View File

@ -11,7 +11,7 @@ use serde_json::Value as JValue;
use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange}; use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange};
use crate::{ use crate::{
ast::types::{BodyItem, Expr, FunctionExpression, KclNone, Program, TagDeclarator}, ast::types::{human_friendly_type, BodyItem, Expr, FunctionExpression, KclNone, Program, TagDeclarator},
engine::EngineManager, engine::EngineManager,
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
fs::FileManager, fs::FileManager,
@ -311,6 +311,24 @@ impl KclValue {
_ => anyhow::bail!("Not a extrude group or extrude groups: {:?}", self), _ => anyhow::bail!("Not a extrude group or extrude groups: {:?}", self),
} }
} }
/// Human readable type name used in error messages. Should not be relied
/// on for program logic.
pub(crate) fn human_friendly_type(&self) -> &'static str {
match self {
KclValue::UserVal(u) => human_friendly_type(&u.value),
KclValue::TagDeclarator(_) => "TagDeclarator",
KclValue::TagIdentifier(_) => "TagIdentifier",
KclValue::SketchGroup(_) => "SketchGroup",
KclValue::SketchGroups { .. } => "SketchGroups",
KclValue::ExtrudeGroup(_) => "ExtrudeGroup",
KclValue::ExtrudeGroups { .. } => "ExtrudeGroups",
KclValue::ImportedGeometry(_) => "ImportedGeometry",
KclValue::Function { .. } => "Function",
KclValue::Plane(_) => "Plane",
KclValue::Face(_) => "Face",
}
}
} }
impl From<SketchGroupSet> for KclValue { impl From<SketchGroupSet> for KclValue {
@ -2355,6 +2373,29 @@ const thisBox = box({start: [0,0], l: 6, w: 10, h: 3})
parse_execute(ast).await.unwrap(); parse_execute(ast).await.unwrap();
} }
#[tokio::test(flavor = "multi_thread")]
#[ignore] // https://github.com/KittyCAD/modeling-app/issues/3338
async fn test_object_member_starting_pipeline() {
let ast = r#"
fn test2 = () => {
return {
thing: startSketchOn('XY')
|> startProfileAt([0, 0], %)
|> line([0, 1], %)
|> line([1, 0], %)
|> line([0, -1], %)
|> close(%)
}
}
const x2 = test2()
x2.thing
|> extrude(10, %)
"#;
parse_execute(ast).await.unwrap();
}
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
#[ignore] // ignore til we get loops #[ignore] // ignore til we get loops
async fn test_execute_with_function_sketch_loop_objects() { async fn test_execute_with_function_sketch_loop_objects() {

View File

@ -460,8 +460,9 @@ where
let Some(val) = T::from_mem_item(arg) else { let Some(val) = T::from_mem_item(arg) else {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!( message: format!(
"Argument at index {i} was supposed to be type {} but wasn't", "Argument at index {i} was supposed to be type {} but found {}",
type_name::<T>(), type_name::<T>(),
arg.human_friendly_type()
), ),
source_ranges: vec![args.source_range], source_ranges: vec![args.source_range],
})); }));
@ -479,8 +480,9 @@ where
let Some(val) = T::from_mem_item(arg) else { let Some(val) = T::from_mem_item(arg) else {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!( message: format!(
"Argument at index {i} was supposed to be type {} but wasn't", "Argument at index {i} was supposed to be type {} but found {}",
type_name::<T>() type_name::<T>(),
arg.human_friendly_type()
), ),
source_ranges: vec![args.source_range], source_ranges: vec![args.source_range],
})); }));

View File

@ -50,6 +50,7 @@ pub async fn circle(args: Args) -> Result<KclValue, KclError> {
/// |> hole(circle([0, 15], 5, %), %) /// |> hole(circle([0, 15], 5, %), %)
/// ///
/// const example = extrude(5, exampleSketch) /// const example = extrude(5, exampleSketch)
/// ```
#[stdlib { #[stdlib {
name = "circle", name = "circle",
}] }]

View File

@ -50,6 +50,38 @@ pub async fn shell(args: Args) -> Result<KclValue, KclError> {
/// thickness: 0.25, /// thickness: 0.25,
/// }, firstSketch) /// }, firstSketch)
/// ``` /// ```
///
/// ```no_run
/// const firstSketch = startSketchOn('-XZ')
/// |> startProfileAt([-12, 12], %)
/// |> line([24, 0], %)
/// |> line([0, -24], %)
/// |> line([-24, 0], %)
/// |> close(%)
/// |> extrude(6, %)
///
/// // Remove the start face for the extrusion.
/// shell({
/// faces: ['start'],
/// thickness: 0.25,
/// }, firstSketch)
/// ```
///
/// ```no_run
/// const firstSketch = startSketchOn('XY')
/// |> startProfileAt([-12, 12], %)
/// |> line([24, 0], %)
/// |> line([0, -24], %)
/// |> line([-24, 0], %, $myTag)
/// |> close(%)
/// |> extrude(6, %)
///
/// // Remove a tagged face for the extrusion.
/// shell({
/// faces: [myTag],
/// thickness: 0.25,
/// }, firstSketch)
/// ```
#[stdlib { #[stdlib {
name = "shell", name = "shell",
}] }]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

View File

@ -903,7 +903,7 @@ const part = rectShape([0, 0], 20, 20)
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([887, 936])], message: "Argument at index 0 was supposed to be type [f64; 2] but wasn't" }"#, r#"semantic: KclErrorDetails { source_ranges: [SourceRange([887, 936])], message: "Argument at index 0 was supposed to be type [f64; 2] but found string (text)" }"#,
); );
} }
@ -1425,7 +1425,7 @@ const secondSketch = startSketchOn(part001, '')
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([272, 298])], message: "Argument at index 1 was supposed to be type kcl_lib::std::sketch::FaceTag but wasn't" }"# r#"semantic: KclErrorDetails { source_ranges: [SourceRange([272, 298])], message: "Argument at index 1 was supposed to be type kcl_lib::std::sketch::FaceTag but found string (text)" }"#
); );
} }
@ -1763,7 +1763,7 @@ const baseExtrusion = extrude(width, sketch001)
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_engine_error_source_range_on_last_command() { async fn kcl_test_shell_with_tag() {
let code = r#"const sketch001 = startSketchOn('XZ') let code = r#"const sketch001 = startSketchOn('XZ')
|> startProfileAt([61.74, 206.13], %) |> startProfileAt([61.74, 206.13], %)
|> xLine(305.11, %, $seg01) |> xLine(305.11, %, $seg01)
@ -1778,12 +1778,8 @@ async fn kcl_test_engine_error_source_range_on_last_command() {
}, %) }, %)
"#; "#;
let result = execute_and_snapshot(code, UnitLength::Mm).await; let result = execute_and_snapshot(code, UnitLength::Mm).await.unwrap();
assert!(result.is_err()); assert_out("shell_with_tag", &result);
assert_eq!(
result.err().unwrap().to_string(),
r#"engine: KclErrorDetails { source_ranges: [SourceRange([256, 312])], message: "Modeling command failed: [ApiError { error_code: InternalEngine, message: \"Invalid brep after shell operation\" }]" }"#
);
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
@ -2236,7 +2232,7 @@ someFunction('INVALID')
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([37, 61]), SourceRange([65, 88])], message: "Argument at index 0 was supposed to be type kcl_lib::std::sketch::SketchData but wasn't" }"# r#"semantic: KclErrorDetails { source_ranges: [SourceRange([37, 61]), SourceRange([65, 88])], message: "Argument at index 0 was supposed to be type kcl_lib::std::sketch::SketchData but found string (text)" }"#
); );
} }
@ -2257,7 +2253,7 @@ someFunction('INVALID')
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([89, 114]), SourceRange([126, 155]), SourceRange([159, 182])], message: "Argument at index 0 was supposed to be type kcl_lib::std::sketch::SketchData but wasn't" }"# r#"semantic: KclErrorDetails { source_ranges: [SourceRange([89, 114]), SourceRange([126, 155]), SourceRange([159, 182])], message: "Argument at index 0 was supposed to be type kcl_lib::std::sketch::SketchData but found string (text)" }"#
); );
} }
@ -2269,6 +2265,6 @@ async fn kcl_test_fillet_and_shell() {
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
r#"engine: KclErrorDetails { source_ranges: [SourceRange([2004, 2065])], message: "Modeling command failed: [ApiError { error_code: InternalEngine, message: \"Shell of non-planar solid3d not available yet\" }]" }"# r#"engine: KclErrorDetails { source_ranges: [SourceRange([2004, 2065])], message: "Modeling command failed: [ApiError { error_code: InternalEngine, message: \"Invalid brep after shell operation\" }]" }"#
); );
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB