From 55e8db4131d7ab7cc03df4495c21bd76ff785cf5 Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Tue, 2 Apr 2024 17:38:32 +0800 Subject: [PATCH 1/4] feat: lsp compile unit cache. Add cache of lookup_compile_unit() and watcher for config file(`kcl.yaml` and `kcl.mod`). Signed-off-by: he1pa <18012015693@163.com> --- kclvm/tools/src/LSP/src/find_refs.rs | 10 +++++++- kclvm/tools/src/LSP/src/notification.rs | 9 ++++++- kclvm/tools/src/LSP/src/quick_fix.rs | 1 + kclvm/tools/src/LSP/src/request.rs | 16 ++++++++----- kclvm/tools/src/LSP/src/state.rs | 31 +++++++++++++++++-------- kclvm/tools/src/LSP/src/tests.rs | 10 ++++++++ kclvm/tools/src/LSP/src/util.rs | 21 +++++++++++++++-- 7 files changed, 78 insertions(+), 20 deletions(-) diff --git a/kclvm/tools/src/LSP/src/find_refs.rs b/kclvm/tools/src/LSP/src/find_refs.rs index 6698047d0..2b3472e4e 100644 --- a/kclvm/tools/src/LSP/src/find_refs.rs +++ b/kclvm/tools/src/LSP/src/find_refs.rs @@ -3,7 +3,7 @@ use crate::goto_def::{find_def_with_gs, goto_definition_with_gs}; use crate::to_lsp::lsp_location; use crate::util::{compile_with_params, Params}; -use crate::state::{KCLVfs, KCLWordIndexMap}; +use crate::state::{KCLCompileUnitCache, KCLVfs, KCLWordIndexMap}; use anyhow::Result; use kclvm_ast::ast::Program; use kclvm_error::Position as KCLPos; @@ -24,6 +24,7 @@ pub(crate) fn find_refs Result<(), anyhow::Error>>( gs: &GlobalState, module_cache: Option, scope_cache: Option, + compile_unit_cache: Option, ) -> Result, String> { let def = find_def_with_gs(kcl_pos, gs, true); match def { @@ -42,6 +43,7 @@ pub(crate) fn find_refs Result<(), anyhow::Error>>( logger, module_cache, scope_cache, + compile_unit_cache, )) } else { Err(format!("Invalid file path: {0}", start.filename)) @@ -67,6 +69,7 @@ pub(crate) fn find_refs_from_def Result<(), anyhow::Error>>( logger: F, module_cache: Option, scope_cache: Option, + compile_unit_cache: Option, ) -> Vec { let mut ref_locations = vec![]; for word_index in (*word_index_map.write()).values_mut() { @@ -92,6 +95,7 @@ pub(crate) fn find_refs_from_def Result<(), anyhow::Error>>( module_cache: module_cache.clone(), scope_cache: scope_cache.clone(), vfs: vfs.clone(), + compile_unit_cache: compile_unit_cache.clone(), }) { Ok((prog, _, gs)) => { let ref_pos = kcl_pos(&file_path, ref_loc.range.start); @@ -216,6 +220,7 @@ mod tests { logger, None, None, + None, ), ); } @@ -273,6 +278,7 @@ mod tests { logger, None, None, + None, ), ); } @@ -330,6 +336,7 @@ mod tests { logger, None, None, + None, ), ); } @@ -380,6 +387,7 @@ mod tests { logger, None, None, + None, ), ); } diff --git a/kclvm/tools/src/LSP/src/notification.rs b/kclvm/tools/src/LSP/src/notification.rs index 785dfb610..ac14cc72d 100644 --- a/kclvm/tools/src/LSP/src/notification.rs +++ b/kclvm/tools/src/LSP/src/notification.rs @@ -1,3 +1,4 @@ +use kclvm_config::{modfile::KCL_MOD_FILE, settings::DEFAULT_SETTING_FILE}; use lsp_types::notification::{ Cancel, DidChangeTextDocument, DidChangeWatchedFiles, DidCloseTextDocument, DidOpenTextDocument, DidSaveTextDocument, @@ -141,8 +142,14 @@ impl LanguageServerState { ) -> anyhow::Result<()> { for change in params.changes { let path = from_lsp::abs_path(&change.uri)?; - self.loader.handle.invalidate(path); + self.loader.handle.invalidate(path.clone()); + if KCL_CONFIG_FILE.contains(&path.file_name().unwrap().to_str().unwrap()) { + self.compile_unit_cache.write().clear(); + } } + Ok(()) } } + +const KCL_CONFIG_FILE: [&'static str; 2] = [DEFAULT_SETTING_FILE, KCL_MOD_FILE]; diff --git a/kclvm/tools/src/LSP/src/quick_fix.rs b/kclvm/tools/src/LSP/src/quick_fix.rs index e2fe284a6..ea2e5cf28 100644 --- a/kclvm/tools/src/LSP/src/quick_fix.rs +++ b/kclvm/tools/src/LSP/src/quick_fix.rs @@ -155,6 +155,7 @@ mod tests { module_cache: None, scope_cache: None, vfs: Some(KCLVfs::default()), + compile_unit_cache: None, }) .unwrap(); diff --git a/kclvm/tools/src/LSP/src/request.rs b/kclvm/tools/src/LSP/src/request.rs index b34e3858b..7dca0e19b 100644 --- a/kclvm/tools/src/LSP/src/request.rs +++ b/kclvm/tools/src/LSP/src/request.rs @@ -267,7 +267,8 @@ pub(crate) fn handle_reference( let pos = kcl_pos(&file, params.text_document_position.position); let log = |msg: String| log_message(msg, &sender); let module_cache = snapshot.module_cache.clone(); - let scope_cache = snapshot.scope_cache.clone(); + let _scope_cache = snapshot.scope_cache.clone(); + let compile_unit_cache = snapshot.compile_unit_cache.clone(); match find_refs( &db.prog, &pos, @@ -276,8 +277,9 @@ pub(crate) fn handle_reference( Some(snapshot.vfs.clone()), log, &db.gs, - module_cache, - scope_cache, + Some(module_cache), + None, + Some(compile_unit_cache), ) { core::result::Result::Ok(locations) => Ok(Some(locations)), Err(msg) => { @@ -319,9 +321,10 @@ pub(crate) fn handle_completion( match compile_with_params(Params { file: file.clone(), - module_cache: snapshot.module_cache, + module_cache: Some(Arc::clone(&snapshot.module_cache)), scope_cache: None, vfs: Some(snapshot.vfs.clone()), + compile_unit_cache: Some(Arc::clone(&snapshot.compile_unit_cache)), }) { Ok((prog, diags, gs)) => Arc::new(AnalysisDatabase { prog, @@ -416,8 +419,9 @@ pub(crate) fn handle_rename( Some(snapshot.vfs.clone()), log, &db.gs, - snapshot.module_cache.clone(), - snapshot.scope_cache.clone(), + Some(snapshot.module_cache), + Some(snapshot.scope_cache), + Some(snapshot.compile_unit_cache), ); match references { Result::Ok(locations) => { diff --git a/kclvm/tools/src/LSP/src/state.rs b/kclvm/tools/src/LSP/src/state.rs index 65e1b8e61..04a491c06 100644 --- a/kclvm/tools/src/LSP/src/state.rs +++ b/kclvm/tools/src/LSP/src/state.rs @@ -7,7 +7,7 @@ use crate::util::{compile_with_params, get_file_name, to_json, Params}; use crate::word_index::build_word_index; use anyhow::Result; use crossbeam_channel::{select, unbounded, Receiver, Sender}; -use kclvm_parser::KCLModuleCache; +use kclvm_parser::{KCLModuleCache, LoadProgramOptions}; use kclvm_sema::resolver::scope::{CachedScope, KCLScopeCache}; use lsp_server::{ReqQueue, Request, Response}; use lsp_types::Url; @@ -48,6 +48,8 @@ pub(crate) struct Handle { pub(crate) type KCLVfs = Arc>; pub(crate) type KCLWordIndexMap = Arc>>>>; +pub(crate) type KCLCompileUnitCache = + Arc, Option)>>>; /// State for the language server pub(crate) struct LanguageServerState { @@ -88,10 +90,13 @@ pub(crate) struct LanguageServerState { pub word_index_map: KCLWordIndexMap, /// KCL parse cache - pub module_cache: Option, + pub module_cache: KCLModuleCache, /// KCL resolver cache - pub scope_cache: Option, + pub scope_cache: KCLScopeCache, + + /// KCL compile unit cache cache + pub compile_unit_cache: KCLCompileUnitCache, } /// A snapshot of the state of the language server @@ -106,9 +111,11 @@ pub(crate) struct LanguageServerSnapshot { /// The word index map pub word_index_map: KCLWordIndexMap, /// KCL parse cache - pub module_cache: Option, + pub module_cache: KCLModuleCache, /// KCL resolver cache - pub scope_cache: Option, + pub scope_cache: KCLScopeCache, + /// KCL compile unit cache cache + pub compile_unit_cache: KCLCompileUnitCache, } #[allow(unused)] @@ -141,8 +148,9 @@ impl LanguageServerState { opened_files: Arc::new(RwLock::new(HashMap::new())), word_index_map: Arc::new(RwLock::new(HashMap::new())), loader, - module_cache: Some(KCLModuleCache::default()), - scope_cache: Some(Arc::new(Mutex::new(CachedScope::default()))), + module_cache: KCLModuleCache::default(), + scope_cache: Arc::new(Mutex::new(CachedScope::default())), + compile_unit_cache: Arc::new(RwLock::new(HashMap::default())), }; let word_index_map = state.word_index_map.clone(); @@ -228,8 +236,9 @@ impl LanguageServerState { self.thread_pool.execute({ let mut snapshot = self.snapshot(); let sender = self.task_sender.clone(); - let module_cache = self.module_cache.clone(); - let scope_cache = self.scope_cache.clone(); + let module_cache = Arc::clone(&self.module_cache); + let scope_cache = Arc::clone(&self.scope_cache); + let compile_unit_cache = Arc::clone(&self.compile_unit_cache); move || match url(&snapshot, file.file_id) { Ok(uri) => { let version = @@ -237,9 +246,10 @@ impl LanguageServerState { let mut db = snapshot.db.write(); match compile_with_params(Params { file: filename.clone(), - module_cache, + module_cache: Some(module_cache), scope_cache: None, vfs: Some(snapshot.vfs), + compile_unit_cache: Some(compile_unit_cache), }) { Ok((prog, diags, gs)) => { let current_version = snapshot @@ -374,6 +384,7 @@ impl LanguageServerState { word_index_map: self.word_index_map.clone(), module_cache: self.module_cache.clone(), scope_cache: self.scope_cache.clone(), + compile_unit_cache: self.compile_unit_cache.clone(), } } diff --git a/kclvm/tools/src/LSP/src/tests.rs b/kclvm/tools/src/LSP/src/tests.rs index 7f8439514..7af033c71 100644 --- a/kclvm/tools/src/LSP/src/tests.rs +++ b/kclvm/tools/src/LSP/src/tests.rs @@ -71,6 +71,7 @@ use crate::from_lsp::file_path_from_url; use crate::goto_def::goto_definition_with_gs; use crate::hover::hover; use crate::main_loop::main_loop; +use crate::state::KCLCompileUnitCache; use crate::state::KCLVfs; use crate::to_lsp::kcl_diag_to_lsp_diags; use crate::util::to_json; @@ -125,6 +126,7 @@ pub(crate) fn compile_test_file( module_cache: Some(KCLModuleCache::default()), scope_cache: Some(KCLScopeCache::default()), vfs: Some(KCLVfs::default()), + compile_unit_cache: Some(KCLCompileUnitCache::default()), }) .unwrap(); (file, program, diags, gs) @@ -286,6 +288,7 @@ fn diagnostics_test() { module_cache: None, scope_cache: None, vfs: Some(KCLVfs::default()), + compile_unit_cache: Some(KCLCompileUnitCache::default()), }) .unwrap(); @@ -472,6 +475,7 @@ fn complete_import_external_file_test() { module_cache: None, scope_cache: None, vfs: Some(KCLVfs::default()), + compile_unit_cache: Some(KCLCompileUnitCache::default()), }) .unwrap(); @@ -529,6 +533,7 @@ fn goto_import_external_file_test() { module_cache: None, scope_cache: None, vfs: Some(KCLVfs::default()), + compile_unit_cache: Some(KCLCompileUnitCache::default()), }) .unwrap(); @@ -1264,6 +1269,7 @@ fn konfig_goto_def_test_base() { module_cache: None, scope_cache: None, vfs: Some(KCLVfs::default()), + compile_unit_cache: Some(KCLCompileUnitCache::default()), }) .unwrap(); @@ -1355,6 +1361,7 @@ fn konfig_goto_def_test_main() { module_cache: None, scope_cache: None, vfs: Some(KCLVfs::default()), + compile_unit_cache: Some(KCLCompileUnitCache::default()), }) .unwrap(); @@ -1418,6 +1425,7 @@ fn konfig_completion_test_main() { module_cache: None, scope_cache: None, vfs: Some(KCLVfs::default()), + compile_unit_cache: Some(KCLCompileUnitCache::default()), }) .unwrap(); @@ -1527,6 +1535,7 @@ fn konfig_hover_test_main() { module_cache: None, scope_cache: None, vfs: Some(KCLVfs::default()), + compile_unit_cache: Some(KCLCompileUnitCache::default()), }) .unwrap(); @@ -1952,6 +1961,7 @@ fn compile_unit_test() { module_cache: None, scope_cache: None, vfs: Some(KCLVfs::default()), + compile_unit_cache: Some(KCLCompileUnitCache::default()), }) .unwrap(); // b.k is not contained in kcl.yaml but need to be contained in main pkg diff --git a/kclvm/tools/src/LSP/src/util.rs b/kclvm/tools/src/LSP/src/util.rs index 7b4a21e5b..ea9b51e31 100644 --- a/kclvm/tools/src/LSP/src/util.rs +++ b/kclvm/tools/src/LSP/src/util.rs @@ -19,7 +19,7 @@ use kclvm_sema::resolver::resolve_program_with_opts; use kclvm_sema::resolver::scope::KCLScopeCache; use crate::from_lsp; -use crate::state::KCLVfs; +use crate::state::{KCLCompileUnitCache, KCLVfs}; use lsp_types::Url; use parking_lot::RwLockReadGuard; use ra_ap_vfs::{FileId, Vfs}; @@ -64,13 +64,30 @@ pub(crate) struct Params { pub module_cache: Option, pub scope_cache: Option, pub vfs: Option, + pub compile_unit_cache: Option, } pub(crate) fn compile_with_params( params: Params, ) -> anyhow::Result<(Program, IndexSet, GlobalState)> { // Lookup compile unit (kcl.mod or kcl.yaml) from the entry file. - let (mut files, opt) = lookup_compile_unit(¶ms.file, true); + let (mut files, opt) = match ¶ms.compile_unit_cache { + Some(cache) => { + let map = cache.read(); + match map.get(¶ms.file) { + Some(compile_unit) => compile_unit.clone(), + None => lookup_compile_unit(¶ms.file, true), + } + } + None => lookup_compile_unit(¶ms.file, true), + }; + + if let Some(cache) = params.compile_unit_cache { + cache + .write() + .insert(params.file.clone(), (files.clone(), opt.clone())); + } + if !files.contains(¶ms.file) { files.push(params.file.clone()); } From 836ee48c8d6a758408666298306187db1bfff594 Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Wed, 3 Apr 2024 15:49:41 +0800 Subject: [PATCH 2/4] restore resolver cache Signed-off-by: he1pa <18012015693@163.com> --- kclvm/tools/src/LSP/src/request.rs | 35 +----------------------------- kclvm/tools/src/LSP/src/state.rs | 2 +- 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/kclvm/tools/src/LSP/src/request.rs b/kclvm/tools/src/LSP/src/request.rs index 7dca0e19b..61dcf6f8d 100644 --- a/kclvm/tools/src/LSP/src/request.rs +++ b/kclvm/tools/src/LSP/src/request.rs @@ -22,7 +22,6 @@ use crate::{ hover, quick_fix, semantic_token::semantic_tokens_full, state::{log_message, LanguageServerSnapshot, LanguageServerState, Task}, - util::{compile_with_params, Params}, }; impl LanguageServerState { @@ -307,39 +306,7 @@ pub(crate) fn handle_completion( .and_then(|ctx| ctx.trigger_character) .and_then(|s| s.chars().next()); - let db = - match completion_trigger_character { - // Some trigger characters need to re-compile - Some(ch) => match ch { - '=' | ':' => { - let file_id = snapshot.vfs.read().file_id(&path.clone().into()).ok_or( - anyhow::anyhow!(LSPError::FileIdNotFound(path.clone().into())), - )?; - let version = *snapshot.opened_files.read().get(&file_id).ok_or_else(|| { - anyhow::anyhow!(LSPError::DocumentVersionNotFound(path.clone().into())) - })?; - - match compile_with_params(Params { - file: file.clone(), - module_cache: Some(Arc::clone(&snapshot.module_cache)), - scope_cache: None, - vfs: Some(snapshot.vfs.clone()), - compile_unit_cache: Some(Arc::clone(&snapshot.compile_unit_cache)), - }) { - Ok((prog, diags, gs)) => Arc::new(AnalysisDatabase { - prog, - diags, - gs, - version, - }), - Err(_) => return Ok(None), - } - } - _ => snapshot.get_db(&path.clone().into())?, - }, - - None => snapshot.get_db(&path.clone().into())?, - }; + let db = snapshot.get_db(&path.clone().into())?; let res = completion(completion_trigger_character, &db.prog, &kcl_pos, &db.gs); diff --git a/kclvm/tools/src/LSP/src/state.rs b/kclvm/tools/src/LSP/src/state.rs index 04a491c06..7b87633d4 100644 --- a/kclvm/tools/src/LSP/src/state.rs +++ b/kclvm/tools/src/LSP/src/state.rs @@ -247,7 +247,7 @@ impl LanguageServerState { match compile_with_params(Params { file: filename.clone(), module_cache: Some(module_cache), - scope_cache: None, + scope_cache: Some(scope_cache), vfs: Some(snapshot.vfs), compile_unit_cache: Some(compile_unit_cache), }) { From def7169cf252e7c03c7450513d274a0f2c8d5dbd Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Wed, 3 Apr 2024 17:13:44 +0800 Subject: [PATCH 3/4] test: add compile unit cache e2e test Signed-off-by: he1pa <18012015693@163.com> --- kclvm/tools/src/LSP/src/state.rs | 7 +- kclvm/tools/src/LSP/src/tests.rs | 124 +++++++++++++++++++++++++++++++ kclvm/tools/src/LSP/src/util.rs | 27 ++++--- 3 files changed, 144 insertions(+), 14 deletions(-) diff --git a/kclvm/tools/src/LSP/src/state.rs b/kclvm/tools/src/LSP/src/state.rs index 7b87633d4..8d9b26655 100644 --- a/kclvm/tools/src/LSP/src/state.rs +++ b/kclvm/tools/src/LSP/src/state.rs @@ -8,7 +8,7 @@ use crate::word_index::build_word_index; use anyhow::Result; use crossbeam_channel::{select, unbounded, Receiver, Sender}; use kclvm_parser::{KCLModuleCache, LoadProgramOptions}; -use kclvm_sema::resolver::scope::{CachedScope, KCLScopeCache}; +use kclvm_sema::resolver::scope::KCLScopeCache; use lsp_server::{ReqQueue, Request, Response}; use lsp_types::Url; use lsp_types::{ @@ -18,7 +18,6 @@ use lsp_types::{ use parking_lot::RwLock; use ra_ap_vfs::{ChangeKind, ChangedFile, FileId, Vfs}; use std::collections::HashMap; -use std::sync::Mutex; use std::thread; use std::time::Duration; use std::{sync::Arc, time::Instant}; @@ -149,8 +148,8 @@ impl LanguageServerState { word_index_map: Arc::new(RwLock::new(HashMap::new())), loader, module_cache: KCLModuleCache::default(), - scope_cache: Arc::new(Mutex::new(CachedScope::default())), - compile_unit_cache: Arc::new(RwLock::new(HashMap::default())), + scope_cache: KCLScopeCache::default(), + compile_unit_cache: KCLCompileUnitCache::default(), }; let word_index_map = state.word_index_map.clone(); diff --git a/kclvm/tools/src/LSP/src/tests.rs b/kclvm/tools/src/LSP/src/tests.rs index 7af033c71..cb2912c9c 100644 --- a/kclvm/tools/src/LSP/src/tests.rs +++ b/kclvm/tools/src/LSP/src/tests.rs @@ -17,6 +17,8 @@ use lsp_types::CompletionResponse; use lsp_types::CompletionTriggerKind; use lsp_types::DocumentFormattingParams; use lsp_types::DocumentSymbolParams; +use lsp_types::FileChangeType; +use lsp_types::FileEvent; use lsp_types::GotoDefinitionParams; use lsp_types::GotoDefinitionResponse; use lsp_types::Hover; @@ -45,8 +47,10 @@ use std::path::Path; use std::path::PathBuf; use std::process::Command; +use std::sync::Arc; use std::thread; use std::time::Duration; +use std::time::Instant; use kclvm_ast::ast::Program; use kclvm_error::Diagnostic as KCLDiagnostic; @@ -74,6 +78,7 @@ use crate::main_loop::main_loop; use crate::state::KCLCompileUnitCache; use crate::state::KCLVfs; use crate::to_lsp::kcl_diag_to_lsp_diags; +use crate::util::compile_unit_with_cache; use crate::util::to_json; use crate::util::{apply_document_changes, compile_with_params, Params}; @@ -882,6 +887,125 @@ fn cancel_test() { assert!(server.receive_response(id.into()).is_none()); } +#[test] +fn compile_unit_cache_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + path.push("src/test_data/compile_unit/b.k"); + + let path = path.to_str().unwrap(); + + let compile_unit_cache = KCLCompileUnitCache::default(); + let start = Instant::now(); + let _ = compile_unit_with_cache(&Some(Arc::clone(&compile_unit_cache)), &path.to_string()); + let first_compile_time = start.elapsed(); + + let start = Instant::now(); + let _ = compile_unit_with_cache(&Some(compile_unit_cache), &path.to_string()); + let second_compile_time = start.elapsed(); + + assert!(first_compile_time > second_compile_time); +} + +#[test] +fn compile_unit_cache_e2e_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + let mut kcl_yaml = root.clone(); + path.push("src/test_data/compile_unit/b.k"); + kcl_yaml.push("src/test_data/compile_unit/kcl.yaml"); + + let path = path.to_str().unwrap(); + + let kcl_yaml = kcl_yaml.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/documentSymbol".to_string(), + DocumentSymbolParams { + text_document: TextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }, + ); + + // First time send request and wait for it's response + let start = Instant::now(); + let _ = server.send_and_receive(r); + let first_compile_time = start.elapsed(); + + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); + + // Second time send request and wait for it's response + let r: Request = Request::new( + id.into(), + "textDocument/documentSymbol".to_string(), + DocumentSymbolParams { + text_document: TextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }, + ); + + let start = Instant::now(); + let _ = server.send_and_receive(r); + let second_compile_time = start.elapsed(); + assert!(first_compile_time > second_compile_time); + + // Mock edit config file, clear cache + server.notification::( + lsp_types::DidChangeWatchedFilesParams { + changes: vec![FileEvent { + uri: Url::from_file_path(kcl_yaml).unwrap(), + typ: FileChangeType::CHANGED, + }], + }, + ); + + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); + + // Third time send request and wait for it's response + let r: Request = Request::new( + id.into(), + "textDocument/documentSymbol".to_string(), + DocumentSymbolParams { + text_document: TextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }, + ); + + let start = Instant::now(); + let _ = server.send_and_receive(r); + let third_compile_time = start.elapsed(); + assert!(third_compile_time > second_compile_time); +} + #[test] fn goto_def_test() { let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); diff --git a/kclvm/tools/src/LSP/src/util.rs b/kclvm/tools/src/LSP/src/util.rs index ea9b51e31..f913cbdc7 100644 --- a/kclvm/tools/src/LSP/src/util.rs +++ b/kclvm/tools/src/LSP/src/util.rs @@ -10,7 +10,7 @@ use kclvm_driver::lookup_compile_unit; use kclvm_error::Diagnostic; use kclvm_error::Position as KCLPos; use kclvm_parser::entry::get_dir_files; -use kclvm_parser::{load_program, KCLModuleCache, ParseSessionRef}; +use kclvm_parser::{load_program, KCLModuleCache, LoadProgramOptions, ParseSessionRef}; use kclvm_sema::advanced_resolver::AdvancedResolver; use kclvm_sema::core::global_state::GlobalState; use kclvm_sema::namer::Namer; @@ -67,20 +67,27 @@ pub(crate) struct Params { pub compile_unit_cache: Option, } -pub(crate) fn compile_with_params( - params: Params, -) -> anyhow::Result<(Program, IndexSet, GlobalState)> { - // Lookup compile unit (kcl.mod or kcl.yaml) from the entry file. - let (mut files, opt) = match ¶ms.compile_unit_cache { +pub(crate) fn compile_unit_with_cache( + compile_unit_cache: &Option, + file: &String, +) -> (Vec, Option) { + match compile_unit_cache { Some(cache) => { let map = cache.read(); - match map.get(¶ms.file) { + match map.get(file) { Some(compile_unit) => compile_unit.clone(), - None => lookup_compile_unit(¶ms.file, true), + None => lookup_compile_unit(file, true), } } - None => lookup_compile_unit(¶ms.file, true), - }; + None => lookup_compile_unit(file, true), + } +} + +pub(crate) fn compile_with_params( + params: Params, +) -> anyhow::Result<(Program, IndexSet, GlobalState)> { + // Lookup compile unit (kcl.mod or kcl.yaml) from the entry file. + let (mut files, opt) = compile_unit_with_cache(¶ms.compile_unit_cache, ¶ms.file); if let Some(cache) = params.compile_unit_cache { cache From 9fba48952ad17a38ecbbf82bf7147add416e5e5c Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Sun, 7 Apr 2024 10:53:49 +0800 Subject: [PATCH 4/4] chore: s/&String/&str in function param Signed-off-by: he1pa <18012015693@163.com> --- kclvm/tools/src/LSP/src/util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kclvm/tools/src/LSP/src/util.rs b/kclvm/tools/src/LSP/src/util.rs index f913cbdc7..d7d997cc1 100644 --- a/kclvm/tools/src/LSP/src/util.rs +++ b/kclvm/tools/src/LSP/src/util.rs @@ -69,7 +69,7 @@ pub(crate) struct Params { pub(crate) fn compile_unit_with_cache( compile_unit_cache: &Option, - file: &String, + file: &str, ) -> (Vec, Option) { match compile_unit_cache { Some(cache) => {