Compare commits
7 Commits
max-unused
...
coredump-e
Author | SHA1 | Date | |
---|---|---|---|
043bfe263f | |||
66064dca58 | |||
cdb12f8e6f | |||
9f43dc5fc8 | |||
36dc589b32 | |||
e7d6bccc60 | |||
a76dcd76fc |
4
src-tauri/Cargo.lock
generated
4
src-tauri/Cargo.lock
generated
@ -6060,7 +6060,7 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ts-rs"
|
name = "ts-rs"
|
||||||
version = "8.1.0"
|
version = "8.1.0"
|
||||||
source = "git+https://github.com/Aleph-Alpha/ts-rs#f898578d80d3e2a54080c1c046c45f9eaa2435c3"
|
source = "git+https://github.com/Aleph-Alpha/ts-rs#badbac08e61e65b312880aa64e9ece2976f1bbef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@ -6072,7 +6072,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ts-rs-macros"
|
name = "ts-rs-macros"
|
||||||
version = "8.1.0"
|
version = "8.1.0"
|
||||||
source = "git+https://github.com/Aleph-Alpha/ts-rs#f898578d80d3e2a54080c1c046c45f9eaa2435c3"
|
source = "git+https://github.com/Aleph-Alpha/ts-rs#badbac08e61e65b312880aa64e9ece2976f1bbef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -56,33 +56,6 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"shell:allow-open",
|
"shell:allow-open",
|
||||||
{
|
|
||||||
"identifier": "shell:allow-execute",
|
|
||||||
"allow": [
|
|
||||||
{
|
|
||||||
"name": "open",
|
|
||||||
"cmd": "open",
|
|
||||||
"args": [
|
|
||||||
"-R",
|
|
||||||
{
|
|
||||||
"validator": "\\S+"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"sidecar": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "explorer",
|
|
||||||
"cmd": "explorer",
|
|
||||||
"args": [
|
|
||||||
"/select",
|
|
||||||
{
|
|
||||||
"validator": "\\S+"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"sidecar": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"dialog:allow-open",
|
"dialog:allow-open",
|
||||||
"dialog:allow-save",
|
"dialog:allow-save",
|
||||||
"dialog:allow-message",
|
"dialog:allow-message",
|
||||||
|
@ -18,6 +18,7 @@ use oauth2::TokenResponse;
|
|||||||
use tauri::{ipc::InvokeError, Manager};
|
use tauri::{ipc::InvokeError, Manager};
|
||||||
use tauri_plugin_cli::CliExt;
|
use tauri_plugin_cli::CliExt;
|
||||||
use tauri_plugin_shell::ShellExt;
|
use tauri_plugin_shell::ShellExt;
|
||||||
|
use tokio::process::Command;
|
||||||
|
|
||||||
const DEFAULT_HOST: &str = "https://api.zoo.dev";
|
const DEFAULT_HOST: &str = "https://api.zoo.dev";
|
||||||
const SETTINGS_FILE_NAME: &str = "settings.toml";
|
const SETTINGS_FILE_NAME: &str = "settings.toml";
|
||||||
@ -331,20 +332,10 @@ async fn get_user(token: &str, hostname: &str) -> Result<kittycad::types::User,
|
|||||||
/// From this GitHub comment: https://github.com/tauri-apps/tauri/issues/4062#issuecomment-1338048169
|
/// From this GitHub comment: https://github.com/tauri-apps/tauri/issues/4062#issuecomment-1338048169
|
||||||
/// But with the Linux support removed since we don't need it for now.
|
/// But with the Linux support removed since we don't need it for now.
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn show_in_folder(app: tauri::AppHandle, path: &str) -> Result<(), InvokeError> {
|
fn show_in_folder(path: &str) -> Result<(), InvokeError> {
|
||||||
// Check if the file exists.
|
|
||||||
// If it doesn't, return an error.
|
|
||||||
if !Path::new(path).exists() {
|
|
||||||
return Err(InvokeError::from_anyhow(anyhow::anyhow!(
|
|
||||||
"The file `{}` does not exist",
|
|
||||||
path
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
{
|
{
|
||||||
app.shell()
|
Command::new("explorer")
|
||||||
.command("explorer")
|
|
||||||
.args(["/select,", path]) // The comma after select is not a typo
|
.args(["/select,", path]) // The comma after select is not a typo
|
||||||
.spawn()
|
.spawn()
|
||||||
.map_err(|e| InvokeError::from_anyhow(e.into()))?;
|
.map_err(|e| InvokeError::from_anyhow(e.into()))?;
|
||||||
@ -352,8 +343,7 @@ fn show_in_folder(app: tauri::AppHandle, path: &str) -> Result<(), InvokeError>
|
|||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
app.shell()
|
Command::new("open")
|
||||||
.command("open")
|
|
||||||
.args(["-R", path])
|
.args(["-R", path])
|
||||||
.spawn()
|
.spawn()
|
||||||
.map_err(|e| InvokeError::from_anyhow(e.into()))?;
|
.map_err(|e| InvokeError::from_anyhow(e.into()))?;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { parse, recast, initPromise } from './wasm'
|
import { parse, recast, initPromise } from './wasm'
|
||||||
import {
|
import {
|
||||||
findAllPreviousVariables,
|
findAllPreviousVariables,
|
||||||
findUnusedVariables,
|
|
||||||
isNodeSafeToReplace,
|
isNodeSafeToReplace,
|
||||||
isTypeInValue,
|
isTypeInValue,
|
||||||
getNodePathFromSourceRange,
|
getNodePathFromSourceRange,
|
||||||
@ -61,91 +60,6 @@ const variableBelowShouldNotBeIncluded = 3
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Test findUnusedVariables', () => {
|
|
||||||
it('should find unused variable in common kcl code', () => {
|
|
||||||
// example code
|
|
||||||
const code = `
|
|
||||||
const xRel001 = -20
|
|
||||||
const xRel002 = -50
|
|
||||||
const part001 = startSketchOn('-XZ')
|
|
||||||
|> startProfileAt([175.73, 109.38], %)
|
|
||||||
|> line([xRel001, 178.25], %)
|
|
||||||
|> line([-265.39, -87.86], %)
|
|
||||||
|> tangentialArcTo([543.32, -355.04], %)
|
|
||||||
`
|
|
||||||
// parse into ast
|
|
||||||
const ast = parse(code)
|
|
||||||
// find unused variables
|
|
||||||
const unusedVariables = findUnusedVariables(ast)
|
|
||||||
// check wether unused variables match the expected result
|
|
||||||
expect(
|
|
||||||
unusedVariables
|
|
||||||
.map((node) => node.declarations.map((decl) => decl.id.name))
|
|
||||||
.flat()
|
|
||||||
).toEqual(['xRel002'])
|
|
||||||
})
|
|
||||||
it("should not find used variable, even if it's heavy nested", () => {
|
|
||||||
// example code
|
|
||||||
const code = `
|
|
||||||
const deepWithin = 1
|
|
||||||
const veryNested = [
|
|
||||||
{ key: [{ key2: max(5, deepWithin) }] }
|
|
||||||
]
|
|
||||||
`
|
|
||||||
// parse into ast
|
|
||||||
const ast = parse(code)
|
|
||||||
// find unused variables
|
|
||||||
const unusedVariables = findUnusedVariables(ast)
|
|
||||||
// check wether unused variables match the expected result
|
|
||||||
expect(
|
|
||||||
unusedVariables.find((node) =>
|
|
||||||
node.declarations.find((decl) => decl.id.name === 'deepWithin')
|
|
||||||
)
|
|
||||||
).toBeFalsy()
|
|
||||||
})
|
|
||||||
it('should not find used variable, even if used in a closure', () => {
|
|
||||||
// example code
|
|
||||||
const code = `const usedInClosure = 1
|
|
||||||
fn myFunction = () => {
|
|
||||||
return usedInClosure
|
|
||||||
}
|
|
||||||
`
|
|
||||||
// parse into ast
|
|
||||||
const ast = parse(code)
|
|
||||||
// find unused variables
|
|
||||||
const unusedVariables = findUnusedVariables(ast)
|
|
||||||
// check wether unused variables match the expected result
|
|
||||||
expect(
|
|
||||||
unusedVariables.find((node) =>
|
|
||||||
node.declarations.find((decl) => decl.id.name === 'usedInClosure')
|
|
||||||
)
|
|
||||||
).toBeFalsy()
|
|
||||||
})
|
|
||||||
// TODO: The commented code in the below does not even parse due to a KCL bug
|
|
||||||
// When it does parse correctly we'de expect 'a' to be defined but unused
|
|
||||||
// as it's shadowed by the 'a' in the inner scope
|
|
||||||
// it('should find unused variable when the same identifier is used in deeper scope', () => {
|
|
||||||
// const code = `const a = 1
|
|
||||||
// const b = 2
|
|
||||||
// fn (a) => {
|
|
||||||
// return a + 1
|
|
||||||
// }
|
|
||||||
// const myVar = b + 5`
|
|
||||||
// // parse into ast
|
|
||||||
// const ast = parse(code)
|
|
||||||
// console.log('ast', ast)
|
|
||||||
// // find unused variables
|
|
||||||
// const unusedVariables = findUnusedVariables(ast)
|
|
||||||
// console.log('unusedVariables', unusedVariables)
|
|
||||||
// // check wether unused variables match the expected result
|
|
||||||
// expect(
|
|
||||||
// unusedVariables
|
|
||||||
// .map((node) => node.declarations.map((decl) => decl.id.name))
|
|
||||||
// .flat()
|
|
||||||
// ).toEqual(['a'])
|
|
||||||
// })
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('testing argIsNotIdentifier', () => {
|
describe('testing argIsNotIdentifier', () => {
|
||||||
const code = `const part001 = startSketchOn('XY')
|
const code = `const part001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-1.2, 4.83], %)
|
|> startProfileAt([-1.2, 4.83], %)
|
||||||
|
@ -392,68 +392,6 @@ export function findAllPreviousVariables(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findUnusedVariables(ast: Program): Array<VariableDeclaration> {
|
|
||||||
const declaredVariables = new Map<string, VariableDeclarator>() // Map to store declared variables
|
|
||||||
const usedVariables = new Set<string>() // Set to track used variables
|
|
||||||
|
|
||||||
// 1. Traverse and populate
|
|
||||||
ast.body.forEach((node) => {
|
|
||||||
traverse(node, {
|
|
||||||
enter(node) {
|
|
||||||
if (node.type === 'VariableDeclarator') {
|
|
||||||
// if node is a VariableDeclarator,
|
|
||||||
// add it to declaredVariables
|
|
||||||
declaredVariables.set(node.id.name, node)
|
|
||||||
} else if (node.type === 'Identifier') {
|
|
||||||
// if the node is Identifier, (use of a variable)
|
|
||||||
// check if it is a declared value,
|
|
||||||
// just in case...
|
|
||||||
// to be sure it's a part of the declared variables
|
|
||||||
if (declaredVariables.has(node.name)) {
|
|
||||||
// if yes - mark it as used
|
|
||||||
usedVariables.add(node.name)
|
|
||||||
}
|
|
||||||
} else if (node.type === 'VariableDeclaration') {
|
|
||||||
// check if the declaration is model-defining (contains PipeExpression)
|
|
||||||
const isModelDefining = node.declarations.some(
|
|
||||||
(decl) => decl.init?.type === 'PipeExpression'
|
|
||||||
)
|
|
||||||
if (isModelDefining) {
|
|
||||||
// If it is, mark all contained variables as used
|
|
||||||
node.declarations.forEach((decl) => {
|
|
||||||
usedVariables.add(decl.id.name)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// 2. Remove used variables from declaredVariables
|
|
||||||
usedVariables.forEach((name) => {
|
|
||||||
declaredVariables.delete(name)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 3. collect unused VariableDeclarations
|
|
||||||
const unusedVariableDeclarations: Array<VariableDeclaration> = []
|
|
||||||
ast.body.forEach((node) => {
|
|
||||||
if (node.type === 'VariableDeclaration') {
|
|
||||||
const unusedDeclarators = node.declarations.filter((declarator) =>
|
|
||||||
declaredVariables.has(declarator.id.name)
|
|
||||||
)
|
|
||||||
if (unusedDeclarators.length > 0) {
|
|
||||||
unusedVariableDeclarations.push({
|
|
||||||
...node,
|
|
||||||
declarations: unusedDeclarators,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 4. Return the unused variables
|
|
||||||
return unusedVariableDeclarations
|
|
||||||
}
|
|
||||||
|
|
||||||
type ReplacerFn = (_ast: Program, varName: string) => { modifiedAst: Program }
|
type ReplacerFn = (_ast: Program, varName: string) => { modifiedAst: Program }
|
||||||
|
|
||||||
export function isNodeSafeToReplace(
|
export function isNodeSafeToReplace(
|
||||||
|
@ -55,6 +55,10 @@ impl CoreDump for CoreDumper {
|
|||||||
Ok(crate::coredump::WebrtcStats::default())
|
Ok(crate::coredump::WebrtcStats::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_client_state(&self) -> Result<crate::coredump::ClientState> {
|
||||||
|
Ok(crate::coredump::ClientState::default())
|
||||||
|
}
|
||||||
|
|
||||||
async fn screenshot(&self) -> Result<String> {
|
async fn screenshot(&self) -> Result<String> {
|
||||||
// Take a screenshot of the engine.
|
// Take a screenshot of the engine.
|
||||||
todo!()
|
todo!()
|
||||||
|
@ -27,6 +27,8 @@ pub trait CoreDump: Clone {
|
|||||||
|
|
||||||
async fn get_webrtc_stats(&self) -> Result<WebrtcStats>;
|
async fn get_webrtc_stats(&self) -> Result<WebrtcStats>;
|
||||||
|
|
||||||
|
async fn get_client_state(&self) -> Result<ClientState>;
|
||||||
|
|
||||||
/// Return a screenshot of the app.
|
/// Return a screenshot of the app.
|
||||||
async fn screenshot(&self) -> Result<String>;
|
async fn screenshot(&self) -> Result<String>;
|
||||||
|
|
||||||
@ -64,6 +66,7 @@ pub trait CoreDump: Clone {
|
|||||||
let webrtc_stats = self.get_webrtc_stats().await?;
|
let webrtc_stats = self.get_webrtc_stats().await?;
|
||||||
let os = self.os().await?;
|
let os = self.os().await?;
|
||||||
let screenshot_url = self.upload_screenshot().await?;
|
let screenshot_url = self.upload_screenshot().await?;
|
||||||
|
let client_state = self.get_client_state().await?;
|
||||||
|
|
||||||
let mut app_info = AppInfo {
|
let mut app_info = AppInfo {
|
||||||
version: self.version()?,
|
version: self.version()?,
|
||||||
@ -74,6 +77,7 @@ pub trait CoreDump: Clone {
|
|||||||
webrtc_stats,
|
webrtc_stats,
|
||||||
github_issue_url: None,
|
github_issue_url: None,
|
||||||
pool: self.pool()?,
|
pool: self.pool()?,
|
||||||
|
client_state,
|
||||||
};
|
};
|
||||||
app_info.set_github_issue_url(&screenshot_url)?;
|
app_info.set_github_issue_url(&screenshot_url)?;
|
||||||
|
|
||||||
@ -109,6 +113,9 @@ pub struct AppInfo {
|
|||||||
|
|
||||||
/// Engine pool the client is connected to.
|
/// Engine pool the client is connected to.
|
||||||
pub pool: String,
|
pub pool: String,
|
||||||
|
|
||||||
|
/// The client state (singletons and xstate)
|
||||||
|
pub client_state: ClientState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppInfo {
|
impl AppInfo {
|
||||||
@ -197,3 +204,23 @@ pub struct WebrtcStats {
|
|||||||
/// Packet jitter for this synchronizing source, measured in seconds.
|
/// Packet jitter for this synchronizing source, measured in seconds.
|
||||||
pub jitter: f32,
|
pub jitter: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Client State Structure
|
||||||
|
#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub struct ClientState {
|
||||||
|
pub engine_command_manager: EngineCommandManager,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub struct EngineCommandManager {
|
||||||
|
pub engine_connection: EngineConnection,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
pub struct EngineConnection {
|
||||||
|
}
|
@ -33,6 +33,9 @@ extern "C" {
|
|||||||
|
|
||||||
#[wasm_bindgen(method, js_name = screenshot, catch)]
|
#[wasm_bindgen(method, js_name = screenshot, catch)]
|
||||||
fn screenshot(this: &CoreDumpManager) -> Result<js_sys::Promise, js_sys::Error>;
|
fn screenshot(this: &CoreDumpManager) -> Result<js_sys::Promise, js_sys::Error>;
|
||||||
|
|
||||||
|
#[wasm_bindgen(method, js_name = getWebrtcStats, catch)]
|
||||||
|
fn get_client_state(this: &CoreDumpManager) -> Result<js_sys::Promise, js_sys::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -140,4 +143,25 @@ impl CoreDump for CoreDumper {
|
|||||||
|
|
||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_client_state(&self) -> Result<crate::coredump::ClientState> {
|
||||||
|
let promise = self
|
||||||
|
.manager
|
||||||
|
.get_client_state()
|
||||||
|
.map_err(|e| anyhow::anyhow!("Failed to get promise from get client state: {:?}", e))?;
|
||||||
|
|
||||||
|
let value = JsFuture::from(promise)
|
||||||
|
.await
|
||||||
|
.map_err(|e| anyhow::anyhow!("Failed to get response from client state: {:?}", e))?;
|
||||||
|
|
||||||
|
// Parse the value as a string.
|
||||||
|
let s = value
|
||||||
|
.as_string()
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Failed to get string from response from client stat: `{:?}`", value))?;
|
||||||
|
|
||||||
|
let client_state: crate::coredump::ClientState =
|
||||||
|
serde_json::from_str(&s).map_err(|e| anyhow::anyhow!("Failed to parse client state: {:?}", e))?;
|
||||||
|
|
||||||
|
Ok(client_state)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1121,7 +1121,7 @@ impl ExecutorContext {
|
|||||||
&self,
|
&self,
|
||||||
program: crate::ast::types::Program,
|
program: crate::ast::types::Program,
|
||||||
memory: &mut ProgramMemory,
|
memory: &mut ProgramMemory,
|
||||||
body_type: BodyType,
|
_body_type: BodyType,
|
||||||
) -> Result<ProgramMemory, KclError> {
|
) -> Result<ProgramMemory, KclError> {
|
||||||
let pipe_info = PipeInfo::default();
|
let pipe_info = PipeInfo::default();
|
||||||
|
|
||||||
@ -1328,10 +1328,8 @@ impl ExecutorContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if BodyType::Root == body_type {
|
// Flush the batch queue.
|
||||||
// Flush the batch queue.
|
self.engine.flush_batch(SourceRange([program.end, program.end])).await?;
|
||||||
self.engine.flush_batch(SourceRange([program.end, program.end])).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(memory.clone())
|
Ok(memory.clone())
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
fn make_circle = (face, tag, pos, radius) => {
|
||||||
|
const sg0 = startSketchOn(face, tag)
|
||||||
|
const sg1 = startProfileAt([pos[0] + radius, pos[1]], sg0)
|
||||||
|
const sg2 = arc({
|
||||||
|
angle_end: 360,
|
||||||
|
angle_start: 0,
|
||||||
|
radius: radius
|
||||||
|
}, sg1, 'arc-' + tag)
|
||||||
|
return close(sg2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pentagon = (len) => {
|
||||||
|
const sg3 = startSketchOn('XY')
|
||||||
|
const sg4 = startProfileAt([-len / 2, -len / 2], sg3)
|
||||||
|
const sg5 = angledLine({ angle: 0, length: len }, sg4, 'a')
|
||||||
|
const sg6 = angledLine({
|
||||||
|
angle: segAng('a', sg5) + 180 - 108,
|
||||||
|
length: len
|
||||||
|
},sg5, 'b')
|
||||||
|
const sg7 = angledLine({
|
||||||
|
angle: segAng('b', sg6) + 180 - 108,
|
||||||
|
length: len
|
||||||
|
}, sg6, 'c')
|
||||||
|
const sg8 = angledLine({
|
||||||
|
angle: segAng('c', sg7) + 180 - 108,
|
||||||
|
length: len
|
||||||
|
}, sg7, 'd')
|
||||||
|
return angledLine({
|
||||||
|
angle: segAng('d', sg8) + 180 - 108,
|
||||||
|
length: len
|
||||||
|
}, sg8)
|
||||||
|
}
|
||||||
|
|
||||||
|
const p = pentagon(48)
|
||||||
|
const pe = extrude(30, p)
|
||||||
|
|
||||||
|
const plumbus0 = make_circle(pe, 'a', [0, 0], 9)
|
||||||
|
const plumbus1 = extrude(18, plumbus0)
|
||||||
|
const plumbus2 = fillet({
|
||||||
|
radius: 0.5,
|
||||||
|
tags: ['arc-a', getOppositeEdge('arc-a', plumbus1)]
|
||||||
|
}, plumbus1)
|
@ -1,41 +1,46 @@
|
|||||||
fn triangle = (len) => {
|
fn make_circle = (face, tag, pos, radius) => {
|
||||||
return startSketchOn('XY')
|
const sg = startSketchOn(face, tag)
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([pos[0] + radius, pos[1]], %)
|
||||||
|> angledLine({angle: 60, length: len}, %, 'a')
|
|> arc({
|
||||||
|> angledLine({angle: 180, length: len}, %, 'b')
|
angle_end: 360,
|
||||||
|> angledLine({angle: 300, length: len}, %, 'c')
|
angle_start: 0,
|
||||||
}
|
radius: radius
|
||||||
|
}, %, 'arc-' + tag)
|
||||||
let triangleHeight = 200
|
|
||||||
let plumbusLen = 100
|
|
||||||
let radius = 80
|
|
||||||
let circ = {angle_start: 0, angle_end: 360, radius: radius}
|
|
||||||
|
|
||||||
let triangleLen = 500
|
|
||||||
const p = triangle(triangleLen)
|
|
||||||
|> extrude(triangleHeight, %)
|
|
||||||
|
|
||||||
fn circl = (x, tag) => {
|
|
||||||
return startSketchOn(p, tag)
|
|
||||||
|> startProfileAt([x + radius, triangleHeight/2], %)
|
|
||||||
|> arc(circ, %, 'arc-' + tag)
|
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
|
return sg
|
||||||
}
|
}
|
||||||
|
|
||||||
const plumbus1 =
|
fn pentagon = (len) => {
|
||||||
circl(-200, 'c')
|
const sg = startSketchOn('XY')
|
||||||
|> extrude(plumbusLen, %)
|
|> startProfileAt([-len / 2, -len / 2], %)
|
||||||
|> fillet({
|
|> angledLine({ angle: 0, length: len }, %, 'a')
|
||||||
radius: 5,
|
|> angledLine({
|
||||||
tags: ['arc-c', getOppositeEdge('arc-c', %)]
|
angle: segAng('a', %) + 180 - 108,
|
||||||
|
length: len
|
||||||
|
}, %, 'b')
|
||||||
|
|> angledLine({
|
||||||
|
angle: segAng('b', %) + 180 - 108,
|
||||||
|
length: len
|
||||||
|
}, %, 'c')
|
||||||
|
|> angledLine({
|
||||||
|
angle: segAng('c', %) + 180 - 108,
|
||||||
|
length: len
|
||||||
|
}, %, 'd')
|
||||||
|
|> angledLine({
|
||||||
|
angle: segAng('d', %) + 180 - 108,
|
||||||
|
length: len
|
||||||
}, %)
|
}, %)
|
||||||
|
|
||||||
const plumbus0 =
|
return sg
|
||||||
circl(200, 'a')
|
}
|
||||||
|> extrude(plumbusLen, %)
|
|
||||||
|
const p = pentagon(48)
|
||||||
|
|> extrude(30, %)
|
||||||
|
|
||||||
|
const plumbus0 = make_circle(p, 'a', [0, 0], 9)
|
||||||
|
|> extrude(18, %)
|
||||||
|> fillet({
|
|> fillet({
|
||||||
radius: 5,
|
radius: 0.5,
|
||||||
tags: ['arc-a', getOppositeEdge('arc-a', %)]
|
tags: ['arc-a', getOppositeEdge('arc-a', %)]
|
||||||
}, %)
|
}, %)
|
||||||
|
|
||||||
|
|
||||||
|
@ -128,6 +128,15 @@ async fn serial_test_lego() {
|
|||||||
twenty_twenty::assert_image("tests/executor/outputs/lego.png", &result, 0.999);
|
twenty_twenty::assert_image("tests/executor/outputs/lego.png", &result, 0.999);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn serial_test_pentagon_fillet_desugar() {
|
||||||
|
let code = include_str!("inputs/pentagon_fillet_desugar.kcl");
|
||||||
|
let result = execute_and_snapshot(code, kcl_lib::settings::types::UnitLength::Cm)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
twenty_twenty::assert_image("tests/executor/outputs/pentagon_fillet_desugar.png", &result, 0.999);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn serial_test_pentagon_fillet_sugar() {
|
async fn serial_test_pentagon_fillet_sugar() {
|
||||||
let code = include_str!("inputs/pentagon_fillet_sugar.kcl");
|
let code = include_str!("inputs/pentagon_fillet_sugar.kcl");
|
||||||
@ -1946,12 +1955,12 @@ const plumbus0 = make_circle(p, 'a', [0, 0], 2.5)
|
|||||||
tags: ['arc-a', getOppositeEdge('arc-a', %)]
|
tags: ['arc-a', getOppositeEdge('arc-a', %)]
|
||||||
}, %)
|
}, %)
|
||||||
|
|
||||||
const plumbus1 = make_circle(p, 'b', [0, 0], 2.5)
|
// const plumbus1 = make_circle(p, 'b', [0, 0], 2.5)
|
||||||
|> extrude(10, %)
|
// |> extrude(10, %)
|
||||||
|> fillet({
|
// |> fillet({
|
||||||
radius: 0.5,
|
// radius: 0.5,
|
||||||
tags: ['arc-b', getOppositeEdge('arc-b', %)]
|
// tags: ['arc-b', getOppositeEdge('arc-b', %)]
|
||||||
}, %)
|
// }, %)
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result = execute_and_snapshot(code, kcl_lib::settings::types::UnitLength::Mm)
|
let result = execute_and_snapshot(code, kcl_lib::settings::types::UnitLength::Mm)
|
||||||
|
BIN
src/wasm-lib/tests/executor/outputs/pentagon_fillet_desugar.png
Normal file
BIN
src/wasm-lib/tests/executor/outputs/pentagon_fillet_desugar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
Binary file not shown.
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 100 KiB |
Binary file not shown.
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 127 KiB |
Reference in New Issue
Block a user