Fix artifact graph to survive when there's an execution error (#5246)

This also changes artifact graph errors to point to the KCL that the
command originated from.
This commit is contained in:
Jonathan Tran
2025-02-04 20:34:56 -05:00
committed by GitHub
parent 30ac0e4f48
commit 6ce270c0d0
2 changed files with 51 additions and 25 deletions

View File

@ -158,6 +158,12 @@ export function isTopLevelModule(range: SourceRange): boolean {
return range[2] === 0
}
function firstSourceRange(error: RustKclError): SourceRange {
return error.sourceRanges.length > 0
? sourceRangeFromRust(error.sourceRanges[0])
: defaultSourceRange()
}
export const wasmUrl = () => {
// For when we're in electron (file based) or web server (network based)
// For some reason relative paths don't work as expected. Otherwise we would
@ -255,7 +261,7 @@ export const parse = (code: string | Error): ParseResult | Error => {
return new KCLError(
parsed.kind,
parsed.msg,
sourceRangeFromRust(parsed.sourceRanges[0]),
firstSourceRange(parsed),
[],
[],
defaultArtifactGraph()
@ -622,7 +628,7 @@ export const executor = async (
const kclError = new KCLError(
parsed.error.kind,
parsed.error.msg,
sourceRangeFromRust(parsed.error.sourceRanges[0]),
firstSourceRange(parsed.error),
parsed.operations,
parsed.artifactCommands,
rustArtifactGraphToMap(parsed.artifactGraph)
@ -691,7 +697,7 @@ export const modifyAstForSketch = async (
const kclError = new KCLError(
parsed.kind,
parsed.msg,
sourceRangeFromRust(parsed.sourceRanges[0]),
firstSourceRange(parsed),
[],
[],
defaultArtifactGraph()
@ -762,7 +768,7 @@ export function programMemoryInit(): ProgramMemory | Error {
return new KCLError(
parsed.kind,
parsed.msg,
sourceRangeFromRust(parsed.sourceRanges[0]),
firstSourceRange(parsed),
[],
[],
defaultArtifactGraph()

View File

@ -12,6 +12,7 @@ use serde::{ser::SerializeSeq, Deserialize, Serialize};
use uuid::Uuid;
use crate::{
errors::KclErrorDetails,
parsing::ast::types::{Node, Program},
KclError, SourceRange,
};
@ -595,9 +596,12 @@ fn artifacts_to_update(
}
ModelingCmd::EnableSketchMode(_) => {
let current_plane_id = current_plane_id.ok_or_else(|| {
KclError::internal(format!(
KclError::Internal(KclErrorDetails {
message: format!(
"Expected a current plane ID when processing EnableSketchMode command, but we have none: {id:?}"
))
),
source_ranges: vec![range],
})
})?;
let existing_plane = artifacts.get(&ArtifactId::new(current_plane_id));
match existing_plane {
@ -626,9 +630,12 @@ fn artifacts_to_update(
ModelingCmd::StartPath(_) => {
let mut return_arr = Vec::new();
let current_plane_id = current_plane_id.ok_or_else(|| {
KclError::internal(format!(
KclError::Internal(KclErrorDetails {
message: format!(
"Expected a current plane ID when processing StartPath command, but we have none: {id:?}"
))
),
source_ranges: vec![range],
})
})?;
return_arr.push(Artifact::Path(Path {
id,
@ -730,9 +737,10 @@ fn artifacts_to_update(
// TODO: Using the first one. Make sure to revisit this
// choice, don't think it matters for now.
path_id: ArtifactId::new(*loft_cmd.section_ids.first().ok_or_else(|| {
KclError::internal(format!(
"Expected at least one section ID in Loft command: {id:?}; cmd={cmd:?}"
))
KclError::Internal(KclErrorDetails {
message: format!("Expected at least one section ID in Loft command: {id:?}; cmd={cmd:?}"),
source_ranges: vec![range],
})
})?),
surface_ids: Vec::new(),
edge_ids: Vec::new(),
@ -772,9 +780,12 @@ fn artifacts_to_update(
};
last_path = Some(path);
let path_sweep_id = path.sweep_id.ok_or_else(|| {
KclError::internal(format!(
KclError::Internal(KclErrorDetails {
message:format!(
"Expected a sweep ID on the path when processing Solid3dGetExtrusionFaceInfo command, but we have none: {id:?}, {path:?}"
))
),
source_ranges: vec![range],
})
})?;
return_arr.push(Artifact::Wall(Wall {
id: face_id,
@ -803,9 +814,12 @@ fn artifacts_to_update(
continue;
};
let path_sweep_id = path.sweep_id.ok_or_else(|| {
KclError::internal(format!(
KclError::Internal(KclErrorDetails {
message:format!(
"Expected a sweep ID on the path when processing Solid3dGetExtrusionFaceInfo command, but we have none: {id:?}, {path:?}"
))
),
source_ranges: vec![range],
})
})?;
return_arr.push(Artifact::Cap(Cap {
id: face_id,
@ -848,17 +862,23 @@ fn artifacts_to_update(
let response_edge_id = match response {
OkModelingCmdResponse::Solid3dGetNextAdjacentEdge(r) => {
let Some(edge_id) = r.edge else {
return Err(KclError::internal(format!(
return Err(KclError::Internal(KclErrorDetails {
message:format!(
"Expected Solid3dGetNextAdjacentEdge response to have an edge ID, but found none: id={id:?}, {response:?}"
)));
),
source_ranges: vec![range],
}));
};
edge_id.into()
}
OkModelingCmdResponse::Solid3dGetOppositeEdge(r) => r.edge.into(),
_ => {
return Err(KclError::internal(format!(
return Err(KclError::Internal(KclErrorDetails {
message:format!(
"Expected Solid3dGetNextAdjacentEdge or Solid3dGetOppositeEdge response, but got: id={id:?}, {response:?}"
)));
),
source_ranges: vec![range],
}));
}
};