Merge remote-tracking branch 'origin/main' into jess/changes-import

* origin/main: (26 commits)
  attempt to import win-ca on windows (#6136)
  Upgrade e2e-tests windows runner from 4 cores to 8 (#6166)
  Follow-up fixes after bearing sample rename (#6164)
  Add test for #5799: "Only showing axis planes when there are no errors" (#6007)
  Wait for export button to make test more reliable (#6143)
  sketching on a mirror2d thats been extruded fixed! (#6149)
  Bump vite from 5.4.16 to 5.4.17 in /packages/codemirror-lang-kcl in the security group (#6150)
  Bump vite from 5.4.16 to 5.4.17 in the security group (#6151)
  Update all KCL-Samples to be more ME friendly (#6132)
  Shorten feedback cycle for legitimate failures (#6146)
  Remove the camera projection toggle from the UI (#6077)
  Use all available CPUs to run tests on CI (#6138)
  [fix] Get rid of risky useEffect in restart onboarding flow (#6133)
  Feature: Traditional menu actions in desktop application part II (#6030)
  [Bug] fix some UI friction from imports (#6139)
  Use scene fixture to make test more reliable on macOS (#6140)
  Fix: function composition during playwright setup created a massive page.reload loop (#6137)
  Alternative way to make appMachine spawned children type safe (#5890)
  [BUG] mutate ast to keep comments for pipe split ast-mod (#6128)
  Rename the app to Zoo Design Studio (#5974)
  ...
This commit is contained in:
Jess Frazelle
2025-04-05 09:33:50 -07:00
349 changed files with 50442 additions and 44887 deletions

View File

@ -3,12 +3,12 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use super::{types::NumericType, ArtifactId, KclValue};
use crate::{docs::StdLibFn, std::get_stdlib_fn, SourceRange};
use crate::{docs::StdLibFn, std::get_stdlib_fn, ModuleId, SourceRange};
/// A CAD modeling operation for display in the feature tree, AKA operations
/// timeline.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[ts(export_to = "Operation.ts")]
#[serde(tag = "type")]
pub enum Operation {
#[serde(rename_all = "camelCase")]
@ -40,7 +40,34 @@ pub enum Operation {
is_error: bool,
},
#[serde(rename_all = "camelCase")]
UserDefinedFunctionCall {
GroupBegin {
/// The details of the group.
group: Group,
/// The source range of the operation in the source code.
source_range: SourceRange,
},
GroupEnd,
}
impl Operation {
/// If the variant is `StdLibCall`, set the `is_error` field.
pub(crate) fn set_std_lib_call_is_error(&mut self, is_err: bool) {
match self {
Self::StdLibCall { ref mut is_error, .. } => *is_error = is_err,
Self::KclStdLibCall { ref mut is_error, .. } => *is_error = is_err,
Self::GroupBegin { .. } | Self::GroupEnd => {}
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export_to = "Operation.ts")]
#[serde(tag = "type")]
#[expect(clippy::large_enum_variant)]
pub enum Group {
/// A function call.
#[serde(rename_all = "camelCase")]
FunctionCall {
/// The name of the user-defined function being called. Anonymous
/// functions have no name.
name: Option<String>,
@ -51,26 +78,20 @@ pub enum Operation {
unlabeled_arg: Option<OpArg>,
/// The labeled keyword arguments to the function.
labeled_args: IndexMap<String, OpArg>,
/// The source range of the operation in the source code.
source_range: SourceRange,
},
UserDefinedFunctionReturn,
}
impl Operation {
/// If the variant is `StdLibCall`, set the `is_error` field.
pub(crate) fn set_std_lib_call_is_error(&mut self, is_err: bool) {
match self {
Self::StdLibCall { ref mut is_error, .. } => *is_error = is_err,
Self::KclStdLibCall { ref mut is_error, .. } => *is_error = is_err,
Self::UserDefinedFunctionCall { .. } | Self::UserDefinedFunctionReturn => {}
}
}
/// A whole-module import use.
#[serde(rename_all = "camelCase")]
ModuleInstance {
/// The name of the module being used.
name: String,
/// The ID of the module which can be used to determine its path.
module_id: ModuleId,
},
}
/// An argument to a CAD modeling operation.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[ts(export_to = "Operation.ts")]
#[serde(rename_all = "camelCase")]
pub struct OpArg {
/// The runtime value of the argument. Instead of using [`KclValue`], we
@ -90,7 +111,7 @@ impl OpArg {
/// A reference to a standard library function. This exists to implement
/// `PartialEq` and `Eq` for `Operation`.
#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[ts(export_to = "Operation.ts")]
#[serde(rename_all = "camelCase")]
pub struct StdLibFnRef {
// The following doc comment gets inlined into Operation, overriding what's
@ -154,7 +175,7 @@ fn is_false(b: &bool) -> bool {
/// A KCL value used in Operations. `ArtifactId`s are used to refer to the
/// actual scene objects. Any data not needed in the UI may be omitted.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[ts(export_to = "Operation.ts")]
#[serde(tag = "type")]
pub enum OpKclValue {
Uuid {
@ -212,21 +233,21 @@ pub enum OpKclValue {
pub type OpKclObjectFields = IndexMap<String, OpKclValue>;
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[ts(export_to = "Operation.ts")]
#[serde(rename_all = "camelCase")]
pub struct OpSketch {
artifact_id: ArtifactId,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[ts(export_to = "Operation.ts")]
#[serde(rename_all = "camelCase")]
pub struct OpSolid {
artifact_id: ArtifactId,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[ts(export_to = "Operation.ts")]
#[serde(rename_all = "camelCase")]
pub struct OpHelix {
artifact_id: ArtifactId,

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use async_recursion::async_recursion;
use indexmap::IndexMap;
use super::{kcl_value::TypeDef, types::PrimitiveType};
use super::{cad_op::Group, kcl_value::TypeDef, types::PrimitiveType};
use crate::{
engine::ExecutionKind,
errors::{KclError, KclErrorDetails},
@ -20,7 +20,7 @@ use crate::{
modules::{ModuleId, ModulePath, ModuleRepr},
parsing::ast::types::{
Annotation, ArrayExpression, ArrayRangeExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem,
CallExpression, CallExpressionKw, Expr, FunctionExpression, IfExpression, ImportPath, ImportSelector,
BoxNode, CallExpression, CallExpressionKw, Expr, FunctionExpression, IfExpression, ImportPath, ImportSelector,
ItemVisibility, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, Name, Node, NodeRef,
ObjectExpression, PipeExpression, Program, TagDeclarator, Type, UnaryExpression, UnaryOperator,
},
@ -564,10 +564,19 @@ impl ExecutorContext {
async fn exec_module_for_result(
&self,
module_id: ModuleId,
module_name: &BoxNode<Name>,
exec_state: &mut ExecState,
exec_kind: ExecutionKind,
source_range: SourceRange,
) -> Result<Option<KclValue>, KclError> {
exec_state.global.operations.push(Operation::GroupBegin {
group: Group::ModuleInstance {
name: module_name.to_string(),
module_id,
},
source_range,
});
let path = exec_state.global.module_infos[&module_id].path.clone();
let mut repr = exec_state.global.module_infos[&module_id].take_repr();
// DON'T EARLY RETURN! We need to restore the module repr
@ -593,6 +602,9 @@ impl ExecutorContext {
};
exec_state.global.module_infos[&module_id].restore_repr(repr);
exec_state.global.operations.push(Operation::GroupEnd);
result
}
@ -644,7 +656,7 @@ impl ExecutorContext {
Expr::Name(name) => {
let value = name.get_result(exec_state, self).await?.clone();
if let KclValue::Module { value: module_id, meta } = value {
self.exec_module_for_result(module_id, exec_state, ExecutionKind::Normal, metadata.source_range)
self.exec_module_for_result(module_id, name, exec_state, ExecutionKind::Normal, metadata.source_range)
.await?
.unwrap_or_else(|| {
exec_state.warn(CompilationError::err(
@ -1401,7 +1413,7 @@ impl Node<CallExpressionKw> {
if matches!(fn_src, FunctionSource::User { .. }) && !ctx.is_isolated_execution().await {
// Track return operation.
exec_state.global.operations.push(Operation::UserDefinedFunctionReturn);
exec_state.global.operations.push(Operation::GroupEnd);
}
let result = return_value.ok_or_else(move || {
@ -1511,12 +1523,14 @@ impl Node<CallExpression> {
if !ctx.is_isolated_execution().await {
// Track call operation.
exec_state.global.operations.push(Operation::UserDefinedFunctionCall {
name: Some(fn_name.to_string()),
function_source_range: func.function_def_source_range().unwrap_or_default(),
unlabeled_arg: None,
// TODO: Add the arguments for legacy positional parameters.
labeled_args: Default::default(),
exec_state.global.operations.push(Operation::GroupBegin {
group: Group::FunctionCall {
name: Some(fn_name.to_string()),
function_source_range: func.function_def_source_range().unwrap_or_default(),
unlabeled_arg: None,
// TODO: Add the arguments for legacy positional parameters.
labeled_args: Default::default(),
},
source_range: callsite,
});
}
@ -1550,7 +1564,7 @@ impl Node<CallExpression> {
if !ctx.is_isolated_execution().await {
// Track return operation.
exec_state.global.operations.push(Operation::UserDefinedFunctionReturn);
exec_state.global.operations.push(Operation::GroupEnd);
}
Ok(result)
@ -2331,15 +2345,17 @@ impl FunctionSource {
.iter()
.map(|(k, arg)| (k.clone(), OpArg::new(OpKclValue::from(&arg.value), arg.source_range)))
.collect();
exec_state.global.operations.push(Operation::UserDefinedFunctionCall {
name: fn_name,
function_source_range: ast.as_source_range(),
unlabeled_arg: args
.kw_args
.unlabeled
.as_ref()
.map(|arg| OpArg::new(OpKclValue::from(&arg.value), arg.source_range)),
labeled_args: op_labeled_args,
exec_state.global.operations.push(Operation::GroupBegin {
group: Group::FunctionCall {
name: fn_name,
function_source_range: ast.as_source_range(),
unlabeled_arg: args
.kw_args
.unlabeled
.as_ref()
.map(|arg| OpArg::new(OpKclValue::from(&arg.value), arg.source_range)),
labeled_args: op_labeled_args,
},
source_range: callsite,
});
}

View File

@ -418,6 +418,9 @@ pub struct Sketch {
pub artifact_id: ArtifactId,
#[ts(skip)]
pub original_id: uuid::Uuid,
/// If the sketch includes a mirror.
#[serde(skip)]
pub mirror: Option<uuid::Uuid>,
pub units: UnitLen,
/// Metadata.
#[serde(skip)]

View File

@ -241,7 +241,7 @@ pub enum ContextType {
Live,
/// Completely mocked connection
/// Mock mode is only for the modeling app when they just want to mock engine calls and not
/// Mock mode is only for the Design Studio when they just want to mock engine calls and not
/// actually make them.
Mock,