format button wasnt working, will add playwright test so we don't regress again (#2340)
* add test Signed-off-by: Jess Frazelle <github@jessfraz.com> * add another test Signed-off-by: Jess Frazelle <github@jessfraz.com> * add another test Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * off by one error Signed-off-by: Jess Frazelle <github@jessfraz.com> * add two tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix typos 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> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix semantic tokens for commants Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix tests Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
@ -264,6 +264,85 @@ test('Can moving camera', async ({ page, context }) => {
|
||||
}, [1, -94, -94])
|
||||
})
|
||||
|
||||
test('if you click the format button it formats your code', async ({
|
||||
page,
|
||||
}) => {
|
||||
const u = getUtils(page)
|
||||
await page.setViewportSize({ width: 1000, height: 500 })
|
||||
await page.goto('/')
|
||||
|
||||
await u.waitForAuthSkipAppStart()
|
||||
|
||||
// check no error to begin with
|
||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
||||
|
||||
await page.click('.cm-content')
|
||||
await page.keyboard.type(`const part001 = startSketchOn('XY')
|
||||
|> startProfileAt([-10, -10], %)
|
||||
|> line([20, 0], %)
|
||||
|> line([0, 20], %)
|
||||
|> line([-20, 0], %)
|
||||
|> close(%)`)
|
||||
await page.click('#code-pane button:first-child')
|
||||
await page.click('button:has-text("Format code")')
|
||||
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const part001 = startSketchOn('XY')
|
||||
|> startProfileAt([-10, -10], %)
|
||||
|> line([20, 0], %)
|
||||
|> line([0, 20], %)
|
||||
|> line([-20, 0], %)
|
||||
|> close(%)`)
|
||||
})
|
||||
|
||||
test('if you use the format keyboard binding it formats your code', async ({
|
||||
page,
|
||||
}) => {
|
||||
test.skip(
|
||||
true,
|
||||
"I can't figure out how to get the keyboard shortcut to work (in playwright)"
|
||||
)
|
||||
|
||||
const u = getUtils(page)
|
||||
await page.setViewportSize({ width: 1000, height: 500 })
|
||||
const lspStartPromise = page.waitForEvent('console', async (message) => {
|
||||
// it would be better to wait for a message that the kcl lsp has started by looking for the message message.text().includes('[lsp] [window/logMessage]')
|
||||
// but that doesn't seem to make it to the console for macos/safari :(
|
||||
if (message.text().includes('start kcl lsp')) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 200))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
await page.goto('/')
|
||||
await u.waitForAuthSkipAppStart()
|
||||
await lspStartPromise
|
||||
|
||||
// check no error to begin with
|
||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
||||
|
||||
await page.click('.cm-content')
|
||||
await page.keyboard.type(`const part001 = startSketchOn('XY')
|
||||
|> startProfileAt([-10, -10], %)
|
||||
|> line([20, 0], %)
|
||||
|> line([0, 20], %)
|
||||
|> line([-20, 0], %)
|
||||
|> close(%)`)
|
||||
|
||||
await page.click('.cm-content')
|
||||
|
||||
// Hit alt+shift+f to format the code
|
||||
await page.keyboard.press('Alt+Shift+KeyF')
|
||||
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const part001 = startSketchOn('XY')
|
||||
|> startProfileAt([-10, -10], %)
|
||||
|> line([20, 0], %)
|
||||
|> line([0, 20], %)
|
||||
|> line([-20, 0], %)
|
||||
|> close(%)`)
|
||||
})
|
||||
|
||||
test('if you write invalid kcl you get inlined errors', async ({ page }) => {
|
||||
const u = getUtils(page)
|
||||
await page.setViewportSize({ width: 1000, height: 500 })
|
||||
@ -529,10 +608,6 @@ test.describe('Can create sketches on all planes and their back sides', () => {
|
||||
})
|
||||
|
||||
test('Auto complete works', async ({ page }) => {
|
||||
test.skip(
|
||||
true,
|
||||
'CORS issue stopping the kcl lsp from working, enable again later'
|
||||
)
|
||||
const u = getUtils(page)
|
||||
// const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||
await page.setViewportSize({ width: 1200, height: 500 })
|
||||
|
@ -79,6 +79,7 @@ export default class CodeManager {
|
||||
if (this._code !== code) {
|
||||
this.code = code
|
||||
this.#updateState(code)
|
||||
this.updateCodeEditor(code)
|
||||
}
|
||||
}
|
||||
|
||||
|
2
src/wasm-lib/Cargo.lock
generated
@ -1895,7 +1895,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.1.54"
|
||||
version = "0.1.55"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx 0.5.1",
|
||||
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-lib"
|
||||
description = "KittyCAD Language implementation and tools"
|
||||
version = "0.1.54"
|
||||
version = "0.1.55"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -3297,6 +3297,144 @@ fn ghi = (x) => {
|
||||
assert_eq!(symbols.len(), 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_recast_bug_extra_parens() {
|
||||
let some_program_string = r#"// Ball Bearing
|
||||
// A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads.
|
||||
|
||||
// Define constants like ball diameter, inside diameter, overhange length, and thickness
|
||||
const sphereDia = 0.5
|
||||
const insideDia = 1
|
||||
const thickness = 0.25
|
||||
const overHangLength = .4
|
||||
|
||||
// Sketch and revolve the inside bearing piece
|
||||
const insideRevolve = startSketchOn('XZ')
|
||||
|> startProfileAt([insideDia / 2, 0], %)
|
||||
|> line([0, thickness + sphereDia / 2], %)
|
||||
|> line([overHangLength, 0], %)
|
||||
|> line([0, -thickness], %)
|
||||
|> line([-overHangLength + thickness, 0], %)
|
||||
|> line([0, -sphereDia], %)
|
||||
|> line([overHangLength - thickness, 0], %)
|
||||
|> line([0, -thickness], %)
|
||||
|> line([-overHangLength, 0], %)
|
||||
|> close(%)
|
||||
|> revolve({ axis: 'y' }, %)
|
||||
|
||||
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
|
||||
const sphere = startSketchOn('XZ')
|
||||
|> startProfileAt([
|
||||
0.05 + insideDia / 2 + thickness,
|
||||
0 - 0.05
|
||||
], %)
|
||||
|> line([sphereDia - 0.1, 0], %)
|
||||
|> arc({
|
||||
angle_start: 0,
|
||||
angle_end: -180,
|
||||
radius: sphereDia / 2 - 0.05
|
||||
}, %)
|
||||
|> close(%)
|
||||
|> revolve({ axis: 'x' }, %)
|
||||
|> patternCircular3d({
|
||||
axis: [0, 0, 1],
|
||||
center: [0, 0, 0],
|
||||
repetitions: 10,
|
||||
arcDegrees: 360,
|
||||
rotateDuplicates: true
|
||||
}, %)
|
||||
|
||||
// Sketch and revolve the outside bearing
|
||||
const outsideRevolve = startSketchOn('XZ')
|
||||
|> startProfileAt([
|
||||
insideDia / 2 + thickness + sphereDia,
|
||||
0
|
||||
], %)
|
||||
|> line([0, sphereDia / 2], %)
|
||||
|> line([-overHangLength + thickness, 0], %)
|
||||
|> line([0, thickness], %)
|
||||
|> line([overHangLength, 0], %)
|
||||
|> line([0, -2 * thickness - sphereDia], %)
|
||||
|> line([-overHangLength, 0], %)
|
||||
|> line([0, thickness], %)
|
||||
|> line([overHangLength - thickness, 0], %)
|
||||
|> close(%)
|
||||
|> revolve({ axis: 'y' }, %)"#;
|
||||
let tokens = crate::token::lexer(some_program_string).unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
|
||||
println!("{:#?}", program);
|
||||
|
||||
let recasted = program.recast(&Default::default(), 0);
|
||||
assert_eq!(
|
||||
recasted,
|
||||
r#"// Ball Bearing
|
||||
// A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads.
|
||||
|
||||
|
||||
// Define constants like ball diameter, inside diameter, overhange length, and thickness
|
||||
const sphereDia = 0.5
|
||||
const insideDia = 1
|
||||
const thickness = 0.25
|
||||
const overHangLength = .4
|
||||
|
||||
// Sketch and revolve the inside bearing piece
|
||||
const insideRevolve = startSketchOn('XZ')
|
||||
|> startProfileAt([insideDia / 2, 0], %)
|
||||
|> line([0, thickness + sphereDia / 2], %)
|
||||
|> line([overHangLength, 0], %)
|
||||
|> line([0, -thickness], %)
|
||||
|> line([-overHangLength + thickness, 0], %)
|
||||
|> line([0, -sphereDia], %)
|
||||
|> line([overHangLength - thickness, 0], %)
|
||||
|> line([0, -thickness], %)
|
||||
|> line([-overHangLength, 0], %)
|
||||
|> close(%)
|
||||
|> revolve({ axis: 'y' }, %)
|
||||
|
||||
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
|
||||
const sphere = startSketchOn('XZ')
|
||||
|> startProfileAt([
|
||||
0.05 + insideDia / 2 + thickness,
|
||||
0 - 0.05
|
||||
], %)
|
||||
|> line([sphereDia - 0.1, 0], %)
|
||||
|> arc({
|
||||
angle_start: 0,
|
||||
angle_end: -180,
|
||||
radius: sphereDia / 2 - 0.05
|
||||
}, %)
|
||||
|> close(%)
|
||||
|> revolve({ axis: 'x' }, %)
|
||||
|> patternCircular3d({
|
||||
axis: [0, 0, 1],
|
||||
center: [0, 0, 0],
|
||||
repetitions: 10,
|
||||
arcDegrees: 360,
|
||||
rotateDuplicates: true
|
||||
}, %)
|
||||
|
||||
// Sketch and revolve the outside bearing
|
||||
const outsideRevolve = startSketchOn('XZ')
|
||||
|> startProfileAt([
|
||||
insideDia / 2 + thickness + sphereDia,
|
||||
0
|
||||
], %)
|
||||
|> line([0, sphereDia / 2], %)
|
||||
|> line([-overHangLength + thickness, 0], %)
|
||||
|> line([0, thickness], %)
|
||||
|> line([overHangLength, 0], %)
|
||||
|> line([0, -2 * thickness - sphereDia], %)
|
||||
|> line([-overHangLength, 0], %)
|
||||
|> line([0, thickness], %)
|
||||
|> line([overHangLength - thickness, 0], %)
|
||||
|> close(%)
|
||||
|> revolve({ axis: 'y' }, %)
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_recast_empty_file() {
|
||||
let some_program_string = r#""#;
|
||||
|
@ -313,6 +313,28 @@ impl Backend {
|
||||
let source_range: SourceRange = token.clone().into();
|
||||
let position = source_range.start_to_lsp_position(¶ms.text);
|
||||
|
||||
// We need to check if we are on the last token of the line.
|
||||
// If we are starting from the end of the last line just add 1 to the line.
|
||||
// Check if we are on the last token of the line.
|
||||
if let Some(line) = params.text.lines().nth(position.line as usize) {
|
||||
if line.len() == position.character as usize {
|
||||
// We are on the last token of the line.
|
||||
// We need to add a new line.
|
||||
let semantic_token = SemanticToken {
|
||||
delta_line: position.line - last_position.line + 1,
|
||||
delta_start: 0,
|
||||
length: token.value.len() as u32,
|
||||
token_type: token_type_index as u32,
|
||||
token_modifiers_bitset: 0,
|
||||
};
|
||||
|
||||
semantic_tokens.push(semantic_token);
|
||||
|
||||
last_position = Position::new(position.line + 1, 0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let semantic_token = SemanticToken {
|
||||
delta_line: position.line - last_position.line,
|
||||
delta_start: if position.line != last_position.line {
|
||||
@ -1011,7 +1033,7 @@ impl LanguageServer for Backend {
|
||||
},
|
||||
0,
|
||||
);
|
||||
let source_range = SourceRange([0, current_code.len() - 1]);
|
||||
let source_range = SourceRange([0, current_code.len()]);
|
||||
let range = source_range.to_lsp_range(current_code);
|
||||
Ok(Some(vec![TextEdit {
|
||||
new_text: recast,
|
||||
|
@ -1014,15 +1014,86 @@ async fn test_kcl_lsp_semantic_tokens() {
|
||||
if let tower_lsp::lsp_types::SemanticTokensResult::Tokens(semantic_tokens) = semantic_tokens {
|
||||
assert_eq!(semantic_tokens.data.len(), 2);
|
||||
assert_eq!(semantic_tokens.data[0].length, 13);
|
||||
assert_eq!(semantic_tokens.data[0].delta_start, 0);
|
||||
assert_eq!(semantic_tokens.data[0].delta_line, 0);
|
||||
assert_eq!(semantic_tokens.data[0].token_type, 8);
|
||||
assert_eq!(semantic_tokens.data[1].length, 4);
|
||||
assert_eq!(semantic_tokens.data[1].delta_start, 14);
|
||||
assert_eq!(semantic_tokens.data[1].delta_line, 0);
|
||||
assert_eq!(semantic_tokens.data[1].token_type, 3);
|
||||
} else {
|
||||
panic!("Expected semantic tokens");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_kcl_lsp_semantic_tokens_multiple_comments() {
|
||||
let server = kcl_lsp_server(false).await.unwrap();
|
||||
|
||||
// Send open file.
|
||||
server
|
||||
.did_open(tower_lsp::lsp_types::DidOpenTextDocumentParams {
|
||||
text_document: tower_lsp::lsp_types::TextDocumentItem {
|
||||
uri: "file:///test.kcl".try_into().unwrap(),
|
||||
language_id: "kcl".to_string(),
|
||||
version: 1,
|
||||
text: r#"// Ball Bearing
|
||||
// A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads.
|
||||
|
||||
// Define constants like ball diameter, inside diameter, overhange length, and thickness
|
||||
const sphereDia = 0.5"#.to_string(),
|
||||
},
|
||||
})
|
||||
.await;
|
||||
server.wait_on_handle().await;
|
||||
|
||||
// Send semantic tokens request.
|
||||
let semantic_tokens = server
|
||||
.semantic_tokens_full(tower_lsp::lsp_types::SemanticTokensParams {
|
||||
text_document: tower_lsp::lsp_types::TextDocumentIdentifier {
|
||||
uri: "file:///test.kcl".try_into().unwrap(),
|
||||
},
|
||||
partial_result_params: Default::default(),
|
||||
work_done_progress_params: Default::default(),
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
// Check the semantic tokens.
|
||||
if let tower_lsp::lsp_types::SemanticTokensResult::Tokens(semantic_tokens) = semantic_tokens {
|
||||
assert_eq!(semantic_tokens.data.len(), 7);
|
||||
assert_eq!(semantic_tokens.data[0].length, 15);
|
||||
assert_eq!(semantic_tokens.data[0].delta_start, 0);
|
||||
assert_eq!(semantic_tokens.data[0].delta_line, 0);
|
||||
assert_eq!(semantic_tokens.data[0].token_type, 6);
|
||||
assert_eq!(semantic_tokens.data[1].length, 232);
|
||||
assert_eq!(semantic_tokens.data[1].delta_start, 0);
|
||||
assert_eq!(semantic_tokens.data[1].delta_line, 1);
|
||||
assert_eq!(semantic_tokens.data[1].token_type, 6);
|
||||
assert_eq!(semantic_tokens.data[2].length, 88);
|
||||
assert_eq!(semantic_tokens.data[2].delta_start, 0);
|
||||
assert_eq!(semantic_tokens.data[2].delta_line, 2);
|
||||
assert_eq!(semantic_tokens.data[2].token_type, 6);
|
||||
assert_eq!(semantic_tokens.data[3].length, 5);
|
||||
assert_eq!(semantic_tokens.data[3].delta_start, 0);
|
||||
assert_eq!(semantic_tokens.data[3].delta_line, 1);
|
||||
assert_eq!(semantic_tokens.data[3].token_type, 4);
|
||||
assert_eq!(semantic_tokens.data[4].length, 9);
|
||||
assert_eq!(semantic_tokens.data[4].delta_start, 6);
|
||||
assert_eq!(semantic_tokens.data[4].delta_line, 0);
|
||||
assert_eq!(semantic_tokens.data[4].token_type, 1);
|
||||
assert_eq!(semantic_tokens.data[5].length, 1);
|
||||
assert_eq!(semantic_tokens.data[5].delta_start, 10);
|
||||
assert_eq!(semantic_tokens.data[5].token_type, 2);
|
||||
assert_eq!(semantic_tokens.data[6].length, 3);
|
||||
assert_eq!(semantic_tokens.data[6].delta_start, 2);
|
||||
assert_eq!(semantic_tokens.data[6].token_type, 0);
|
||||
} else {
|
||||
panic!("Expected semantic tokens");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_kcl_lsp_document_symbol() {
|
||||
let server = kcl_lsp_server(false).await.unwrap();
|
||||
@ -1112,6 +1183,183 @@ async fn test_kcl_lsp_formatting() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_kcl_lsp_formatting_extra_parens() {
|
||||
let server = kcl_lsp_server(false).await.unwrap();
|
||||
|
||||
// Send open file.
|
||||
server
|
||||
.did_open(tower_lsp::lsp_types::DidOpenTextDocumentParams {
|
||||
text_document: tower_lsp::lsp_types::TextDocumentItem {
|
||||
uri: "file:///test.kcl".try_into().unwrap(),
|
||||
language_id: "kcl".to_string(),
|
||||
version: 1,
|
||||
text: r#"// Ball Bearing
|
||||
// A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads.
|
||||
|
||||
// Define constants like ball diameter, inside diameter, overhange length, and thickness
|
||||
const sphereDia = 0.5
|
||||
const insideDia = 1
|
||||
const thickness = 0.25
|
||||
const overHangLength = .4
|
||||
|
||||
// Sketch and revolve the inside bearing piece
|
||||
const insideRevolve = startSketchOn('XZ')
|
||||
|> startProfileAt([insideDia / 2, 0], %)
|
||||
|> line([0, thickness + sphereDia / 2], %)
|
||||
|> line([overHangLength, 0], %)
|
||||
|> line([0, -thickness], %)
|
||||
|> line([-overHangLength + thickness, 0], %)
|
||||
|> line([0, -sphereDia], %)
|
||||
|> line([overHangLength - thickness, 0], %)
|
||||
|> line([0, -thickness], %)
|
||||
|> line([-overHangLength, 0], %)
|
||||
|> close(%)
|
||||
|> revolve({ axis: 'y' }, %)
|
||||
|
||||
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
|
||||
const sphere = startSketchOn('XZ')
|
||||
|> startProfileAt([
|
||||
0.05 + insideDia / 2 + thickness,
|
||||
0 - 0.05
|
||||
], %)
|
||||
|> line([sphereDia - 0.1, 0], %)
|
||||
|> arc({
|
||||
angle_start: 0,
|
||||
angle_end: -180,
|
||||
radius: sphereDia / 2 - 0.05
|
||||
}, %)
|
||||
|> close(%)
|
||||
|> revolve({ axis: 'x' }, %)
|
||||
|> patternCircular3d({
|
||||
axis: [0, 0, 1],
|
||||
center: [0, 0, 0],
|
||||
repetitions: 10,
|
||||
arcDegrees: 360,
|
||||
rotateDuplicates: true
|
||||
}, %)
|
||||
|
||||
// Sketch and revolve the outside bearing
|
||||
const outsideRevolve = startSketchOn('XZ')
|
||||
|> startProfileAt([
|
||||
insideDia / 2 + thickness + sphereDia,
|
||||
0
|
||||
], %)
|
||||
|> line([0, sphereDia / 2], %)
|
||||
|> line([-overHangLength + thickness, 0], %)
|
||||
|> line([0, thickness], %)
|
||||
|> line([overHangLength, 0], %)
|
||||
|> line([0, -2 * thickness - sphereDia], %)
|
||||
|> line([-overHangLength, 0], %)
|
||||
|> line([0, thickness], %)
|
||||
|> line([overHangLength - thickness, 0], %)
|
||||
|> close(%)
|
||||
|> revolve({ axis: 'y' }, %)"#
|
||||
.to_string(),
|
||||
},
|
||||
})
|
||||
.await;
|
||||
server.wait_on_handle().await;
|
||||
|
||||
// Send formatting request.
|
||||
let formatting = server
|
||||
.formatting(tower_lsp::lsp_types::DocumentFormattingParams {
|
||||
text_document: tower_lsp::lsp_types::TextDocumentIdentifier {
|
||||
uri: "file:///test.kcl".try_into().unwrap(),
|
||||
},
|
||||
options: tower_lsp::lsp_types::FormattingOptions {
|
||||
tab_size: 2,
|
||||
insert_spaces: true,
|
||||
properties: Default::default(),
|
||||
trim_trailing_whitespace: None,
|
||||
insert_final_newline: None,
|
||||
trim_final_newlines: None,
|
||||
},
|
||||
work_done_progress_params: Default::default(),
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
// Check the formatting.
|
||||
assert_eq!(formatting.len(), 1);
|
||||
assert_eq!(
|
||||
formatting[0].range,
|
||||
tower_lsp::lsp_types::Range {
|
||||
start: tower_lsp::lsp_types::Position { line: 0, character: 0 },
|
||||
end: tower_lsp::lsp_types::Position {
|
||||
line: 60,
|
||||
character: 30
|
||||
}
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
formatting[0].new_text,
|
||||
r#"// Ball Bearing
|
||||
// A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads.
|
||||
|
||||
|
||||
// Define constants like ball diameter, inside diameter, overhange length, and thickness
|
||||
const sphereDia = 0.5
|
||||
const insideDia = 1
|
||||
const thickness = 0.25
|
||||
const overHangLength = .4
|
||||
|
||||
// Sketch and revolve the inside bearing piece
|
||||
const insideRevolve = startSketchOn('XZ')
|
||||
|> startProfileAt([insideDia / 2, 0], %)
|
||||
|> line([0, thickness + sphereDia / 2], %)
|
||||
|> line([overHangLength, 0], %)
|
||||
|> line([0, -thickness], %)
|
||||
|> line([-overHangLength + thickness, 0], %)
|
||||
|> line([0, -sphereDia], %)
|
||||
|> line([overHangLength - thickness, 0], %)
|
||||
|> line([0, -thickness], %)
|
||||
|> line([-overHangLength, 0], %)
|
||||
|> close(%)
|
||||
|> revolve({ axis: 'y' }, %)
|
||||
|
||||
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
|
||||
const sphere = startSketchOn('XZ')
|
||||
|> startProfileAt([
|
||||
0.05 + insideDia / 2 + thickness,
|
||||
0 - 0.05
|
||||
], %)
|
||||
|> line([sphereDia - 0.1, 0], %)
|
||||
|> arc({
|
||||
angle_start: 0,
|
||||
angle_end: -180,
|
||||
radius: sphereDia / 2 - 0.05
|
||||
}, %)
|
||||
|> close(%)
|
||||
|> revolve({ axis: 'x' }, %)
|
||||
|> patternCircular3d({
|
||||
axis: [0, 0, 1],
|
||||
center: [0, 0, 0],
|
||||
repetitions: 10,
|
||||
arcDegrees: 360,
|
||||
rotateDuplicates: true
|
||||
}, %)
|
||||
|
||||
// Sketch and revolve the outside bearing
|
||||
const outsideRevolve = startSketchOn('XZ')
|
||||
|> startProfileAt([
|
||||
insideDia / 2 + thickness + sphereDia,
|
||||
0
|
||||
], %)
|
||||
|> line([0, sphereDia / 2], %)
|
||||
|> line([-overHangLength + thickness, 0], %)
|
||||
|> line([0, thickness], %)
|
||||
|> line([overHangLength, 0], %)
|
||||
|> line([0, -2 * thickness - sphereDia], %)
|
||||
|> line([-overHangLength, 0], %)
|
||||
|> line([0, thickness], %)
|
||||
|> line([overHangLength - thickness, 0], %)
|
||||
|> close(%)
|
||||
|> revolve({ axis: 'y' }, %)"#
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_kcl_lsp_rename() {
|
||||
let server = kcl_lsp_server(false).await.unwrap();
|
||||
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 139 KiB |
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 129 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 134 KiB |
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 136 KiB |
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 211 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 114 KiB |
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 115 KiB |
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 134 KiB |
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 137 KiB |
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 111 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 195 KiB |
Before Width: | Height: | Size: 251 KiB After Width: | Height: | Size: 250 KiB |
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB |
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 147 KiB |
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 167 KiB |
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 168 KiB |
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 115 KiB |
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 115 KiB |
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 134 KiB |
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 154 KiB |
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 114 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |