get responses back from batch (#2687)
* updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * remove my stupid println Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * weird typescript Signed-off-by: Jess Frazelle <github@jessfraz.com> * better batch stuff; Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * ckeanup Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * typpo Signed-off-by: Jess Frazelle <github@jessfraz.com> * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * batch more Signed-off-by: Jess Frazelle <github@jessfraz.com> * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * thing * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * up[dates Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixces Signed-off-by: Jess Frazelle <github@jessfraz.com> * cleanups Signed-off-by: Jess Frazelle <github@jessfraz.com> * images Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * empty * cleanups Signed-off-by: Jess Frazelle <github@jessfraz.com> * console log all the things Signed-off-by: Jess Frazelle <github@jessfraz.com> * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * fixups Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * console log cleanup Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * nicer types Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * remove logs Signed-off-by: Jess Frazelle <github@jessfraz.com> * remove logs Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 45 KiB |
@ -32,9 +32,7 @@ import {
|
|||||||
SKETCH_GROUP_SEGMENTS,
|
SKETCH_GROUP_SEGMENTS,
|
||||||
SKETCH_LAYER,
|
SKETCH_LAYER,
|
||||||
X_AXIS,
|
X_AXIS,
|
||||||
XZ_PLANE,
|
|
||||||
Y_AXIS,
|
Y_AXIS,
|
||||||
YZ_PLANE,
|
|
||||||
} from './sceneInfra'
|
} from './sceneInfra'
|
||||||
import { isQuaternionVertical, quaternionFromUpNForward } from './helpers'
|
import { isQuaternionVertical, quaternionFromUpNForward } from './helpers'
|
||||||
import {
|
import {
|
||||||
|
@ -47,7 +47,6 @@ import {
|
|||||||
TANGENTIAL_ARC_TO_SEGMENT,
|
TANGENTIAL_ARC_TO_SEGMENT,
|
||||||
getParentGroup,
|
getParentGroup,
|
||||||
getSketchOrientationDetails,
|
getSketchOrientationDetails,
|
||||||
getSketchQuaternion,
|
|
||||||
} from 'clientSideScene/sceneEntities'
|
} from 'clientSideScene/sceneEntities'
|
||||||
import {
|
import {
|
||||||
moveValueIntoNewVariablePath,
|
moveValueIntoNewVariablePath,
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { fireEvent, render, screen } from '@testing-library/react'
|
import { render, screen } from '@testing-library/react'
|
||||||
import { BrowserRouter } from 'react-router-dom'
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
import ProjectSidebarMenu from './ProjectSidebarMenu'
|
import ProjectSidebarMenu from './ProjectSidebarMenu'
|
||||||
import { SettingsAuthProviderJest } from './SettingsAuthProvider'
|
import { SettingsAuthProviderJest } from './SettingsAuthProvider'
|
||||||
import { APP_NAME } from 'lib/constants'
|
|
||||||
import { CommandBarProvider } from './CommandBar/CommandBarProvider'
|
import { CommandBarProvider } from './CommandBar/CommandBarProvider'
|
||||||
import { Project } from 'wasm-lib/kcl/bindings/Project'
|
import { Project } from 'wasm-lib/kcl/bindings/Project'
|
||||||
|
|
||||||
|
@ -92,7 +92,6 @@ export class KclManager {
|
|||||||
return this._kclErrors
|
return this._kclErrors
|
||||||
}
|
}
|
||||||
set kclErrors(kclErrors) {
|
set kclErrors(kclErrors) {
|
||||||
console.log('[lsp] not lsp, actually typescript: ', kclErrors)
|
|
||||||
this._kclErrors = kclErrors
|
this._kclErrors = kclErrors
|
||||||
let diagnostics = kclErrorsToDiagnostics(kclErrors)
|
let diagnostics = kclErrorsToDiagnostics(kclErrors)
|
||||||
editorManager.addDiagnostics(diagnostics)
|
editorManager.addDiagnostics(diagnostics)
|
||||||
|
@ -58,6 +58,9 @@ function isHighlightSetEntity_type(
|
|||||||
|
|
||||||
type WebSocketResponse = Models['WebSocketResponse_type']
|
type WebSocketResponse = Models['WebSocketResponse_type']
|
||||||
type OkWebSocketResponseData = Models['OkWebSocketResponseData_type']
|
type OkWebSocketResponseData = Models['OkWebSocketResponseData_type']
|
||||||
|
type BatchResponseMap = {
|
||||||
|
[key: string]: Models['BatchResponse_type']
|
||||||
|
}
|
||||||
|
|
||||||
type ResultCommand = CommandInfo & {
|
type ResultCommand = CommandInfo & {
|
||||||
type: 'result'
|
type: 'result'
|
||||||
@ -1316,7 +1319,8 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
message.success &&
|
message.success &&
|
||||||
message.resp.type === 'modeling' &&
|
(message.resp.type === 'modeling' ||
|
||||||
|
message.resp.type === 'modeling_batch') &&
|
||||||
message.request_id
|
message.request_id
|
||||||
) {
|
) {
|
||||||
this.handleModelingCommand(
|
this.handleModelingCommand(
|
||||||
@ -1380,19 +1384,60 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
id: string,
|
id: string,
|
||||||
raw: WebSocketResponse
|
raw: WebSocketResponse
|
||||||
) {
|
) {
|
||||||
if (message.type !== 'modeling') {
|
if (!(message.type === 'modeling' || message.type === 'modeling_batch')) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const modelingResponse = message.data.modeling_response
|
|
||||||
const command = this.artifactMap[id]
|
const command = this.artifactMap[id]
|
||||||
|
let modelingResponse: Models['OkModelingCmdResponse_type'] = {
|
||||||
|
type: 'empty',
|
||||||
|
}
|
||||||
|
if ('modeling_response' in message.data) {
|
||||||
|
modelingResponse = message.data.modeling_response
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
command?.type === 'pending' &&
|
command?.type === 'pending' &&
|
||||||
command.commandType === 'batch' &&
|
command.commandType === 'batch' &&
|
||||||
command?.additionalData?.type === 'batch-ids'
|
command?.additionalData?.type === 'batch-ids'
|
||||||
) {
|
) {
|
||||||
|
if ('responses' in message.data) {
|
||||||
|
const batchResponse = message.data.responses as BatchResponseMap
|
||||||
|
// Iterate over the map of responses.
|
||||||
|
Object.entries(batchResponse).forEach(([key, response]) => {
|
||||||
|
// If the response is a success, we resolve the promise.
|
||||||
|
if ('response' in response && response.response) {
|
||||||
|
this.handleModelingCommand(
|
||||||
|
{
|
||||||
|
type: 'modeling',
|
||||||
|
data: {
|
||||||
|
modeling_response: response.response,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
key,
|
||||||
|
{
|
||||||
|
request_id: key,
|
||||||
|
resp: {
|
||||||
|
type: 'modeling',
|
||||||
|
data: {
|
||||||
|
modeling_response: response.response,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else if ('errors' in response) {
|
||||||
|
this.handleFailedModelingCommand(key, {
|
||||||
|
request_id: key,
|
||||||
|
success: false,
|
||||||
|
errors: response.errors,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
command.additionalData.ids.forEach((id) => {
|
command.additionalData.ids.forEach((id) => {
|
||||||
this.handleModelingCommand(message, id, raw)
|
this.handleModelingCommand(message, id, raw)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
// batch artifact is just a container, we don't need to keep it
|
// batch artifact is just a container, we don't need to keep it
|
||||||
// once we process all the commands inside it
|
// once we process all the commands inside it
|
||||||
const resolve = command.resolve
|
const resolve = command.resolve
|
||||||
@ -1401,7 +1446,6 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
id,
|
id,
|
||||||
commandType: command.commandType,
|
commandType: command.commandType,
|
||||||
range: command.range,
|
range: command.range,
|
||||||
data: modelingResponse,
|
|
||||||
raw,
|
raw,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -1733,7 +1777,7 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
command: EngineCommand
|
command: EngineCommand
|
||||||
ast: Program
|
ast: Program
|
||||||
idToRangeMap?: { [key: string]: SourceRange }
|
idToRangeMap?: { [key: string]: SourceRange }
|
||||||
}): Promise<any> {
|
}): Promise<ResolveCommand | void> {
|
||||||
if (this.engineConnection === undefined) {
|
if (this.engineConnection === undefined) {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
@ -1802,11 +1846,13 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
command: Models['ModelingCmd_type'],
|
command: Models['ModelingCmd_type'],
|
||||||
ast?: Program,
|
ast?: Program,
|
||||||
range?: SourceRange
|
range?: SourceRange
|
||||||
) {
|
): Promise<ResolveCommand | void> {
|
||||||
let resolve: (val: any) => void = () => {}
|
let resolve: (val: any) => void = () => {}
|
||||||
const promise = new Promise((_resolve, reject) => {
|
const promise: Promise<ResolveCommand | void> = new Promise(
|
||||||
|
(_resolve, reject) => {
|
||||||
resolve = _resolve
|
resolve = _resolve
|
||||||
})
|
}
|
||||||
|
)
|
||||||
const getParentId = (): string | undefined => {
|
const getParentId = (): string | undefined => {
|
||||||
if (command.type === 'extend_path') return command.path
|
if (command.type === 'extend_path') return command.path
|
||||||
if (command.type === 'solid3d_get_extrusion_face_info') {
|
if (command.type === 'solid3d_get_extrusion_face_info') {
|
||||||
@ -1867,11 +1913,13 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
idToRangeMap?: { [key: string]: SourceRange },
|
idToRangeMap?: { [key: string]: SourceRange },
|
||||||
ast?: Program,
|
ast?: Program,
|
||||||
range?: SourceRange
|
range?: SourceRange
|
||||||
) {
|
): Promise<ResolveCommand | void> {
|
||||||
let resolve: (val: any) => void = () => {}
|
let resolve: (val: any) => void = () => {}
|
||||||
const promise = new Promise((_resolve, reject) => {
|
const promise: Promise<ResolveCommand | void> = new Promise(
|
||||||
|
(_resolve, reject) => {
|
||||||
resolve = _resolve
|
resolve = _resolve
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if (!idToRangeMap) {
|
if (!idToRangeMap) {
|
||||||
throw new Error('idToRangeMap is required for batch commands')
|
throw new Error('idToRangeMap is required for batch commands')
|
||||||
@ -1891,7 +1939,7 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
resolve,
|
resolve,
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(
|
Promise.all(
|
||||||
commands.map((c) =>
|
commands.map((c) =>
|
||||||
this.handlePendingCommand(c.cmd_id, c.cmd, ast, idToRangeMap[c.cmd_id])
|
this.handlePendingCommand(c.cmd_id, c.cmd, ast, idToRangeMap[c.cmd_id])
|
||||||
)
|
)
|
||||||
@ -1903,7 +1951,7 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
rangeStr: string,
|
rangeStr: string,
|
||||||
commandStr: string,
|
commandStr: string,
|
||||||
idToRangeStr: string
|
idToRangeStr: string
|
||||||
): Promise<any> {
|
): Promise<string | void> {
|
||||||
if (this.engineConnection === undefined) {
|
if (this.engineConnection === undefined) {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
@ -1932,13 +1980,13 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
command,
|
command,
|
||||||
ast: this.getAst(),
|
ast: this.getAst(),
|
||||||
idToRangeMap,
|
idToRangeMap,
|
||||||
}).then(({ raw }: { raw: WebSocketResponse | undefined | null }) => {
|
}).then((resp) => {
|
||||||
if (raw === undefined || raw === null) {
|
if (!resp) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'returning modeling cmd response to the rust side is undefined or null'
|
'returning modeling cmd response to the rust side is undefined or null'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return JSON.stringify(raw)
|
return JSON.stringify(resp.raw)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
commandResult(id: string): Promise<any> {
|
commandResult(id: string): Promise<any> {
|
||||||
|
@ -1,20 +1,26 @@
|
|||||||
//! Executes KCL programs.
|
//! Executes KCL programs.
|
||||||
//! The server reuses the same engine session for each KCL program it receives.
|
//! The server reuses the same engine session for each KCL program it receives.
|
||||||
use std::net::SocketAddr;
|
use std::{
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
net::SocketAddr,
|
||||||
use std::sync::Arc;
|
sync::{
|
||||||
use std::time::Duration;
|
atomic::{AtomicUsize, Ordering},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
use hyper::body::Bytes;
|
use hyper::{
|
||||||
use hyper::header::CONTENT_TYPE;
|
body::Bytes,
|
||||||
use hyper::service::{make_service_fn, service_fn};
|
header::CONTENT_TYPE,
|
||||||
use hyper::{Body, Error, Response, Server};
|
service::{make_service_fn, service_fn},
|
||||||
use kcl_lib::executor::ExecutorContext;
|
Body, Error, Response, Server,
|
||||||
use kcl_lib::settings::types::UnitLength;
|
};
|
||||||
use kcl_lib::test_server::RequestBody;
|
use kcl_lib::{executor::ExecutorContext, settings::types::UnitLength, test_server::RequestBody};
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::{
|
||||||
use tokio::task::JoinHandle;
|
sync::{mpsc, oneshot},
|
||||||
use tokio::time::sleep;
|
task::JoinHandle,
|
||||||
|
time::sleep,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ServerArgs {
|
pub struct ServerArgs {
|
||||||
|
@ -3,7 +3,7 @@ use schemars::JsonSchema;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value as JValue;
|
use serde_json::Value as JValue;
|
||||||
|
|
||||||
use super::{Literal, Value};
|
use crate::ast::types::{Literal, Value};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)]
|
||||||
#[databake(path = kcl_lib::ast::types)]
|
#[databake(path = kcl_lib::ast::types)]
|
||||||
|
@ -4,8 +4,10 @@ use databake::*;
|
|||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::ConstraintLevel;
|
use crate::{
|
||||||
use crate::executor::{MemoryItem, SourceRange, UserVal};
|
ast::types::ConstraintLevel,
|
||||||
|
executor::{MemoryItem, SourceRange, UserVal},
|
||||||
|
};
|
||||||
|
|
||||||
/// KCL value for an optional parameter which was not given an argument.
|
/// KCL value for an optional parameter which was not given an argument.
|
||||||
/// (remember, parameters are in the function declaration,
|
/// (remember, parameters are in the function declaration,
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
//! Functions for generating docs for our stdlib functions.
|
//! Functions for generating docs for our stdlib functions.
|
||||||
|
|
||||||
use crate::std::Primitive;
|
use std::path::Path;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::Path;
|
|
||||||
use tower_lsp::lsp_types::{
|
use tower_lsp::lsp_types::{
|
||||||
CompletionItem, CompletionItemKind, CompletionItemLabelDetails, Documentation, InsertTextFormat, MarkupContent,
|
CompletionItem, CompletionItemKind, CompletionItemLabelDetails, Documentation, InsertTextFormat, MarkupContent,
|
||||||
MarkupKind, ParameterInformation, ParameterLabel, SignatureHelp, SignatureInformation,
|
MarkupKind, ParameterInformation, ParameterLabel, SignatureHelp, SignatureInformation,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::std::Primitive;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, ts_rs::TS)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, ts_rs::TS)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
@ -6,7 +6,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
use kittycad::types::{OkWebSocketResponseData, WebSocketRequest, WebSocketResponse};
|
use kittycad::types::{WebSocketRequest, WebSocketResponse};
|
||||||
use tokio::sync::{mpsc, oneshot, RwLock};
|
use tokio::sync::{mpsc, oneshot, RwLock};
|
||||||
use tokio_tungstenite::tungstenite::Message as WsMsg;
|
use tokio_tungstenite::tungstenite::Message as WsMsg;
|
||||||
|
|
||||||
@ -183,6 +183,39 @@ impl EngineConnection {
|
|||||||
for e in ws_resp.errors.iter().flatten() {
|
for e in ws_resp.errors.iter().flatten() {
|
||||||
println!("got error message: {} {}", e.error_code, e.message);
|
println!("got error message: {} {}", e.error_code, e.message);
|
||||||
}
|
}
|
||||||
|
// If we got a batch response, add all the inner responses.
|
||||||
|
println!("got response: {:?}", ws_resp);
|
||||||
|
if let Some(kittycad::types::OkWebSocketResponseData::ModelingBatch { responses }) =
|
||||||
|
&ws_resp.resp
|
||||||
|
{
|
||||||
|
for (resp_id, batch_response) in responses {
|
||||||
|
let id: uuid::Uuid = resp_id.parse().unwrap();
|
||||||
|
if let Some(response) = &batch_response.response {
|
||||||
|
responses_clone.insert(
|
||||||
|
id,
|
||||||
|
kittycad::types::WebSocketResponse {
|
||||||
|
request_id: Some(id),
|
||||||
|
resp: Some(kittycad::types::OkWebSocketResponseData::Modeling {
|
||||||
|
modeling_response: response.clone(),
|
||||||
|
}),
|
||||||
|
errors: None,
|
||||||
|
success: Some(true),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
responses_clone.insert(
|
||||||
|
id,
|
||||||
|
kittycad::types::WebSocketResponse {
|
||||||
|
request_id: Some(id),
|
||||||
|
resp: None,
|
||||||
|
errors: batch_response.errors.clone(),
|
||||||
|
success: Some(false),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(id) = ws_resp.request_id {
|
if let Some(id) = ws_resp.request_id {
|
||||||
responses_clone.insert(id, ws_resp.clone());
|
responses_clone.insert(id, ws_resp.clone());
|
||||||
}
|
}
|
||||||
@ -246,7 +279,7 @@ impl EngineManager for EngineConnection {
|
|||||||
source_range: crate::executor::SourceRange,
|
source_range: crate::executor::SourceRange,
|
||||||
cmd: kittycad::types::WebSocketRequest,
|
cmd: kittycad::types::WebSocketRequest,
|
||||||
_id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>,
|
_id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>,
|
||||||
) -> Result<OkWebSocketResponseData, KclError> {
|
) -> Result<WebSocketResponse, KclError> {
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
|
|
||||||
// Send the request to the engine, via the actor.
|
// Send the request to the engine, via the actor.
|
||||||
@ -291,14 +324,7 @@ impl EngineManager for EngineConnection {
|
|||||||
}
|
}
|
||||||
// We pop off the responses to cleanup our mappings.
|
// We pop off the responses to cleanup our mappings.
|
||||||
if let Some((_, resp)) = self.responses.remove(&id) {
|
if let Some((_, resp)) = self.responses.remove(&id) {
|
||||||
return if let Some(data) = &resp.resp {
|
return Ok(resp);
|
||||||
Ok(data.clone())
|
|
||||||
} else {
|
|
||||||
Err(KclError::Engine(KclErrorDetails {
|
|
||||||
message: format!("Modeling command failed: {:?}", resp.errors),
|
|
||||||
source_ranges: vec![source_range],
|
|
||||||
}))
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
//! Functions for setting up our WebSocket and WebRTC connections for communications with the
|
//! Functions for setting up our WebSocket and WebRTC connections for communications with the
|
||||||
//! engine.
|
//! engine.
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kittycad::types::{OkWebSocketResponseData, WebSocketRequest};
|
use kittycad::types::{OkWebSocketResponseData, WebSocketRequest, WebSocketResponse};
|
||||||
|
|
||||||
use crate::{errors::KclError, executor::DefaultPlanes};
|
use crate::{errors::KclError, executor::DefaultPlanes};
|
||||||
|
|
||||||
@ -37,13 +40,43 @@ impl crate::engine::EngineManager for EngineConnection {
|
|||||||
|
|
||||||
async fn inner_send_modeling_cmd(
|
async fn inner_send_modeling_cmd(
|
||||||
&self,
|
&self,
|
||||||
_id: uuid::Uuid,
|
id: uuid::Uuid,
|
||||||
_source_range: crate::executor::SourceRange,
|
_source_range: crate::executor::SourceRange,
|
||||||
_cmd: kittycad::types::WebSocketRequest,
|
cmd: kittycad::types::WebSocketRequest,
|
||||||
_id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>,
|
_id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>,
|
||||||
) -> Result<OkWebSocketResponseData, KclError> {
|
) -> Result<WebSocketResponse, KclError> {
|
||||||
Ok(OkWebSocketResponseData::Modeling {
|
match cmd {
|
||||||
modeling_response: kittycad::types::OkModelingCmdResponse::Empty {},
|
WebSocketRequest::ModelingCmdBatchReq {
|
||||||
|
ref requests,
|
||||||
|
batch_id: _,
|
||||||
|
responses: _,
|
||||||
|
} => {
|
||||||
|
// Create the empty responses.
|
||||||
|
let mut responses = HashMap::new();
|
||||||
|
for request in requests {
|
||||||
|
responses.insert(
|
||||||
|
request.cmd_id.to_string(),
|
||||||
|
kittycad::types::BatchResponse {
|
||||||
|
response: Some(kittycad::types::OkModelingCmdResponse::Empty {}),
|
||||||
|
errors: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(WebSocketResponse {
|
||||||
|
request_id: Some(id),
|
||||||
|
resp: Some(OkWebSocketResponseData::ModelingBatch { responses }),
|
||||||
|
success: Some(true),
|
||||||
|
errors: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
_ => Ok(WebSocketResponse {
|
||||||
|
request_id: Some(id),
|
||||||
|
resp: Some(OkWebSocketResponseData::Modeling {
|
||||||
|
modeling_response: kittycad::types::OkModelingCmdResponse::Empty {},
|
||||||
|
}),
|
||||||
|
success: Some(true),
|
||||||
|
errors: None,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ impl crate::engine::EngineManager for EngineConnection {
|
|||||||
source_range: crate::executor::SourceRange,
|
source_range: crate::executor::SourceRange,
|
||||||
cmd: kittycad::types::WebSocketRequest,
|
cmd: kittycad::types::WebSocketRequest,
|
||||||
id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>,
|
id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>,
|
||||||
) -> Result<kittycad::types::OkWebSocketResponseData, KclError> {
|
) -> Result<kittycad::types::WebSocketResponse, KclError> {
|
||||||
let source_range_str = serde_json::to_string(&source_range).map_err(|e| {
|
let source_range_str = serde_json::to_string(&source_range).map_err(|e| {
|
||||||
KclError::Engine(KclErrorDetails {
|
KclError::Engine(KclErrorDetails {
|
||||||
message: format!("Failed to serialize source range: {:?}", e),
|
message: format!("Failed to serialize source range: {:?}", e),
|
||||||
@ -182,18 +182,6 @@ impl crate::engine::EngineManager for EngineConnection {
|
|||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(data) = &ws_result.resp {
|
Ok(ws_result)
|
||||||
Ok(data.clone())
|
|
||||||
} else if let Some(errors) = &ws_result.errors {
|
|
||||||
Err(KclError::Engine(KclErrorDetails {
|
|
||||||
message: format!("Modeling command failed: {:?}", errors),
|
|
||||||
source_ranges: vec![source_range],
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
Err(KclError::Engine(KclErrorDetails {
|
|
||||||
message: format!("Modeling command failed: {:?}", ws_result),
|
|
||||||
source_ranges: vec![source_range],
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,13 +47,13 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
source_range: crate::executor::SourceRange,
|
source_range: crate::executor::SourceRange,
|
||||||
cmd: kittycad::types::WebSocketRequest,
|
cmd: kittycad::types::WebSocketRequest,
|
||||||
id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>,
|
id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>,
|
||||||
) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError>;
|
) -> Result<kittycad::types::WebSocketResponse, crate::errors::KclError>;
|
||||||
|
|
||||||
async fn clear_scene(&self, source_range: crate::executor::SourceRange) -> Result<(), crate::errors::KclError> {
|
async fn clear_scene(&self, source_range: crate::executor::SourceRange) -> Result<(), crate::errors::KclError> {
|
||||||
self.send_modeling_cmd(
|
self.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
source_range,
|
source_range,
|
||||||
kittycad::types::ModelingCmd::SceneClearAll {},
|
&kittycad::types::ModelingCmd::SceneClearAll {},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@ -67,12 +67,13 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_modeling_cmd(
|
// Add a modeling command to the batch but don't fire it right away.
|
||||||
|
async fn batch_modeling_cmd(
|
||||||
&self,
|
&self,
|
||||||
id: uuid::Uuid,
|
id: uuid::Uuid,
|
||||||
source_range: crate::executor::SourceRange,
|
source_range: crate::executor::SourceRange,
|
||||||
cmd: kittycad::types::ModelingCmd,
|
cmd: &kittycad::types::ModelingCmd,
|
||||||
) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> {
|
) -> Result<(), crate::errors::KclError> {
|
||||||
let req = WebSocketRequest::ModelingCmdReq {
|
let req = WebSocketRequest::ModelingCmdReq {
|
||||||
cmd: cmd.clone(),
|
cmd: cmd.clone(),
|
||||||
cmd_id: id,
|
cmd_id: id,
|
||||||
@ -81,17 +82,18 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
// Add cmd to the batch.
|
// Add cmd to the batch.
|
||||||
self.batch().lock().unwrap().push((req, source_range));
|
self.batch().lock().unwrap().push((req, source_range));
|
||||||
|
|
||||||
// If the batch only has this one command that expects a return value,
|
Ok(())
|
||||||
// fire it right away, or if we want to flush batch queue.
|
|
||||||
let is_sending = is_cmd_with_return_values(&cmd);
|
|
||||||
|
|
||||||
// Return a fake modeling_request empty response.
|
|
||||||
if !is_sending {
|
|
||||||
return Ok(OkWebSocketResponseData::Modeling {
|
|
||||||
modeling_response: kittycad::types::OkModelingCmdResponse::Empty {},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send the modeling cmd and wait for the response.
|
||||||
|
async fn send_modeling_cmd(
|
||||||
|
&self,
|
||||||
|
id: uuid::Uuid,
|
||||||
|
source_range: crate::executor::SourceRange,
|
||||||
|
cmd: kittycad::types::ModelingCmd,
|
||||||
|
) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> {
|
||||||
|
self.batch_modeling_cmd(id, source_range, &cmd).await?;
|
||||||
|
|
||||||
// Flush the batch queue.
|
// Flush the batch queue.
|
||||||
self.flush_batch(source_range).await
|
self.flush_batch(source_range).await
|
||||||
}
|
}
|
||||||
@ -124,7 +126,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
let batched_requests = WebSocketRequest::ModelingCmdBatchReq {
|
let batched_requests = WebSocketRequest::ModelingCmdBatchReq {
|
||||||
requests,
|
requests,
|
||||||
batch_id: uuid::Uuid::new_v4(),
|
batch_id: uuid::Uuid::new_v4(),
|
||||||
responses: false,
|
responses: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
let final_req = if self.batch().lock().unwrap().len() == 1 {
|
let final_req = if self.batch().lock().unwrap().len() == 1 {
|
||||||
@ -155,23 +157,41 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
self.batch().lock().unwrap().clear();
|
self.batch().lock().unwrap().clear();
|
||||||
|
|
||||||
// We pop off the responses to cleanup our mappings.
|
// We pop off the responses to cleanup our mappings.
|
||||||
let id_final = match final_req {
|
match final_req {
|
||||||
WebSocketRequest::ModelingCmdBatchReq {
|
WebSocketRequest::ModelingCmdBatchReq {
|
||||||
requests: _,
|
ref requests,
|
||||||
batch_id,
|
batch_id,
|
||||||
responses: _,
|
responses: _,
|
||||||
} => batch_id,
|
} => {
|
||||||
WebSocketRequest::ModelingCmdReq { cmd: _, cmd_id } => cmd_id,
|
// Get the last command ID.
|
||||||
_ => {
|
let last_id = requests.last().unwrap().cmd_id;
|
||||||
return Err(KclError::Engine(KclErrorDetails {
|
let ws_resp = self
|
||||||
|
.inner_send_modeling_cmd(batch_id, source_range, final_req, id_to_source_range.clone())
|
||||||
|
.await?;
|
||||||
|
let response = self.parse_websocket_response(ws_resp, source_range)?;
|
||||||
|
|
||||||
|
// If we have a batch response, we want to return the specific id we care about.
|
||||||
|
if let kittycad::types::OkWebSocketResponseData::ModelingBatch { responses } = &response {
|
||||||
|
self.parse_batch_responses(last_id, id_to_source_range, responses.clone())
|
||||||
|
} else {
|
||||||
|
// We should never get here.
|
||||||
|
Err(KclError::Engine(KclErrorDetails {
|
||||||
|
message: format!("Failed to get batch response: {:?}", response),
|
||||||
|
source_ranges: vec![source_range],
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WebSocketRequest::ModelingCmdReq { cmd: _, cmd_id } => {
|
||||||
|
let ws_resp = self
|
||||||
|
.inner_send_modeling_cmd(cmd_id, source_range, final_req, id_to_source_range)
|
||||||
|
.await?;
|
||||||
|
self.parse_websocket_response(ws_resp, source_range)
|
||||||
|
}
|
||||||
|
_ => Err(KclError::Engine(KclErrorDetails {
|
||||||
message: format!("The final request is not a modeling command: {:?}", final_req),
|
message: format!("The final request is not a modeling command: {:?}", final_req),
|
||||||
source_ranges: vec![source_range],
|
source_ranges: vec![source_range],
|
||||||
}));
|
})),
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
self.inner_send_modeling_cmd(id_final, source_range, final_req, id_to_source_range)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn make_default_plane(
|
async fn make_default_plane(
|
||||||
@ -186,10 +206,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
let default_origin = Point3d { x: 0.0, y: 0.0, z: 0.0 }.into();
|
let default_origin = Point3d { x: 0.0, y: 0.0, z: 0.0 }.into();
|
||||||
|
|
||||||
let plane_id = uuid::Uuid::new_v4();
|
let plane_id = uuid::Uuid::new_v4();
|
||||||
self.send_modeling_cmd(
|
self.batch_modeling_cmd(
|
||||||
plane_id,
|
plane_id,
|
||||||
source_range,
|
source_range,
|
||||||
ModelingCmd::MakePlane {
|
&ModelingCmd::MakePlane {
|
||||||
clobber: false,
|
clobber: false,
|
||||||
origin: default_origin,
|
origin: default_origin,
|
||||||
size: default_size,
|
size: default_size,
|
||||||
@ -202,10 +222,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
|
|
||||||
if let Some(color) = color {
|
if let Some(color) = color {
|
||||||
// Set the color.
|
// Set the color.
|
||||||
self.send_modeling_cmd(
|
self.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
source_range,
|
source_range,
|
||||||
ModelingCmd::PlaneSetColor { color, plane_id },
|
&ModelingCmd::PlaneSetColor { color, plane_id },
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
@ -312,62 +332,79 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
neg_yz: planes[&PlaneName::NegYz],
|
neg_yz: planes[&PlaneName::NegYz],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_websocket_response(
|
||||||
|
&self,
|
||||||
|
response: kittycad::types::WebSocketResponse,
|
||||||
|
source_range: crate::executor::SourceRange,
|
||||||
|
) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> {
|
||||||
|
if let Some(data) = &response.resp {
|
||||||
|
Ok(data.clone())
|
||||||
|
} else if let Some(errors) = &response.errors {
|
||||||
|
Err(KclError::Engine(KclErrorDetails {
|
||||||
|
message: format!("Modeling command failed: {:?}", errors),
|
||||||
|
source_ranges: vec![source_range],
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
// We should never get here.
|
||||||
|
Err(KclError::Engine(KclErrorDetails {
|
||||||
|
message: "Modeling command failed: no response or errors".to_string(),
|
||||||
|
source_ranges: vec![source_range],
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_cmd_with_return_values(cmd: &kittycad::types::ModelingCmd) -> bool {
|
fn parse_batch_responses(
|
||||||
let (kittycad::types::ModelingCmd::Export { .. }
|
&self,
|
||||||
| kittycad::types::ModelingCmd::Extrude { .. }
|
// The last response we are looking for.
|
||||||
| kittycad::types::ModelingCmd::DefaultCameraLookAt { .. }
|
id: uuid::Uuid,
|
||||||
| kittycad::types::ModelingCmd::DefaultCameraFocusOn { .. }
|
// The mapping of source ranges to command IDs.
|
||||||
| kittycad::types::ModelingCmd::DefaultCameraGetSettings { .. }
|
id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>,
|
||||||
| kittycad::types::ModelingCmd::DefaultCameraPerspectiveSettings { .. }
|
// The response from the engine.
|
||||||
| kittycad::types::ModelingCmd::DefaultCameraZoom { .. }
|
responses: HashMap<String, kittycad::types::BatchResponse>,
|
||||||
| kittycad::types::ModelingCmd::SketchModeDisable { .. }
|
) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> {
|
||||||
| kittycad::types::ModelingCmd::ObjectBringToFront { .. }
|
// Iterate over the responses and check for errors.
|
||||||
| kittycad::types::ModelingCmd::SelectWithPoint { .. }
|
for (cmd_id, resp) in responses.iter() {
|
||||||
| kittycad::types::ModelingCmd::HighlightSetEntity { .. }
|
let cmd_id = uuid::Uuid::parse_str(cmd_id).map_err(|e| {
|
||||||
| kittycad::types::ModelingCmd::EntityGetChildUuid { .. }
|
KclError::Engine(KclErrorDetails {
|
||||||
| kittycad::types::ModelingCmd::EntityGetNumChildren { .. }
|
message: format!("Failed to parse command ID: {:?}", e),
|
||||||
| kittycad::types::ModelingCmd::EntityGetParentId { .. }
|
source_ranges: vec![id_to_source_range[&id]],
|
||||||
| kittycad::types::ModelingCmd::EntityGetAllChildUuids { .. }
|
})
|
||||||
| kittycad::types::ModelingCmd::CameraDragMove { .. }
|
})?;
|
||||||
| kittycad::types::ModelingCmd::CameraDragEnd { .. }
|
|
||||||
| kittycad::types::ModelingCmd::SelectGet { .. }
|
|
||||||
| kittycad::types::ModelingCmd::Solid3DGetAllEdgeFaces { .. }
|
|
||||||
| kittycad::types::ModelingCmd::Solid3DGetAllOppositeEdges { .. }
|
|
||||||
| kittycad::types::ModelingCmd::Solid3DGetOppositeEdge { .. }
|
|
||||||
| kittycad::types::ModelingCmd::Solid3DGetNextAdjacentEdge { .. }
|
|
||||||
| kittycad::types::ModelingCmd::Solid3DGetPrevAdjacentEdge { .. }
|
|
||||||
| kittycad::types::ModelingCmd::GetEntityType { .. }
|
|
||||||
| kittycad::types::ModelingCmd::CurveGetControlPoints { .. }
|
|
||||||
| kittycad::types::ModelingCmd::CurveGetType { .. }
|
|
||||||
| kittycad::types::ModelingCmd::MouseClick { .. }
|
|
||||||
| kittycad::types::ModelingCmd::TakeSnapshot { .. }
|
|
||||||
| kittycad::types::ModelingCmd::PathGetInfo { .. }
|
|
||||||
| kittycad::types::ModelingCmd::PathGetCurveUuidsForVertices { .. }
|
|
||||||
| kittycad::types::ModelingCmd::PathGetVertexUuids { .. }
|
|
||||||
| kittycad::types::ModelingCmd::CurveGetEndPoints { .. }
|
|
||||||
| kittycad::types::ModelingCmd::FaceIsPlanar { .. }
|
|
||||||
| kittycad::types::ModelingCmd::FaceGetPosition { .. }
|
|
||||||
| kittycad::types::ModelingCmd::FaceGetGradient { .. }
|
|
||||||
| kittycad::types::ModelingCmd::PlaneIntersectAndProject { .. }
|
|
||||||
| kittycad::types::ModelingCmd::ImportFiles { .. }
|
|
||||||
| kittycad::types::ModelingCmd::Mass { .. }
|
|
||||||
| kittycad::types::ModelingCmd::Volume { .. }
|
|
||||||
| kittycad::types::ModelingCmd::Density { .. }
|
|
||||||
| kittycad::types::ModelingCmd::SurfaceArea { .. }
|
|
||||||
| kittycad::types::ModelingCmd::CenterOfMass { .. }
|
|
||||||
| kittycad::types::ModelingCmd::GetSketchModePlane { .. }
|
|
||||||
| kittycad::types::ModelingCmd::EntityGetDistance { .. }
|
|
||||||
| kittycad::types::ModelingCmd::EntityLinearPattern { .. }
|
|
||||||
| kittycad::types::ModelingCmd::EntityCircularPattern { .. }
|
|
||||||
| kittycad::types::ModelingCmd::ZoomToFit { .. }
|
|
||||||
| kittycad::types::ModelingCmd::Solid3DGetExtrusionFaceInfo { .. }) = cmd
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
true
|
if let Some(errors) = resp.errors.as_ref() {
|
||||||
|
// Get the source range for the command.
|
||||||
|
let source_range = id_to_source_range.get(&cmd_id).cloned().ok_or_else(|| {
|
||||||
|
KclError::Engine(KclErrorDetails {
|
||||||
|
message: format!("Failed to get source range for command ID: {:?}", cmd_id),
|
||||||
|
source_ranges: vec![],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
return Err(KclError::Engine(KclErrorDetails {
|
||||||
|
message: format!("Modeling command failed: {:?}", errors),
|
||||||
|
source_ranges: vec![source_range],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if let Some(response) = resp.response.as_ref() {
|
||||||
|
if cmd_id == id {
|
||||||
|
// This is the response we care about.
|
||||||
|
return Ok(kittycad::types::OkWebSocketResponseData::Modeling {
|
||||||
|
modeling_response: response.clone(),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Continue the loop if this is not the response we care about.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an error that we did not get an error or the response we wanted.
|
||||||
|
// This should never happen but who knows.
|
||||||
|
Err(KclError::Engine(KclErrorDetails {
|
||||||
|
message: format!("Failed to find response for command ID: {:?}", id),
|
||||||
|
source_ranges: vec![],
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Hash, Eq, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Hash, Eq, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
@ -1066,10 +1066,10 @@ impl ExecutorContext {
|
|||||||
|
|
||||||
// Set the edge visibility.
|
// Set the edge visibility.
|
||||||
engine
|
engine
|
||||||
.send_modeling_cmd(
|
.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
SourceRange::default(),
|
SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::EdgeLinesVisible {
|
&kittycad::types::ModelingCmd::EdgeLinesVisible {
|
||||||
hidden: !settings.highlight_edges,
|
hidden: !settings.highlight_edges,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -1145,10 +1145,10 @@ impl ExecutorContext {
|
|||||||
) -> Result<ProgramMemory, KclError> {
|
) -> Result<ProgramMemory, KclError> {
|
||||||
// Before we even start executing the program, set the units.
|
// Before we even start executing the program, set the units.
|
||||||
self.engine
|
self.engine
|
||||||
.send_modeling_cmd(
|
.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
SourceRange::default(),
|
SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::SetSceneUnits {
|
&kittycad::types::ModelingCmd::SetSceneUnits {
|
||||||
unit: self.settings.units.clone().into(),
|
unit: self.settings.units.clone().into(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
use super::Node;
|
use anyhow::Result;
|
||||||
use crate::ast::types::{
|
|
||||||
|
use crate::{
|
||||||
|
ast::types::{
|
||||||
BinaryPart, BodyItem, LiteralIdentifier, MemberExpression, MemberObject, ObjectExpression, ObjectProperty,
|
BinaryPart, BodyItem, LiteralIdentifier, MemberExpression, MemberObject, ObjectExpression, ObjectProperty,
|
||||||
Parameter, Program, UnaryExpression, Value, VariableDeclarator,
|
Parameter, Program, UnaryExpression, Value, VariableDeclarator,
|
||||||
|
},
|
||||||
|
lint::Node,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
/// Walker is implemented by things that are able to walk an AST tree to
|
/// Walker is implemented by things that are able to walk an AST tree to
|
||||||
/// produce lints. This trait is implemented automatically for a few of the
|
/// produce lints. This trait is implemented automatically for a few of the
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::types::VariableDeclarator,
|
ast::types::VariableDeclarator,
|
||||||
executor::SourceRange,
|
executor::SourceRange,
|
||||||
@ -7,8 +9,6 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
def_finding!(
|
def_finding!(
|
||||||
Z0001,
|
Z0001,
|
||||||
"Identifiers must be lowerCamelCase",
|
"Identifiers must be lowerCamelCase",
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
use super::{walk, Node};
|
|
||||||
use crate::{ast::types::Program, executor::SourceRange, lsp::IntoDiagnostic};
|
|
||||||
use anyhow::Result;
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
|
use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
ast::types::Program,
|
||||||
|
executor::SourceRange,
|
||||||
|
lint::{walk, Node},
|
||||||
|
lsp::IntoDiagnostic,
|
||||||
|
};
|
||||||
|
|
||||||
/// Check the provided AST for any found rule violations.
|
/// Check the provided AST for any found rule violations.
|
||||||
///
|
///
|
||||||
/// The Rule trait is automatically implemented for a few other types,
|
/// The Rule trait is automatically implemented for a few other types,
|
||||||
@ -105,7 +111,6 @@ macro_rules! finding {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub(crate) use finding;
|
pub(crate) use finding;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) use test::{assert_finding, assert_no_finding, test_finding, test_no_finding};
|
pub(crate) use test::{assert_finding, assert_no_finding, test_finding, test_no_finding};
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ async fn inner_chamfer(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
ModelingCmd::Solid3DFilletEdge {
|
ModelingCmd::Solid3DFilletEdge {
|
||||||
edge_id,
|
edge_id,
|
||||||
|
@ -111,13 +111,13 @@ pub(crate) async fn do_post_extrude(
|
|||||||
// We need to do this after extrude for sketch on face.
|
// We need to do this after extrude for sketch on face.
|
||||||
if let SketchSurface::Face(_) = sketch_group.on {
|
if let SketchSurface::Face(_) = sketch_group.on {
|
||||||
// Disable the sketch mode.
|
// Disable the sketch mode.
|
||||||
args.send_modeling_cmd(uuid::Uuid::new_v4(), kittycad::types::ModelingCmd::SketchModeDisable {})
|
args.batch_modeling_cmd(uuid::Uuid::new_v4(), kittycad::types::ModelingCmd::SketchModeDisable {})
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bring the object to the front of the scene.
|
// Bring the object to the front of the scene.
|
||||||
// See: https://github.com/KittyCAD/modeling-app/issues/806
|
// See: https://github.com/KittyCAD/modeling-app/issues/806
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
kittycad::types::ModelingCmd::ObjectBringToFront {
|
kittycad::types::ModelingCmd::ObjectBringToFront {
|
||||||
object_id: sketch_group.id,
|
object_id: sketch_group.id,
|
||||||
|
@ -110,7 +110,7 @@ async fn inner_fillet(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
ModelingCmd::Solid3DFilletEdge {
|
ModelingCmd::Solid3DFilletEdge {
|
||||||
edge_id,
|
edge_id,
|
||||||
|
@ -59,7 +59,7 @@ async fn inner_helix(
|
|||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Box<ExtrudeGroup>, KclError> {
|
) -> Result<Box<ExtrudeGroup>, KclError> {
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::EntityMakeHelix {
|
ModelingCmd::EntityMakeHelix {
|
||||||
cylinder_id: extrude_group.id,
|
cylinder_id: extrude_group.id,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::types::{BodyItem, FunctionExpression, Program, Value},
|
ast::types::{BodyItem, FunctionExpression, Program, Value},
|
||||||
|
@ -215,6 +215,16 @@ impl Args {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a modeling command to the batch but don't fire it right away.
|
||||||
|
pub async fn batch_modeling_cmd(
|
||||||
|
&self,
|
||||||
|
id: uuid::Uuid,
|
||||||
|
cmd: kittycad::types::ModelingCmd,
|
||||||
|
) -> Result<(), crate::errors::KclError> {
|
||||||
|
self.ctx.engine.batch_modeling_cmd(id, self.source_range, &cmd).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Send the modeling cmd and wait for the response.
|
||||||
pub async fn send_modeling_cmd(
|
pub async fn send_modeling_cmd(
|
||||||
&self,
|
&self,
|
||||||
id: uuid::Uuid,
|
id: uuid::Uuid,
|
||||||
|
@ -242,7 +242,7 @@ async fn inner_revolve(
|
|||||||
match data.axis {
|
match data.axis {
|
||||||
RevolveAxis::Axis(axis) => {
|
RevolveAxis::Axis(axis) => {
|
||||||
let (axis, origin) = axis.axis_and_origin()?;
|
let (axis, origin) = axis.axis_and_origin()?;
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::Revolve {
|
ModelingCmd::Revolve {
|
||||||
angle,
|
angle,
|
||||||
@ -274,7 +274,7 @@ async fn inner_revolve(
|
|||||||
.id
|
.id
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::RevolveAboutEdge {
|
ModelingCmd::RevolveAboutEdge {
|
||||||
angle,
|
angle,
|
||||||
|
@ -4,11 +4,10 @@ use anyhow::Result;
|
|||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
|
|
||||||
use super::utils::between;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{MemoryItem, SketchGroup},
|
executor::{MemoryItem, SketchGroup},
|
||||||
std::Args,
|
std::{utils::between, Args},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Returns the segment end of x.
|
/// Returns the segment end of x.
|
||||||
|
@ -48,7 +48,6 @@ pub async fn circle(args: Args) -> Result<MemoryItem, 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",
|
||||||
}]
|
}]
|
||||||
|
@ -126,7 +126,7 @@ async fn inner_shell(
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
ModelingCmd::Solid3DShellFace {
|
ModelingCmd::Solid3DShellFace {
|
||||||
face_ids,
|
face_ids,
|
||||||
|
@ -55,7 +55,7 @@ async fn inner_line_to(
|
|||||||
let from = sketch_group.current_pen_position()?;
|
let from = sketch_group.current_pen_position()?;
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
|
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::ExtendPath {
|
ModelingCmd::ExtendPath {
|
||||||
path: sketch_group.id,
|
path: sketch_group.id,
|
||||||
@ -217,7 +217,7 @@ async fn inner_line(
|
|||||||
|
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
|
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::ExtendPath {
|
ModelingCmd::ExtendPath {
|
||||||
path: sketch_group.id,
|
path: sketch_group.id,
|
||||||
@ -409,7 +409,7 @@ async fn inner_angled_line(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::ExtendPath {
|
ModelingCmd::ExtendPath {
|
||||||
path: sketch_group.id,
|
path: sketch_group.id,
|
||||||
@ -1071,7 +1071,7 @@ async fn start_sketch_on_face(
|
|||||||
|
|
||||||
// Enter sketch mode on the face.
|
// Enter sketch mode on the face.
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::EnableSketchMode {
|
ModelingCmd::EnableSketchMode {
|
||||||
animated: false,
|
animated: false,
|
||||||
@ -1117,7 +1117,7 @@ async fn start_sketch_on_plane(data: PlaneData, args: Args) -> Result<Box<Plane>
|
|||||||
} => {
|
} => {
|
||||||
// Create the custom plane on the fly.
|
// Create the custom plane on the fly.
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::MakePlane {
|
ModelingCmd::MakePlane {
|
||||||
clobber: false,
|
clobber: false,
|
||||||
@ -1135,7 +1135,7 @@ async fn start_sketch_on_plane(data: PlaneData, args: Args) -> Result<Box<Plane>
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Enter sketch mode on the plane.
|
// Enter sketch mode on the plane.
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
ModelingCmd::EnableSketchMode {
|
ModelingCmd::EnableSketchMode {
|
||||||
animated: false,
|
animated: false,
|
||||||
@ -1205,8 +1205,8 @@ pub(crate) async fn inner_start_profile_at(
|
|||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
let path_id = uuid::Uuid::new_v4();
|
let path_id = uuid::Uuid::new_v4();
|
||||||
|
|
||||||
args.send_modeling_cmd(path_id, ModelingCmd::StartPath {}).await?;
|
args.batch_modeling_cmd(path_id, ModelingCmd::StartPath {}).await?;
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::MovePathPen {
|
ModelingCmd::MovePathPen {
|
||||||
path: path_id,
|
path: path_id,
|
||||||
@ -1359,7 +1359,7 @@ pub(crate) async fn inner_close(
|
|||||||
|
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
|
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::ClosePath {
|
ModelingCmd::ClosePath {
|
||||||
path_id: sketch_group.id,
|
path_id: sketch_group.id,
|
||||||
@ -1370,7 +1370,7 @@ pub(crate) async fn inner_close(
|
|||||||
// If we are sketching on a plane we can close the sketch group now.
|
// If we are sketching on a plane we can close the sketch group now.
|
||||||
if let SketchSurface::Plane(_) = sketch_group.on {
|
if let SketchSurface::Plane(_) = sketch_group.on {
|
||||||
// We were on a plane, disable the sketch mode.
|
// We were on a plane, disable the sketch mode.
|
||||||
args.send_modeling_cmd(uuid::Uuid::new_v4(), kittycad::types::ModelingCmd::SketchModeDisable {})
|
args.batch_modeling_cmd(uuid::Uuid::new_v4(), kittycad::types::ModelingCmd::SketchModeDisable {})
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1436,7 +1436,6 @@ pub async fn arc(args: Args) -> Result<MemoryItem, KclError> {
|
|||||||
/// radius: 16
|
/// radius: 16
|
||||||
/// }, %)
|
/// }, %)
|
||||||
/// |> close(%)
|
/// |> close(%)
|
||||||
///
|
|
||||||
// const example = extrude(10, exampleSketch)
|
// const example = extrude(10, exampleSketch)
|
||||||
/// ```
|
/// ```
|
||||||
#[stdlib {
|
#[stdlib {
|
||||||
@ -1469,7 +1468,7 @@ pub(crate) async fn inner_arc(
|
|||||||
|
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
|
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::ExtendPath {
|
ModelingCmd::ExtendPath {
|
||||||
path: sketch_group.id,
|
path: sketch_group.id,
|
||||||
@ -1565,7 +1564,7 @@ async fn inner_tangential_arc(
|
|||||||
let start_angle = Angle::from_degrees(0.0);
|
let start_angle = Angle::from_degrees(0.0);
|
||||||
let (_, to) = arc_center_and_end(from, start_angle, end_angle, *radius);
|
let (_, to) = arc_center_and_end(from, start_angle, end_angle, *radius);
|
||||||
|
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::ExtendPath {
|
ModelingCmd::ExtendPath {
|
||||||
path: sketch_group.id,
|
path: sketch_group.id,
|
||||||
@ -1582,7 +1581,7 @@ async fn inner_tangential_arc(
|
|||||||
to.into()
|
to.into()
|
||||||
}
|
}
|
||||||
TangentialArcData::Point(to) => {
|
TangentialArcData::Point(to) => {
|
||||||
args.send_modeling_cmd(id, tan_arc_to(&sketch_group, to)).await?;
|
args.batch_modeling_cmd(id, tan_arc_to(&sketch_group, to)).await?;
|
||||||
|
|
||||||
*to
|
*to
|
||||||
}
|
}
|
||||||
@ -1692,7 +1691,7 @@ async fn inner_tangential_arc_to(
|
|||||||
|
|
||||||
let delta = [to_x - from.x, to_y - from.y];
|
let delta = [to_x - from.x, to_y - from.y];
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
args.send_modeling_cmd(id, tan_arc_to(&sketch_group, &delta)).await?;
|
args.batch_modeling_cmd(id, tan_arc_to(&sketch_group, &delta)).await?;
|
||||||
|
|
||||||
let current_path = Path::TangentialArcTo {
|
let current_path = Path::TangentialArcTo {
|
||||||
base: BasePath {
|
base: BasePath {
|
||||||
@ -1769,7 +1768,7 @@ async fn inner_bezier_curve(
|
|||||||
|
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
|
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::ExtendPath {
|
ModelingCmd::ExtendPath {
|
||||||
path: sketch_group.id,
|
path: sketch_group.id,
|
||||||
@ -1864,7 +1863,7 @@ async fn inner_hole(
|
|||||||
|
|
||||||
match hole_sketch_group {
|
match hole_sketch_group {
|
||||||
SketchGroupSet::SketchGroup(hole_sketch_group) => {
|
SketchGroupSet::SketchGroup(hole_sketch_group) => {
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
ModelingCmd::Solid2DAddHole {
|
ModelingCmd::Solid2DAddHole {
|
||||||
object_id: sketch_group.id,
|
object_id: sketch_group.id,
|
||||||
@ -1874,7 +1873,7 @@ async fn inner_hole(
|
|||||||
.await?;
|
.await?;
|
||||||
// suggestion (mike)
|
// suggestion (mike)
|
||||||
// we also hide the source hole since its essentially "consumed" by this operation
|
// we also hide the source hole since its essentially "consumed" by this operation
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
ModelingCmd::ObjectVisible {
|
ModelingCmd::ObjectVisible {
|
||||||
object_id: hole_sketch_group.id,
|
object_id: hole_sketch_group.id,
|
||||||
@ -1885,7 +1884,7 @@ async fn inner_hole(
|
|||||||
}
|
}
|
||||||
SketchGroupSet::SketchGroups(hole_sketch_groups) => {
|
SketchGroupSet::SketchGroups(hole_sketch_groups) => {
|
||||||
for hole_sketch_group in hole_sketch_groups {
|
for hole_sketch_group in hole_sketch_groups {
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
ModelingCmd::Solid2DAddHole {
|
ModelingCmd::Solid2DAddHole {
|
||||||
object_id: sketch_group.id,
|
object_id: sketch_group.id,
|
||||||
@ -1895,7 +1894,7 @@ async fn inner_hole(
|
|||||||
.await?;
|
.await?;
|
||||||
// suggestion (mike)
|
// suggestion (mike)
|
||||||
// we also hide the source hole since its essentially "consumed" by this operation
|
// we also hide the source hole since its essentially "consumed" by this operation
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
ModelingCmd::ObjectVisible {
|
ModelingCmd::ObjectVisible {
|
||||||
object_id: hole_sketch_group.id,
|
object_id: hole_sketch_group.id,
|
||||||
|
@ -28,12 +28,22 @@ pub async fn execute_wasm(
|
|||||||
let memory: kcl_lib::executor::ProgramMemory = serde_json::from_str(memory_str).map_err(|e| e.to_string())?;
|
let memory: kcl_lib::executor::ProgramMemory = serde_json::from_str(memory_str).map_err(|e| e.to_string())?;
|
||||||
let units = kcl_lib::settings::types::UnitLength::from_str(units).map_err(|e| e.to_string())?;
|
let units = kcl_lib::settings::types::UnitLength::from_str(units).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let engine = kcl_lib::engine::conn_wasm::EngineConnection::new(engine_manager)
|
let engine: std::sync::Arc<Box<dyn kcl_lib::engine::EngineManager>> = if is_mock {
|
||||||
|
Arc::new(Box::new(
|
||||||
|
kcl_lib::engine::conn_mock::EngineConnection::new()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("{:?}", e))?;
|
.map_err(|e| format!("{:?}", e))?,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Arc::new(Box::new(
|
||||||
|
kcl_lib::engine::conn_wasm::EngineConnection::new(engine_manager)
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("{:?}", e))?,
|
||||||
|
))
|
||||||
|
};
|
||||||
let fs = Arc::new(kcl_lib::fs::FileManager::new(fs_manager));
|
let fs = Arc::new(kcl_lib::fs::FileManager::new(fs_manager));
|
||||||
let ctx = kcl_lib::executor::ExecutorContext {
|
let ctx = kcl_lib::executor::ExecutorContext {
|
||||||
engine: Arc::new(Box::new(engine)),
|
engine,
|
||||||
fs,
|
fs,
|
||||||
stdlib: std::sync::Arc::new(kcl_lib::std::StdLib::new()),
|
stdlib: std::sync::Arc::new(kcl_lib::std::StdLib::new()),
|
||||||
settings: ExecutorSettings {
|
settings: ExecutorSettings {
|
||||||
|
@ -459,7 +459,7 @@ async fn serial_test_execute_engine_error_return() {
|
|||||||
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([222, 235])], message: "Modeling command failed: Some([ApiError { error_code: BadRequest, message: \"The path is not closed. Solid2D construction requires a closed path!\" }])" }"#,
|
r#"engine: KclErrorDetails { source_ranges: [SourceRange([222, 235])], message: "Modeling command failed: [ApiError { error_code: BadRequest, message: \"The path is not closed. Solid2D construction requires a closed path!\" }]" }"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1614,7 +1614,7 @@ const sketch001 = startSketchOn(box, "revolveAxis")
|
|||||||
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([349, 409])], message: "Modeling command failed: Some([ApiError { error_code: InternalEngine, message: \"Solid3D revolve failed: sketch profile must lie entirely on one side of the revolution axis\" }])" }"#
|
r#"engine: KclErrorDetails { source_ranges: [SourceRange([349, 409])], message: "Modeling command failed: [ApiError { error_code: InternalEngine, message: \"Solid3D revolve failed: sketch profile must lie entirely on one side of the revolution axis\" }]" }"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1873,7 +1873,7 @@ const bracket = startSketchOn('XY')
|
|||||||
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([1443, 1443])], message: "Modeling command failed: Some([ApiError { error_code: BadRequest, message: \"Fillet failed\" }])" }"#
|
r#"engine: KclErrorDetails { source_ranges: [SourceRange([1443, 1443])], message: "Modeling command failed: [ApiError { error_code: BadRequest, message: \"Fillet failed\" }]" }"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|