BREAKING: KCL @settings are the source of truth for units (#5808)

This commit is contained in:
Jonathan Tran
2025-03-31 10:56:03 -04:00
committed by GitHub
parent eac5abba79
commit efc8c82d8b
237 changed files with 820 additions and 2146 deletions

View File

@ -812,56 +812,6 @@ impl Backend {
Ok(())
}
pub async fn update_units(
&self,
params: custom_notifications::UpdateUnitsParams,
) -> RpcResult<Option<custom_notifications::UpdateUnitsResponse>> {
{
let mut ctx = self.executor_ctx.write().await;
// Borrow the executor context mutably.
let Some(ref mut executor_ctx) = *ctx else {
self.client
.log_message(MessageType::ERROR, "no executor context set to update units for")
.await;
return Ok(None);
};
self.client
.log_message(MessageType::INFO, format!("update units: {:?}", params))
.await;
if executor_ctx.settings.units == params.units
&& !self.has_diagnostics(params.text_document.uri.as_ref()).await
{
// Return early the units are the same.
return Ok(None);
}
// Set the engine units.
executor_ctx.update_units(params.units);
}
// Lock is dropped here since nested.
// This is IMPORTANT.
let new_params = TextDocumentItem {
uri: params.text_document.uri.clone(),
text: std::mem::take(&mut params.text.to_string()),
version: Default::default(),
language_id: Default::default(),
};
// Force re-execution.
self.inner_on_change(new_params, true).await;
// Check if we have diagnostics.
// If we do we return early, since we failed in some way.
if self.has_diagnostics(params.text_document.uri.as_ref()).await {
return Ok(None);
}
Ok(Some(custom_notifications::UpdateUnitsResponse {}))
}
pub async fn update_can_execute(
&self,
params: custom_notifications::UpdateCanExecuteParams,

View File

@ -42,7 +42,6 @@ pub async fn kcl_lsp_server(execute: bool) -> Result<crate::lsp::kcl::Backend> {
can_execute: Arc::new(tokio::sync::RwLock::new(can_execute)),
is_initialized: Default::default(),
})
.custom_method("kcl/updateUnits", crate::lsp::kcl::Backend::update_units)
.custom_method("kcl/updateCanExecute", crate::lsp::kcl::Backend::update_can_execute)
.finish();

View File

@ -2324,80 +2324,6 @@ async fn kcl_test_kcl_lsp_on_change_update_memory() {
server.executor_ctx().await.clone().unwrap().close().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn kcl_test_kcl_lsp_update_units() {
let server = kcl_lsp_server(true).await.unwrap();
let same_text = r#"fn cube = (pos, scale) => {
sg = startSketchOn(XY)
|> startProfileAt(pos, %)
|> line(end = [0, scale])
|> line(end = [scale, 0])
|> line(end = [0, -scale])
return sg
}
part001 = cube([0,0], 20)
|> close()
|> extrude(length = 20)"#
.to_string();
// 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: same_text.clone(),
},
})
.await;
// Get the tokens.
let tokens = server.token_map.get("file:///test.kcl").unwrap().clone();
assert_eq!(tokens.as_slice().len(), 123);
// Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert_eq!(ast.ast.body.len(), 2);
// Send change file.
server
.did_change(tower_lsp::lsp_types::DidChangeTextDocumentParams {
text_document: tower_lsp::lsp_types::VersionedTextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
version: 1,
},
content_changes: vec![tower_lsp::lsp_types::TextDocumentContentChangeEvent {
range: None,
range_length: None,
text: same_text.clone(),
}],
})
.await;
let units = server.executor_ctx.read().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Update the units.
server
.update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
units: crate::settings::types::UnitLength::M,
text: same_text.clone(),
})
.await
.unwrap();
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::M);
server.executor_ctx().await.clone().unwrap().close().await;
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_kcl_lsp_empty_file_execute_ok() {
let server = kcl_lsp_server(true).await.unwrap();
@ -2733,145 +2659,6 @@ async fn kcl_test_kcl_lsp_code_and_ast_unchanged_but_has_diagnostics_reexecute()
server.executor_ctx().await.clone().unwrap().close().await;
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_kcl_lsp_code_and_ast_units_unchanged_but_has_diagnostics_reexecute_on_unit_change() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
|> close()
|> extrude(length = 3.14)"#;
// 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: code.to_string(),
},
})
.await;
// Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default());
// Assure we have no diagnostics.
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
// Add some fake diagnostics.
server.diagnostics_map.insert(
"file:///test.kcl".to_string(),
vec![tower_lsp::lsp_types::Diagnostic {
range: tower_lsp::lsp_types::Range {
start: tower_lsp::lsp_types::Position { line: 0, character: 0 },
end: tower_lsp::lsp_types::Position { line: 0, character: 0 },
},
message: "fake diagnostic".to_string(),
severity: Some(tower_lsp::lsp_types::DiagnosticSeverity::ERROR),
code: None,
source: None,
related_information: None,
tags: None,
data: None,
code_description: None,
}],
);
// Assure we have one diagnostics.
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 1);
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Update the units to the _same_ units.
server
.update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
units: crate::settings::types::UnitLength::Mm,
text: code.to_string(),
})
.await
.unwrap();
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default());
// Assure we have no diagnostics.
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
server.executor_ctx().await.clone().unwrap().close().await;
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_kcl_lsp_code_and_ast_units_unchanged_but_has_memory_reexecute_on_unit_change() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
|> close()
|> extrude(length = 3.14)"#;
// 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: code.to_string(),
},
})
.await;
// Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default());
// Assure we have no diagnostics.
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Update the units to the _same_ units.
server
.update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
units: crate::settings::types::UnitLength::Mm,
text: code.to_string(),
})
.await
.unwrap();
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default());
// Assure we have no diagnostics.
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
server.executor_ctx().await.clone().unwrap().close().await;
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_kcl_lsp_cant_execute_set() {
let server = kcl_lsp_server(true).await.unwrap();
@ -2903,23 +2690,6 @@ async fn kcl_test_kcl_lsp_cant_execute_set() {
// Assure we have no diagnostics.
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 0);
// Update the units to the _same_ units.
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
server
.update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
units: crate::settings::types::UnitLength::Mm,
text: code.to_string(),
})
.await
.unwrap();
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default());
@ -2936,23 +2706,6 @@ async fn kcl_test_kcl_lsp_cant_execute_set() {
.unwrap();
assert_eq!(server.can_execute().await, false);
// Update the units to the _same_ units.
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
server
.update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
units: crate::settings::types::UnitLength::Mm,
text: code.to_string(),
})
.await
.unwrap();
let units = server.executor_ctx().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
let mut default_hashed = Node::<Program>::default();
default_hashed.compute_digest();
@ -2970,23 +2723,6 @@ async fn kcl_test_kcl_lsp_cant_execute_set() {
.unwrap();
assert_eq!(server.can_execute().await, true);
// Update the units to the _same_ units.
let units = server.executor_ctx.read().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
server
.update_units(crate::lsp::kcl::custom_notifications::UpdateUnitsParams {
text_document: crate::lsp::kcl::custom_notifications::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
units: crate::settings::types::UnitLength::Mm,
text: code.to_string(),
})
.await
.unwrap();
let units = server.executor_ctx.read().await.clone().unwrap().settings.units;
assert_eq!(units, crate::settings::types::UnitLength::Mm);
// Get the ast.
let ast = server.ast_map.get("file:///test.kcl").unwrap().clone();
assert!(ast.ast != Node::<Program>::default());