From 495338925b541ceed91b173b7ead67e1864e26bf Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Wed, 3 Jul 2024 19:13:40 +0800 Subject: [PATCH 1/2] add document version check in newline complete Signed-off-by: he1pa <18012015693@163.com> --- kclvm/tools/src/LSP/src/notification.rs | 2 +- kclvm/tools/src/LSP/src/request.rs | 20 +++-- .../newline_with_version.k | 6 ++ kclvm/tools/src/LSP/src/tests.rs | 87 +++++++++++++++++++ 4 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 kclvm/tools/src/LSP/src/test_data/completion_test/newline/newline_with_version/newline_with_version.k diff --git a/kclvm/tools/src/LSP/src/notification.rs b/kclvm/tools/src/LSP/src/notification.rs index d553022fc..beb71658e 100644 --- a/kclvm/tools/src/LSP/src/notification.rs +++ b/kclvm/tools/src/LSP/src/notification.rs @@ -97,7 +97,7 @@ impl LanguageServerState { let old_text = text.clone(); apply_document_changes(&mut text, content_changes); vfs.set_file_contents(path.into(), Some(text.clone().into_bytes())); - + self.opened_files.write().insert(file_id, text_document.version); // Update word index let old_word_index = build_word_index_with_content(&old_text, &text_document.uri, true); let new_word_index = build_word_index_with_content(&text, &text_document.uri, true); diff --git a/kclvm/tools/src/LSP/src/request.rs b/kclvm/tools/src/LSP/src/request.rs index 7afde3ccd..88ea23688 100644 --- a/kclvm/tools/src/LSP/src/request.rs +++ b/kclvm/tools/src/LSP/src/request.rs @@ -151,7 +151,6 @@ impl LanguageServerSnapshot { let current_version = *self.opened_files.read().get(&file_id).ok_or_else(|| { anyhow::anyhow!(LSPError::DocumentVersionNotFound(path.clone().into())) })?; - Ok(db_version == current_version) } } @@ -306,16 +305,25 @@ pub(crate) fn handle_completion( return Ok(None); } - let kcl_pos = kcl_pos(&file, params.text_document_position.position); + let db = match snapshot.get_db(&path.clone().into()) { + Ok(db) => db, + Err(_) => return Ok(None), + }; + let completion_trigger_character = params .context .and_then(|ctx| ctx.trigger_character) .and_then(|s| s.chars().next()); - let db = match snapshot.get_db(&path.clone().into()) { - Ok(db) => db, - Err(_) => return Ok(None), - }; + if let Some(c) = completion_trigger_character { + if let '\n' = c { + if !snapshot.verify_request_version(db.version, &path)? { + return Err(anyhow!(LSPError::Retry)); + } + } + } + + let kcl_pos = kcl_pos(&file, params.text_document_position.position); let metadata = snapshot .entry_cache diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/newline/newline_with_version/newline_with_version.k b/kclvm/tools/src/LSP/src/test_data/completion_test/newline/newline_with_version/newline_with_version.k new file mode 100644 index 000000000..cd37b7c40 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/newline/newline_with_version/newline_with_version.k @@ -0,0 +1,6 @@ +schema Name: + name: str + +name1 = "" + +name: Name{} \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/tests.rs b/kclvm/tools/src/LSP/src/tests.rs index e7f4a0fd0..e4cb70f41 100644 --- a/kclvm/tools/src/LSP/src/tests.rs +++ b/kclvm/tools/src/LSP/src/tests.rs @@ -1172,6 +1172,93 @@ fn complete_test() { ) } +#[test] +fn complete_with_version_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + + path.push("src/test_data/completion_test/newline/newline_with_version/newline_with_version.k"); + + let path = path.to_str().unwrap(); + let src = std::fs::read_to_string(path).unwrap(); + let server = Project {}.server(InitializeParams::default()); + + // Mock open file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: Url::from_file_path(path).unwrap(), + language_id: "KCL".to_string(), + version: 0, + text: src, + }, + }, + ); + + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); + + let r: Request = Request::new( + id.into(), + "textDocument/completion".to_string(), + CompletionParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + }, + position: Position::new(6, 4), + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + context: Some(CompletionContext { + trigger_kind: CompletionTriggerKind::TRIGGER_CHARACTER, + trigger_character: Some("\n".to_string()), + }), + }, + ); + + let id = r.id.clone(); + server.client.sender.send(r.into()).unwrap(); + + server.notification::( + lsp_types::DidChangeTextDocumentParams { + text_document: lsp_types::VersionedTextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + version: 1, + }, + content_changes: vec![TextDocumentContentChangeEvent { + range: None, + range_length: None, + text: "schema Name:\n name: str\n\nname1 = \"\"\n\nname: Name{\n \n}" + .to_string(), + }], + }, + ); + + while let Some(msg) = server.recv() { + match msg { + Message::Request(req) => { + panic!("did not expect a request as a response to a request: {req:?}") + } + Message::Notification(_) => (), + Message::Response(res) => { + assert_eq!(res.id, id); + assert_eq!( + res.result.unwrap(), + to_json(CompletionResponse::Array(vec![CompletionItem { + label: "name".to_string(), + kind: Some(CompletionItemKind::FIELD), + detail: Some("name: str".to_string()), + ..Default::default() + },])) + .unwrap() + ); + break; + } + } + } +} + #[test] fn hover_test() { let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); From 38efa639adc6e9473458532bc7bb81cb6380e540 Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Thu, 4 Jul 2024 10:44:54 +0800 Subject: [PATCH 2/2] fmt code Signed-off-by: he1pa <18012015693@163.com> --- kclvm/tools/src/LSP/src/notification.rs | 4 +++- kclvm/tools/src/LSP/src/request.rs | 8 +++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kclvm/tools/src/LSP/src/notification.rs b/kclvm/tools/src/LSP/src/notification.rs index beb71658e..d7be1b5a5 100644 --- a/kclvm/tools/src/LSP/src/notification.rs +++ b/kclvm/tools/src/LSP/src/notification.rs @@ -97,7 +97,9 @@ impl LanguageServerState { let old_text = text.clone(); apply_document_changes(&mut text, content_changes); vfs.set_file_contents(path.into(), Some(text.clone().into_bytes())); - self.opened_files.write().insert(file_id, text_document.version); + self.opened_files + .write() + .insert(file_id, text_document.version); // Update word index let old_word_index = build_word_index_with_content(&old_text, &text_document.uri, true); let new_word_index = build_word_index_with_content(&text, &text_document.uri, true); diff --git a/kclvm/tools/src/LSP/src/request.rs b/kclvm/tools/src/LSP/src/request.rs index 88ea23688..f5b36ba31 100644 --- a/kclvm/tools/src/LSP/src/request.rs +++ b/kclvm/tools/src/LSP/src/request.rs @@ -315,11 +315,9 @@ pub(crate) fn handle_completion( .and_then(|ctx| ctx.trigger_character) .and_then(|s| s.chars().next()); - if let Some(c) = completion_trigger_character { - if let '\n' = c { - if !snapshot.verify_request_version(db.version, &path)? { - return Err(anyhow!(LSPError::Retry)); - } + if matches!(completion_trigger_character, Some('\n')) { + if !snapshot.verify_request_version(db.version, &path)? { + return Err(anyhow!(LSPError::Retry)); } }